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;
}
}
}
}