1. 程式人生 > >Arcengine的工具中實現Snapping(捕捉)

Arcengine的工具中實現Snapping(捕捉)

在Engine的工具(ITool)裡:

OnClick事件處理函式中:

首先需要獲取一個圖層,作為Snapping的參照,

IFeatureLayer targetLayer

然後宣告一個IMovePointFeedBack作為滑鼠移動時捕捉點的顯示:

  1. IMovePointFeedback m_pMovePtFeed = new MovePointFeedback();  
  2. mFeedback = (IDisplayFeedback)m_pMovePtFeed;  
  3. ISimpleMarkerSymbol simpleMarkerSymbol = new SimpleMarkerSymbolClass();  
  4. IRgbColor pRGBColor = new RgbColorClass();  
  5. pRGBColor.Red = 0;  
  6. pRGBColor.Green = 0;  
  7. pRGBColor.Blue = 0;  
  8. simpleMarkerSymbol.Color = pRGBColor;  
  9. simpleMarkerSymbol.Size = 3;  
  10. simpleMarkerSymbol.Style = ESRI.ArcGIS.Display.esriSimpleMarkerStyle.esriSMSSquare;  
  11. ISymbol symbol = simpleMarkerSymbol as
     ISymbol;  
  12. symbol.ROP2 = esriRasterOpCode.esriROPNotXOrPen;  
  13. //symbol.ROP2 = esriRasterOpCode.;
  14. m_pMovePtFeed.Symbol = (ISymbol)simpleMarkerSymbol;  

然後開始Feedback的顯示(tmpPoint是指開始的點,其實影響不大,如果不想要源點在螢幕上的話,可以取一個在螢幕外的點):

  1. m_pMovePtFeed.Display = mMapControl.ActiveView.ScreenDisplay;  
  2. m_pMovePtFeed.Start(tmpPoint, tmpPoint);  

在OnMouseMove事件中:

  1. IPoint pPoint2 = null;  
  2. IPoint pPoint = pMap.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);  
  3. pPoint2 = Snapping(pPoint.X, pPoint.Y, targetLayer, pMap, 10);  
  4. if (pPoint2 == null)  
  5. pPoint2 = pPoint;  
  6. ((IMovePointFeedback)mFeedback).MoveTo(pPoint2);  

其中Snapping函式即為最主要的查詢函式,其功能為根據輸入的點座標在目標圖層上查詢最為相近的點(也即需要捕捉的點),返回該點,若沒有找到則返回NULL,最後一個引數的含義是,在地圖控制元件上,以多少個畫素為單位在周邊查詢捕捉點.

  1. public IPoint Snapping(double x, double y, IFeatureLayer iFeatureLyr, IMapControl3 axMapControl1,double snappingDis)  
  2.         {  
  3.             IPoint iHitPoint = null;  
  4.             IMap iMap = axMapControl1.Map;  
  5.             IActiveView iView = axMapControl1.ActiveView;  
  6.             IFeatureClass iFClss = iFeatureLyr.FeatureClass;  
  7.             IPoint point = new PointClass();  
  8.             point.PutCoords(x, y);  
  9.             double length = ConvertPixelsToMapUnits(axMapControl1.ActiveView, snappingDis);  
  10.             ITopologicalOperator pTopo = point as ITopologicalOperator;  
  11.             IGeometry pGeometry = pTopo.Buffer(length).Envelope as IGeometry;  
  12.             ISpatialFilter spatialFilter = new SpatialFilterClass();  
  13.             spatialFilter.GeometryField = iFeatureLyr.FeatureClass.ShapeFieldName;  
  14.             spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;  
  15.             spatialFilter.Geometry = pGeometry;  
  16.             IFeatureCursor cursor = iFClss.Search(spatialFilter, false);  
  17.             IFeature iF = cursor.NextFeature();  
  18.             if (iF == nullreturnnull;  
  19.             IPoint iHitPt = new ESRI.ArcGIS.Geometry.Point();  
  20.             IHitTest iHitTest = iF.Shape as IHitTest;  
  21.             double hitDist = 0;  
  22.             int partIndex = 0;  
  23.             int vertexIndex = 0;  
  24.             bool bVertexHit = false;  
  25.             // Tolerance in pixels for line hits
  26.             double tol = ConvertPixelsToMapUnits(iView, snappingDis);  
  27.             if (iHitTest.HitTest(point, tol, esriGeometryHitPartType.esriGeometryPartBoundary,  
  28.                 iHitPt, ref hitDist, ref partIndex, ref vertexIndex, ref bVertexHit))  
  29.             {  
  30.                 iHitPoint = iHitPt;  
  31.             }  
  32.             //axMapControl1.ActiveView.Refresh();
  33.             return iHitPoint;  
  34.         }  
  35.         publicdouble ConvertPixelsToMapUnits(IActiveView pActiveView, double pixelUnits)  
  36.         {  
  37.             double realWorldDisplayExtent;  
  38.             int pixelExtent;  
  39.             double sizeOfOnePixel;  
  40.             pixelExtent = pActiveView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().right - pActiveView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().left;  
  41.             realWorldDisplayExtent = pActiveView.ScreenDisplay.DisplayTransformation.VisibleBounds.Width;  
  42.             sizeOfOnePixel = realWorldDisplayExtent / pixelExtent;  
  43.             return pixelUnits * sizeOfOnePixel;  
  44.         }  

此時即可實現滑鼠實時地捕捉目標圖層上的物件,若需要獲取當前位置的捕捉點時,則可以在相應事件(例如OnMouseDown或OnDbClick)中呼叫:

  1. IPoint pPoint = ((IMovePointFeedback)mFeedback).Stop();  

這時實時捕捉將會停止,若需要重新開始捕捉,則在之後呼叫這些語句即可:

  1. //重新開始Snap
  2. IPoint tmpPoint = new PointClass();  
  3. tmpPoint.PutCoords(pMap.Extent.XMin - 1, pMap.Extent.YMin - 1);  
  4. IMovePointFeedback m_pMovePtFeed = (IMovePointFeedback)mFeedback;  
  5. m_pMovePtFeed.Display = pMap.ActiveView.ScreenDisplay;  
  6. m_pMovePtFeed.Start(tmpPoint, tmpPoint);