首页 > 代码库 > engine的工具中实现Snapping(捕捉)

engine的工具中实现Snapping(捕捉)

 

在Engine的工具(ITool)里:

OnClick事件处理函数中:

首先需要获取一个图层,作为Snapping的参照,

IFeatureLayer targetLayer

然后声明一个IMovePointFeedBack作为鼠标移动时捕捉点的显示:

IMovePointFeedback m_pMovePtFeed = new MovePointFeedback();  
mFeedback = (IDisplayFeedback)m_pMovePtFeed;  
ISimpleMarkerSymbol simpleMarkerSymbol = new SimpleMarkerSymbolClass();  
IRgbColor pRGBColor = new RgbColorClass();  
pRGBColor.Red = 0;  
pRGBColor.Green = 0;  
pRGBColor.Blue = 0;  
simpleMarkerSymbol.Color = pRGBColor;  
simpleMarkerSymbol.Size = 3;  
simpleMarkerSymbol.Style = ESRI.ArcGIS.Display.esriSimpleMarkerStyle.esriSMSSquare;  
ISymbol symbol = simpleMarkerSymbol as ISymbol;  
symbol.ROP2 = esriRasterOpCode.esriROPNotXOrPen;  
//symbol.ROP2 = esriRasterOpCode.;  
m_pMovePtFeed.Symbol = (ISymbol)simpleMarkerSymbol;  

然后, 开始Feedback的显示(tmpPoint是指开始的点,其实影响不大,如果不想要源点在屏幕上的话,可以取一个在屏幕外的点):

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

在OnMouseMove事件中:

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

其中Snapping函数即为最主要的查找函数,其功能为根据输入的点坐标在目标图层上查找最为相近的点(也即需要捕捉的点),返回该点,若没有找到则返回NULL,最后一个参数的含义是,在地图控件上,以多少个像素为单位在周边查找捕捉点.

public IPoint Snapping(double x, double y, IFeatureLayer iFeatureLyr, IMapControl3 axMapControl1,double snappingDis)  
{  
    IPoint iHitPoint = null;  
    IMap iMap = axMapControl1.Map;  
    IActiveView iView = axMapControl1.ActiveView;  
    IFeatureClass iFClss = iFeatureLyr.FeatureClass;  
    IPoint point = new PointClass();  
    point.PutCoords(x, y);  
    double length = ConvertPixelsToMapUnits(axMapControl1.ActiveView, snappingDis);  
    ITopologicalOperator pTopo = point as ITopologicalOperator;  
    IGeometry pGeometry = pTopo.Buffer(length).Envelope as IGeometry;  
    ISpatialFilter spatialFilter = new SpatialFilterClass();  
    spatialFilter.GeometryField = iFeatureLyr.FeatureClass.ShapeFieldName;  
    spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;  
    spatialFilter.Geometry = pGeometry;  
    IFeatureCursor cursor = iFClss.Search(spatialFilter, false);  
    IFeature iF = cursor.NextFeature();  
    if (iF == null) return null;  
    IPoint iHitPt = new ESRI.ArcGIS.Geometry.Point();  
    IHitTest iHitTest = iF.Shape as IHitTest;  
    double hitDist = 0;  
    int partIndex = 0;  
    int vertexIndex = 0;  
    bool bVertexHit = false;  
    // Tolerance in pixels for line hits  
    double tol = ConvertPixelsToMapUnits(iView, snappingDis);  
    if (iHitTest.HitTest(point, tol, esriGeometryHitPartType.esriGeometryPartBoundary,  
iHitPt, ref hitDist, ref partIndex, ref vertexIndex, ref bVertexHit))  
    {  
iHitPoint = iHitPt;  
    }  
    //axMapControl1.ActiveView.Refresh();  
    return iHitPoint;  
}  
public double ConvertPixelsToMapUnits(IActiveView pActiveView, double pixelUnits)  
{  
    double realWorldDisplayExtent;  
    int pixelExtent;  
    double sizeOfOnePixel;  
    pixelExtent = pActiveView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().right - pActiveView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().left;  
    realWorldDisplayExtent = pActiveView.ScreenDisplay.DisplayTransformation.VisibleBounds.Width;  
    sizeOfOnePixel = realWorldDisplayExtent / pixelExtent;  
    return pixelUnits * sizeOfOnePixel;  
}

此时即可实现鼠标实时地捕捉目标图层上的对象,若需要获取当前位置的捕捉点时,则可以在相应事件(例如OnMouseDown或OnDbClick)中调用:

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

这时实时捕捉将会停止,若需要重新开始捕捉,则在之后调用这些语句即可:

 

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

 

engine的工具中实现Snapping(捕捉)