AO开发包为我们提供了绘制平行线的工具 ControlsEditingSketchParallelCommand ,但是它必须宿主在编辑右键菜单上 ControlsEditingSketchContextMenu。对于熟悉ArcGIS Engine开发的朋友完全可以自己开发实现绘制平行线功能。本文为大家介绍实现平行线绘制的一些思路。
确定平行线绘制起点,选择参考的基准线
接下来绘制平行线时 大家发现鼠标画线已经被限定在与参考线平行那条线上
using System; using System.Drawing; using System.Runtime.InteropServices; using System.Collections.Generic; using ESRI.ArcGIS.ADF.BaseClasses; using ESRI.ArcGIS.ADF.CATIDs; using ESRI.ArcGIS.Controls; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.Display; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.esriSystem; using System.Text.RegularExpressions; using System.Windows.Forms; namespace Parallel { /// /// Summary description for ParallelTool1. /// [Guid("f4afe519-b3a0-454d-9615-e64f2b18ff53")] [ClassInterface(ClassInterfaceType.None)] [ProgId("demo.Parallel.ParallelTool1")] public sealed class ParallelTool1 : BaseTool { #region COM Registration Function(s) [ComRegisterFunction()] [ComVisible(false)] static void RegisterFunction(Type registerType) { // Required for ArcGIS Component Category Registrar support ArcGISCategoryRegistration(registerType); // // TODO: Add any COM registration code here // } [ComUnregisterFunction()] [ComVisible(false)] static void UnregisterFunction(Type registerType) { // Required for ArcGIS Component Category Registrar support ArcGISCategoryUnregistration(registerType); // // TODO: Add any COM unregistration code here // } #region ArcGIS Component Category Registrar generated code /// /// Required method for ArcGIS Component Category registration - /// Do not modify the contents of this method with the code editor. /// private static void ArcGISCategoryRegistration(Type registerType) { string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID); ControlsCommands.Register(regKey); } /// /// Required method for ArcGIS Component Category unregistration - /// Do not modify the contents of this method with the code editor. /// private static void ArcGISCategoryUnregistration(Type registerType) { string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID); ControlsCommands.Unregister(regKey); } #endregion #endregion private IHookHelper m_hookHelper; private IMapControl3 m_mapControl; //private IPolyline pPolyline = null; private IPolyline pPolyline_Parallel = null; private INewLineFeedback pDraglineFeedBack = null; private List AddPs = new List(); private int Flag = 0; private double dis = 0; private double angle = 0; public ParallelTool1() { // // TODO: Define values for the public properties // base.m_category = ""; //localizable text base.m_caption = ""; //localizable text base.m_message = ""; //localizable text base.m_toolTip = ""; //localizable text base.m_name = ""; //unique id, non-localizable (e.g. "MyCategory_MyTool") try { // // TODO: change resource name if necessary // string bitmapResourceName = GetType().Name + ".bmp"; base.m_bitmap = new Bitmap(GetType(), bitmapResourceName); base.m_cursor = new System.Windows.Forms.Cursor(GetType(), GetType().Name + ".cur"); } catch (Exception ex) { System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap"); } } #region Overridden Class Methods /// /// Occurs when this tool is created /// /// Instance of the application public override void OnCreate(object hook) { if (m_hookHelper == null) m_hookHelper = new HookHelperClass(); m_hookHelper.Hook = hook; // TODO: Add ParallelTool1.OnCreate implementation m_mapControl = hook as IMapControl3; } /// /// Occurs when this tool is clicked /// public override void OnClick() { // TODO: Add ParallelTool1.OnClick implementation } public override void OnMouseDown(int Button, int Shift, int X, int Y) { // TODO: Add ParallelTool1.OnMouseDown implementation try { IPoint sStartPoint = m_mapControl.ToMapPoint(X, Y); if (pDraglineFeedBack == null) { pDraglineFeedBack = new NewLineFeedback(); } pDraglineFeedBack.Display = m_mapControl.ActiveView.ScreenDisplay; if (Flag == 0) { pDraglineFeedBack.Start(sStartPoint); Flag += 1; } else { if (pPolyline_Parallel == null) CatchSel(m_mapControl.Map, X, Y); if (pPolyline_Parallel == null) pDraglineFeedBack.Start(sStartPoint); else { if (Flag == 2) { } else { IPoint pPoint = SetMouseLocation(X, Y); pDraglineFeedBack.Start(pPoint); } } } } catch (Exception er) { MessageBox.Show(er.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } public override void OnMouseMove(int Button, int Shift, int X, int Y) { // TODO: Add ParallelTool1.OnMouseMove implementation try { if (pDraglineFeedBack == null) return; if (pPolyline_Parallel == null) { IPoint sPoint = m_mapControl.ToMapPoint(X, Y); pDraglineFeedBack.MoveTo(sPoint); } else { IPoint pPoint = SetMouseLocation(X, Y); pDraglineFeedBack.MoveTo(pPoint); } } catch { } } public override void OnMouseUp(int Button, int Shift, int X, int Y) { // TODO: Add ParallelTool1.OnMouseUp implementation try { if (pDraglineFeedBack == null) return; IPoint sPoint = null; if(pPolyline_Parallel == null) sPoint = m_mapControl.ToMapPoint(X, Y); else sPoint = SetMouseLocation(X, Y); if (Button == 1) { if (Flag != 2) { pDraglineFeedBack.AddPoint(sPoint); AddPs.Add(sPoint); if (AddPs.Count == 2) { pPolyline_Parallel = pDraglineFeedBack.Stop(); IFeatureLayer sFlyr = Publics.Functions.G_Funs.getFlyrByName(m_mapControl.Map, "燃气-管线"); IDataset pDS = sFlyr.FeatureClass as IDataset; IWorkspaceEdit pWSEdit = pDS.Workspace as IWorkspaceEdit; pWSEdit.StartEditing(true); pWSEdit.StartEditOperation(); IFeature pFea = sFlyr.FeatureClass.CreateFeature(); pFea.Shape = pPolyline_Parallel; pFea.Store(); pWSEdit.StopEditOperation(); //m_mapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, sFlyr, m_mapControl.Extent); pDraglineFeedBack = null; AddPs.Clear(); Flag = 0; pPolyline_Parallel = null; //m_mapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, m_mapControl.Extent); m_mapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewAll, null, m_mapControl.Extent); } } else { Flag += 1; } } //else if (Button == 2) //{ // pDraglineFeedBack.Stop(); // pDraglineFeedBack = null; // AddPs.Clear(); // Flag = 0; // pPolyline_Parallel = null; // m_mapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, m_mapControl.Extent); //} } catch (Exception er) { MessageBox.Show(er.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } #endregion private void CatchSel(IMap sMap, int X, int Y) { try { Publics.Functions.G_Funs.ClearSelection(m_mapControl); for (int i = 0; i < sMap.LayerCount; i++) { //管线上加点 ILayer pLayer = sMap.get_Layer(i); if (Regex.IsMatch(pLayer.Name, "-参考线", RegexOptions.IgnoreCase)) { ESRI.ArcGIS.Geometry.IPoint pt = new ESRI.ArcGIS.Geometry.PointClass(); pt = m_mapControl.ToMapPoint(X, Y); //点击处做缓冲区 double dis = Publics.Functions.G_Funs.ConvertPixelsToMapUnits(m_mapControl, 20); ITopologicalOperator pTopo = pt as ITopologicalOperator; IGeometry geo = pTopo.Buffer(dis); esriGeometryType geoType = (pLayer as IFeatureLayer).FeatureClass.ShapeType; esriFeatureType FeatureType = (pLayer as IFeatureLayer).FeatureClass.FeatureType; //空间查询条件 ISpatialFilter pSpatial = new SpatialFilterClass(); pSpatial.Geometry = geo; pSpatial.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; if (geoType == esriGeometryType.esriGeometryPoint) pSpatial.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains; IFeatureCursor pFeatureCursor = (pLayer as IFeatureLayer).FeatureClass.Search(pSpatial, false); if (pFeatureCursor != null) { IFeature pFeature = pFeatureCursor.NextFeature(); if (pFeature != null) { IPolyline pPolyline = pFeature.ShapeCopy as IPolyline; 计算管线上点 IProximityOperator pProximityOperator = pFeature.ShapeCopy as IProximityOperator; //IPoint pNearsetPoint = new ESRI.ArcGIS.Geometry.PointClass(); //pProximityOperator.QueryNearestPoint(pt, esriSegmentExtension.esriExtendEmbedded, pNearsetPoint); 将管线上的点添加到临时图元 //Publics.Functions.G_Funs.AddMarkerElement(m_mapControl.Map, pNearsetPoint); //pt = AddPs[AddPs.Count - 1]; dis = pProximityOperator.ReturnDistance(AddPs[AddPs.Count - 1]); IPoint pNearsetPoint = new ESRI.ArcGIS.Geometry.PointClass(); pProximityOperator.QueryNearestPoint(AddPs[AddPs.Count - 1], esriSegmentExtension.esriExtendEmbedded, pNearsetPoint); ILine pLine = new LineClass(); //pLine.FromPoint = pPolyline.FromPoint; //pLine.ToPoint = pPolyline.ToPoint; //angle = pLine.Angle; //if (angle < 0) //{ // angle = angle +180*Math.PI/180; //} //double dx = dis / Math.Sin(angle); //double dy = dis / Math.Cos(angle); IClone pClone = pPolyline as IClone; ITransform2D pTransform2D = pClone.Clone() as ITransform2D; //pTransform2D.Move(dx, dy); pLine = new LineClass(); pLine.FromPoint = pNearsetPoint; pLine.ToPoint = AddPs[AddPs.Count - 1]; pTransform2D.MoveVector(pLine); pPolyline_Parallel = pTransform2D as IPolyline; //IFeatureLayer sFlyr = pLayer as IFeatureLayer; //IFeature pFea = sFlyr.FeatureClass.CreateFeature(); //pFea.Shape = pPolyline_Parallel; //pFea.Store(); //m_mapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, pLayer, m_mapControl.Extent); Flag = 2; return; } Publics.Functions.G_Funs.pReleaseObj(pFeatureCursor); pFeatureCursor = null; if (pFeature != null) return; } } } } catch (Exception er) { MessageBox.Show(er.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } private IPoint SetMouseLocation(int X, int Y) { try { IPoint pPoint = m_mapControl.ToMapPoint(X, Y); IProximityOperator pProximityOperator = pPolyline_Parallel as IProximityOperator; IPoint pNearsetPoint = new ESRI.ArcGIS.Geometry.PointClass(); pProximityOperator.QueryNearestPoint(pPoint, esriSegmentExtension.esriExtendEmbedded, pNearsetPoint); return pNearsetPoint; } catch (Exception er) { MessageBox.Show(er.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return null; } } } }