天天看点

【二次开发】CityMaker交互操作——拾取鼠标拾取

**

鼠标拾取

**

一、 鼠标拾取原理

鼠标可以通过点选和框选的方式实现拾取渲染对象,并支持通过按住Ctrl键实现多选。 IRenderControl的MouseSelectObjectMask属性可以设置哪些类型的对象参与鼠标拾取,注意是按对象的类型过滤。如果想设置具体某个对象是否参与鼠标拾取可以通过IRenderable对象的MouseSelectMask属性来设置。鼠标可以拾取的对象有多种类型,并分别对应于不同的拾取对象类型,如地理要素图层gviObjectFeatureLayer的鼠标拾取对象为IFeatureLayerPickResult。

参与鼠标拾取的对象类型gviMouseSelectObjectMask

枚举值:

gviSelectNone  	       空对象,当定义的某些节点,并不希望进行绘制绘制求交等操作可以指定该类型 

  gviSelectFeatureLayer    场景数据(默认值) 

  gviSelectTerrain 		   地形数据 

  gviSelectReferencePlane  基准面 

  gviSelectTerrainHole     地形挖洞拾取 

  gviSelectTileLayer       3DTileLayer 

  gviSelectLable  	       标注(TableLable、Label共用此项) 

  gviSelectParticleEffect  粒子系统(ParticleEffect、ComplexParticleEffect共用此项) 

  gviSelectRenderGeometry  渲染对象. 

  gviSelectSkinnedMesh     骨骼动画 

  gviSelectTileHole        三维瓦片挖洞 

  gviSelectOverlayLabel    界面悬浮标注. 

  gviSelectTerrainObject   地形对象. 

  gviSelectTerrainVideo    贴地视频(TerrainVideo, Viewshed共用此项)
  注意:不能单独只拾取TerrainVideo或Viewshed,必须允许拾取到底下衬的瓦片或地形或FeatureLayer,才能反算出TerrainVideo或Viewshed是否被拾取。 

  gviSelectObjectOnEverything  所有表面附着对象

  gviSelectAll  		   所有对象 
           

鼠标拾取可通过3步实现。

1)设置鼠标交互模式为gviInteractSelect,并设置鼠标拾取触发方式MouseSelectMode(Click、Drag)

2)注册控件拾取事件(点选或框选事件)并设置鼠标拾取对象类型过滤器MouseSelectObjectMask

3)实现拾取事件(点选或框选)

通过HighlightFeature可以将拾取到的对象进行高亮显示,通过查询可取到拾取对象的属性信息等,效果如下图

【二次开发】CityMaker交互操作——拾取鼠标拾取

二、 实现代码

1. .net代码

/*注册点击事件*/
    private void RegisterClientEvent(AxRenderControl rendercontrol)
    {
   	    //设置交互模式为InterSelect
        rendercontrol.InteractMode = gviInteractMode.gviInteractSelect;
        //设置鼠标拾取对象类型为 所有对象 
        rendercontrol.MouseSelectObjectMask = gviMouseSelectObjectMask.gviSelectAll;
        // 设置鼠标拾取触发方式为Click或Drag
        rendercontrol.MouseSelectMode = gviMouseSelectMode.gviMouseSelectClick | gviMouseSelectMode.gviMouseSelectDrag; 
        // 注册控件拾取事件,点选
        rendercontrol.RcMouseClickSelect += new Gvitech.CityMaker.Controls._IRenderControlEvents_RcMouseClickSelectEventHandler(axRenderControl1_RcMouseClickSelect);
        // 注册控件框选事件 
        rendercontrol.RcMouseDragSelect += new Gvitech.CityMaker.Controls._IRenderControlEvents_RcMouseDragSelectEventHandler(axRenderControl1_RcMouseDragSelect); 
    }
           
/*框选事件*/
    void axRenderControl1_RcMouseDragSelect(object sender, _IRenderControlEvents_RcMouseDragSelectEvent e)
    {
        IPickResultCollection prc = e.pickResults;//框选范围内的所有集合
        if (prc == null)
            return;
        if (e.mask != gviModKeyMask.gviModKeyCtrl)  //判断是否Control键按下
          {}
        if (prc != null)
        {
            for (int i = 0; i < prc.Count; i++)
            {
                IPickResult pr = prc[i];
                switch (pr.Type)
                {
                    case gviObjectType.gviObjectFeatureLayer:
                        IFeatureLayerPickResult flpr = pr as IFeatureLayerPickResult;
                        int fid = flpr.FeatureId;
                        IFeatureLayer fl = flpr.FeatureLayer;
                        fl.HighlightFeature(fid, 0xffff0000);//高亮拾取对象  
                        MessageBox.Show(fid.ToString());
                        break;
                    case gviObjectType.gviObjectLabel:
                        ILabelPickResult labelpr = pr as ILabelPickResult;
                        ILabel label = labelpr.Label;
                        MessageBox.Show("拾取到标签Label");
                        break;
                    case gviObjectType.gviObjectOverlayLabel:
                        IOverlayLabelPickResult overlpr = pr as IOverlayLabelPickResult;
                        IOverlayLabel ovelabel = overlpr.OverlayLabel;
                        MessageBox.Show("拾取到OverlayLabel");
                        break;
                    case gviObjectType.gviObject3DTileLayer:
                        I3DTileLayerPickResult tilepr = pr as I3DTileLayerPickResult;
                        I3DTileLayer tilely = tilepr.TileLayer;
                        MessageBox.Show("拾取到瓦片对象");
                        break;
                    case gviObjectType.gviObjectComplexParticleEffect:
                        IComplexParticleEffectPickResult pepr = pr as IComplexParticleEffectPickResult;
                        IComplexParticleEffect comparic = pepr.ComplexParticleEffect;
                        MessageBox.Show("拾取到复杂粒子特效对象");
                        break;
                    case gviObjectType.gviObjectParticleEffect:
                        IParticleEffectPickResult partipr = pr as IParticleEffectPickResult;
                        IParticleEffect particle = partipr.ParticleEffect;
                        MessageBox.Show("拾取到粒子效果对象");
                        break;
                    case gviObjectType.gviObjectReferencePlane:
                        IReferencePlanePickResult refpr = pr as IReferencePlanePickResult;
                        IReferencePlane refernplane = refpr.ReferencePlane;
                        MessageBox.Show("拾取到基准平面对象");
                        break;
                    case gviObjectType.gviObjectRenderArrow:
                        IRenderArrowPickResult renderpr = pr as IRenderArrowPickResult;
                        IRenderArrow arrow = renderpr.RenderArrow;
                        MessageBox.Show("拾取到箭头RenderArrow");
                        break;
                    case gviObjectType.gviObjectRenderModelPoint:
                        IRenderModelPointPickResult rendermppr = pr as IRenderModelPointPickResult;
                        IRenderModelPoint rendermp = rendermppr.ModelPoint;
                        MessageBox.Show("拾取到模型渲染对象");
                        break;
                    case gviObjectType.gviObjectRenderMultiPoint:
                        IRenderMultiPointPickResult multipr = pr as IRenderMultiPointPickResult;
                        IRenderMultiPoint multipoint = multipr.MultiPoint;
                        MessageBox.Show("拾取到MultiPoint模型渲染对象");
                        break;
                    case gviObjectType.gviObjectRenderMultiPolygon:
                        IRenderMultiPolygonPickResult multipolygonpr = pr as IRenderMultiPolygonPickResult;
                        IRenderMultiPolygon multipolygon = multipolygonpr.MultiPolygon;
                        MessageBox.Show("拾取到multiPolygon模型渲染对象");
                        break;
                    case gviObjectType.gviObjectRenderMultiPolyline:
                        IRenderMultiPolylinePickResult mutlipolylinepr = pr as IRenderMultiPolylinePickResult;
                        IRenderMultiPolyline multipolyline = mutlipolylinepr.MultiPolyline;
                        MessageBox.Show("拾取到多线渲染对象");
                        break;
                    case gviObjectType.gviObjectRenderMultiTriMesh:
                        IRenderMultiTriMeshPickResult rendermtpr = pr as IRenderMultiTriMeshPickResult;
                        IRenderMultiTriMesh multiTresh = rendermtpr.MultiTriMesh;
                        MessageBox.Show("拾取到多三角网格面渲染对象");
                        break;
                    case gviObjectType.gviObjectRenderPOI:
                        IRenderPOIPickResult renderPoiPr = pr as IRenderPOIPickResult;
                        IRenderPOI renderPoi = renderPoiPr.POI;
                        MessageBox.Show("拾取到POI渲染对象");
                        break;
                    case gviObjectType.gviObjectRenderPoint:
                        IRenderPointPickResult renderPointPr = pr as IRenderPointPickResult;
                        IRenderPoint renderPoint = renderPointPr.Point;
                        MessageBox.Show("拾取到点渲染对象");
                        break;
                    case gviObjectType.gviObjectRenderPolygon:
                        IRenderPolygonPickResult renderPolygonPr = pr as IRenderPolygonPickResult;
                        IRenderPolygon renderPolygon = renderPolygonPr.Polygon;
                        MessageBox.Show("拾取到面渲染对象");
                        break;
                    case gviObjectType.gviObjectRenderPolyline:
                        IRenderPolylinePickResult renderPolylinePr = pr as IRenderPolylinePickResult;
                        IRenderPolyline renderPolyline = renderPolylinePr.Polyline;
                        MessageBox.Show("拾取到线渲染对象");
                        break;
                    case gviObjectType.gviObjectRenderTriMesh:
                        IRenderTriMeshPickResult renderTriMeshPr = pr as IRenderTriMeshPickResult;
                        IRenderTriMesh renderTriMesh = renderTriMeshPr.TriMesh;
                        MessageBox.Show("拾取到三角面渲染对象");
                        break;
                    case gviObjectType.gviObjectSkinnedMesh:
                        ISkinnedMeshPickResult skinMeshPr = pr as ISkinnedMeshPickResult;
                        ISkinnedMesh skinnedMesh = skinMeshPr.SkinnedMesh;
                        MessageBox.Show("拾取到骨骼动画对象");
                        break;
                    case gviObjectType.gviObjectTableLabel:
                        ITableLabelPickResult tblabelPr = pr as ITableLabelPickResult;
                        ITableLabel tbLael = tblabelPr.TableLabel;
                        MessageBox.Show("拾取到TableLabel");
                        break;
                    case gviObjectType.gviObjectTerrain3DArrow:
                        ITerrain3DArrowPickResult terrain3DArrowPr = pr as ITerrain3DArrowPickResult;
                        ITerrain3DArrow terrain3DArrow = terrain3DArrowPr.Terrain3DArrow;
                        MessageBox.Show("拾取到箭头Terrain3DArrow");
                        break;
                    case gviObjectType.gviObjectTerrainArc:
                        ITerrainArcPickResult terrainArcPr = pr as ITerrainArcPickResult;
                        ITerrainArc terrainArc = terrainArcPr.TerrainArc;
                        MessageBox.Show("拾取到弧渲染对象");
                        break;
                    case gviObjectType.gviObjectTerrainArrow:
                        ITerrainArrowPickResult terrainArrowPr = pr as ITerrainArrowPickResult;
                        ITerrainArrow terrainArrow = terrainArrowPr.TerrainArrow;
                        MessageBox.Show("拾取到箭头TerrainArrow");
                        break;
                    case gviObjectType.gviObjectTerrainBox:
                        ITerrainBoxPickResult terrainBoxPr = pr as ITerrainBoxPickResult;
                        ITerrain3DRectBase terrainBox = terrainBoxPr.TerrainBox;
                        MessageBox.Show("拾取到长方体");
                        break;

                    case gviObjectType.gviObjectTerrainCone:
                        ITerrainConePickResult terrainconePr = pr as ITerrainConePickResult;
                        ITerrain3DRegBase terrainCone = terrainconePr.TerrainCone;
                        MessageBox.Show("拾取到椎体");
                        break;
                    case gviObjectType.gviObjectTerrainCylinder:
                        ITerrainCylinderPickResult terrainCylinderPr = pr as ITerrainCylinderPickResult;
                        ITerrain3DRegBase terrainCylinder = terrainCylinderPr.TerrainCylinder;
                        MessageBox.Show("拾取到柱体");
                        break;
                    case gviObjectType.gviObjectTerrainEllipse:
                        ITerrainEllipsePickResult terrainEllipsePr = pr as ITerrainEllipsePickResult;
                        ITerrainEllipse terrainEllips = terrainEllipsePr.TerrainEllipse;
                        MessageBox.Show("拾取到椭圆");
                        break;
                    case gviObjectType.gviObjectTerrainHole:
                        ITerrainHolePickResult terrainHolePr = pr as ITerrainHolePickResult;
                        ITerrainHole terrainHole = terrainHolePr.TerrainHole;
                        MessageBox.Show("拾取到地形挖洞");
                        break;
                    case gviObjectType.gviObjectTerrainImageLabel:
                        ITerrainImageLabelPickResult terrainImagePr = pr as ITerrainImageLabelPickResult;
                        ITerrainImageLabel terrainImageLabel = terrainImagePr.TerrainImageLabel;
                        MessageBox.Show("拾取到图片标签");
                        break;
                    case gviObjectType.gviObjectTerrainModifier:
                        ITerrainModifierPickResult terrainModifiPr = pr as ITerrainModifierPickResult;
                        ITerrainModifier terrainModif = terrainModifiPr.TerrainModifier;
                        MessageBox.Show("拾取到地形编辑对象");
                        break;
                    case gviObjectType.gviObjectTerrain:
                        ITerrainPickResult terrainpr = pr as ITerrainPickResult;
                        ITerrain terrain = terrainpr.Terrain;
                        MessageBox.Show("拾取到地形");
                        break;
                    case gviObjectType.gviObjectTerrainPyramid:
                        ITerrainPyramidPickResult terrainPyramidPr = pr as ITerrainPyramidPickResult;
                        ITerrain3DRectBase terrainPyramid = terrainPyramidPr.TerrainPyramid;
                        MessageBox.Show("拾取到金字塔");
                        break;
                    case gviObjectType.gviObjectTerrainRectangle:
                        ITerrainRectanglePickResult terrainRectanglepr = pr as ITerrainRectanglePickResult;
                        ITerrainRectangle terrainRectangle = terrainRectanglepr.TerrainRectangle;
                        MessageBox.Show("拾取到矩形");
                        break;
                    case gviObjectType.gviObjectTerrainRegularPolygon:
                        ITerrainRegularPolygonPickResult terrainRegularPolygonPr = pr as ITerrainRegularPolygonPickResult;
                        ITerrainRegularPolygon terrainRegularPolygon = terrainRegularPolygonPr.TerrainRegularPolygon;
                        MessageBox.Show("拾取到正多边形");
                        break;
                    case gviObjectType.gviObjectTerrainSphere:
                        ITerrainSpherePickResult terrainSpherePr = pr as ITerrainSpherePickResult;
                        ITerrainSphere terrainSphere = terrainSpherePr.TerrainSphere;
                        MessageBox.Show("拾取到球体");
                        break;
                    case gviObjectType.gviObjectTerrainVideo:
                        ITerrainVideoPickResult terrainVideoPr = pr as ITerrainVideoPickResult;
                        ITerrainVideo terrainVideo = terrainVideoPr.TerrainVideo;
                        MessageBox.Show("拾取到贴地视频");
                        break;
                    case gviObjectType.gviObjectViewshed:
                        IViewshedPickResult viewshedPr = pr as IViewshedPickResult;
                        IViewshed viewshed = viewshedPr.Viewshed;
                        MessageBox.Show("拾取到视域");
                        break;
                    case gviObjectType.gviObject3DTileHole:
                        ITileHolePickResult tileHolePr = pr as ITileHolePickResult;
                        I3DTileHole tileHole = tileHolePr.TileHole;
                        MessageBox.Show("拾取到瓦片挖洞");
                        break;
                }
            }
        }
    }
           
/*点击事件*/
    void axRenderControl1_RcMouseClickSelect(object sender, _IRenderControlEvents_RcMouseClickSelectEvent e)
    {
        IPickResult pickresault = e.pickResult;
        if (pickresault == null)
            return;
        if (e.mask != gviModKeyMask.gviModKeyCtrl)  //判断是否Control键按下,也可以是其他键盘键
        { }
        switch (pickresault.Type)
        {
            case gviObjectType.gviObjectFeatureLayer:
                IFeatureLayerPickResult flpr = pr as IFeatureLayerPickResult;
                int fid = flpr.FeatureId;
                IFeatureLayer fl = flpr.FeatureLayer;
                fl.HighlightFeature(fid, 0xffff0000);//高亮拾取对象  
                MessageBox.Show(fid.ToString());
                break;
            case ...

            ///方法同框选事件       
        }
    }
           

2. JS代码

//设置控件交互模式
  /*注册点击事件*/
  function registerclickevent(){
      __g.interactMode = 2;  //gviInteractMode.gviInteractSelect鼠标交互改为点击选择模式
      __g.mouseSelectObjectMask = 65535;  //gviMouseSelectObjectMask.gviSelectAll设置选择对象类型

      //绑定拾取事件
      __g.onmouseclickselect = fnMouseClickSelect; //注册点击事件
      __g.onmousedragselect = fnMouseDragSelect;//注册框选事件

      //设置鼠标拾取触发方式
      __g.mouseSelectMode = 1|2; //gviMouseSelectMode.gviMouseSelectClick | gviMouseSelectMode.gviMouseSelectDrag
   }
           
//点击事件
function fnMouseClickSelect(pickResult, intersectPoint, mask, eventSender) { 
  if(pickResult == null) 
 	return; 
  if(pickResult != null) { 
  switch (pickResult.type){ 
 	 case gviObjectType.gviObjectFeatureLayer: 
 		 var fid = pickResult.featureId; 
 		 var fl = pickResult.featureLayer;
 		  fl.highlightFeature(fid, 0xffff0000);//高亮对象 
     break; 
 	 case gviObjectType.gviObjectLabel: 
 		 var labelpr = pickResult.Label;
 	     alert("拾取到标签Label"); 
     break;
     case gviObjectType.gviObjectOverlayLabel: 
 	     var ovelabel = pickResult.OverlayLabel; 
 	     alert("拾取到OverlayLabel");
     break; // ...... }
  }
}
           

三、 注意

拾取事件(RcMouseClickSelect/RcMouseDragSelect)的触发不再限制需要进入拾取模式。每种交互模式,执行某些底层预定义的鼠标操作,也会触发拾取事件(见下图)。 图中打勾表示当前模式下执行当前的鼠标操作,三维会触发拾取事件。反之,打叉处表示不会触发拾取事件。

若想在漫游模式下使用鼠标点选对矢量进行拾取,需如下设置,且先后顺序不可颠倒:

   __g.interactMode = gviInteractMode.gviInteractNormal;
   //MouseSelectMode与MouseSelectObjectMask之间的调用不存在顺序问题。
   __g.mouseSelectObjectMask = gviMouseSelectObjectMask.gviSelectFeatureLayer;
   __g.mouseSelectMode = gviMouseSelectMode.gviMouseSelectClick;