**
鼠标拾取
**
一、 鼠标拾取原理
鼠标可以通过点选和框选的方式实现拾取渲染对象,并支持通过按住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可以将拾取到的对象进行高亮显示,通过查询可取到拾取对象的属性信息等,效果如下图
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TP35EMRpmTzEFRPpHOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLygjN4UjNwMTM5ITMwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
二、 实现代码
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;