我有道路图层。 我需要指向另一个道路相交的点层。 如何将这些点添加到现有点图层。
手头我有线图层,线要素/ To和From Points以及点图层。 我只需要一个指针来指示如何在点图层中创建点。
我正在使用C#
谢谢。
答案 0 :(得分:2)
下面的代码说明了通过使用扩展方法实现此目的的方法。 ArcObjects API经常被批评为接口太多,导致代码可读性降低。我相信扩展方法可以解决许多这些问题。缺点是阅读代码的人无法轻易区分扩展方法和API的一部分方法。
我不确定问题的背景,但是如果你要为街道交叉点创建点,你可以考虑使用不同的点哈希函数。这将允许道路交叉点,其中道路在多于一个点处交叉由单个点表示。这类似于地图拓扑中使用的群集容差。
我还没有真正了解一个很好的继承方法,用于调用自定义异常的基础构造函数。任何建议都会受到赞赏。
using System;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.ADF.BaseClasses;
using ESRI.ArcGIS.Framework;
using System.Windows.Forms;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Carto;
using System.Collections.Generic;
using ESRI.ArcGIS.Editor;
namespace IGG.SurveyTools
{
/// <summary>
/// Summary description for TestCommand.
/// </summary>
[ProgId("IGG.SurveyTools.TestCommand")]
public sealed class TestCommand : BaseCommand
{
private IEditor m_Editor;
public TestCommand()
{
//
// TODO: Define values for the public properties
//
base.m_category = ""; //localizable text
base.m_caption = "Add End points"; //localizable text
base.m_message = ""; //localizable text
base.m_toolTip = ""; //localizable text
base.m_name = ""; //unique id, non-localizable (e.g. "MyCategory_MyCommand")
}
#region Overriden Class Methods
/// <summary>
/// Occurs when this command is created
/// </summary>
/// <param name="hook">Instance of the application</param>
public override void OnCreate(object hook)
{
IApplication app = hook as IApplication;
if (app == null)
return;
m_Editor = app.FindExtensionByName("ESRI Object Editor") as IEditor;
}
public override bool Enabled
{
get
{
return (m_Editor != null && m_Editor.EditState == esriEditState.esriStateEditing);
}
}
public override void OnClick()
{
try
{
string fmt = "{0},{1}";
IMxDocument mxDoc = (IMxDocument)m_Editor.Parent.Document;
IFeatureLayer polylineLayer = mxDoc.FocusMap.FindFLayer("My Polylines");
IFeatureLayer pointLayer = mxDoc.FocusMap.FindFLayer("My Points");
if(((IDataset)pointLayer.FeatureClass).Workspace != m_Editor.EditWorkspace)
{
MessageBox.Show(new Win32Win(m_Editor), "Points layer is not being edited");
return;
}
Dictionary<string, IPoint> endPoints = polylineLayer.GetEndPoints(fmt);
if (endPoints.Count == 0)
{
MessageBox.Show("no end points found");
return;
}
Dictionary<string,IPoint> existingPoints = pointLayer.GetPoints(fmt);
Dictionary<string,IPoint> newPoints = endPoints.Subtract(existingPoints);
if(newPoints.Count == 0)
{
MessageBox.Show(new Win32Win(m_Editor.Parent),"all endpoints are present in pointslayer");
return;
}
m_Editor.StartOperation();
try
{
pointLayer.FeatureClass.PutPoints(newPoints.Values);
m_Editor.StopOperation(String.Format("Added {0} new endpoints", newPoints.Count));
((IActiveView)m_Editor.Map).Refresh();
}
catch(Exception ex)
{
m_Editor.AbortOperation();
}
}
catch (Exception ex)
{
MessageBox.Show(new Win32Win(m_Editor), ex.Message + Environment.NewLine + ex.StackTrace);
}
}
#endregion
}
public class Win32Win : IWin32Window
{
private IntPtr m_handle;
public Win32Win(IApplication app) { m_handle = new IntPtr(app.hWnd); }
public IntPtr Handle { get { return m_handle; } }
public Win32Win(int hwnd) { m_handle = new IntPtr(hwnd); }
public Win32Win(IEditor editor) { m_handle = new IntPtr(editor.Parent.hWnd); }
}
public class LayerNotFoundException : Exception
{
public LayerNotFoundException(string lyrName)
: base("Layer not found: " + lyrName)
{
}
}
public class FeatureLayerNotFoundException : LayerNotFoundException
{
public FeatureLayerNotFoundException(string lyrName)
: base(lyrName)
{
}
}
public static class MyExtensions
{
public static void PutPoints(this IFeatureClass fc, IEnumerable<IPoint> pnts)
{
IFeatureCursor fCur = fc.Insert(false);
IFeatureBuffer buff = fc.CreateFeatureBuffer();
foreach (IPoint pnt in pnts)
{
buff.Shape = pnt;
fCur.InsertFeature(buff);
}
fCur.Flush();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(fCur);
}
/// <summary>
/// returns first layer in map with case-insensitive name
/// </summary>
/// <param name="map"></param>
/// <param name="name"></param>
/// <returns></returns>
public static ILayer FindLayer(this IMap map, string name)
{
if (map.LayerCount == 0)
throw new LayerNotFoundException(name);
IEnumLayer enumLayer = map.get_Layers(null, true);
ILayer layer;
while ((layer = enumLayer.Next()) != null)
{
if (layer.Name.Trim().ToUpper() == name.Trim().ToUpper())
return layer;
}
throw new LayerNotFoundException(name);
}
public static IFeatureLayer FindFLayer(this IMap map, string name)
{
IFeatureLayer fLayer = map.FindLayer(name) as IFeatureLayer;
if (fLayer == null)
throw new FeatureLayerNotFoundException(name);
return fLayer;
}
public static Dictionary<string, IPoint> GetPoints(this IFeatureLayer fLayer, string fmt)
{
if (fLayer.FeatureClass == null
|| fLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryPoint)
throw new Exception("bad point layer: " + fLayer.Name);
Dictionary<string, IPoint> outDict = new Dictionary<string, IPoint>();
IFeatureCursor fCur = fLayer.FeatureClass.Search(null, false);
IFeature feat;
while ((feat = fCur.NextFeature()) != null)
{
outDict.AddPoint((IPoint)feat.ShapeCopy,fmt);
}
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(fCur);
return outDict;
}
public static Dictionary<string, IPoint> GetEndPoints(this IFeatureLayer fLayer, string fmt)
{
if (fLayer.FeatureClass == null
|| fLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryPolyline)
throw new Exception("bad polyline layer: " + fLayer.Name);
Dictionary<string, IPoint> outDict = new Dictionary<string, IPoint>();
IFeatureCursor fCur = fLayer.FeatureClass.Search(null, false);
IFeature feat;
while ((feat = fCur.NextFeature()) != null)
{
IPolyline polyline = (IPolyline)feat.ShapeCopy;
if (polyline == null || polyline.IsEmpty)
continue;
outDict.AddPoint(polyline.FromPoint,fmt);
outDict.AddPoint(polyline.ToPoint,fmt);
}
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(fCur);
return outDict;
}
public static string Hash(this IPoint pnt, string fmt)
{
// use different formatting options to do quick and dirty clustering
return String.Format(fmt, pnt.X, pnt.Y);
}
public static void AddPoint(this Dictionary<string,IPoint> dict ,IPoint pnt, string fmt)
{
string hash = pnt.Hash(fmt);
if (!dict.ContainsKey(hash))
dict.Add(hash, pnt);
}
public static Dictionary<string, IPoint> Subtract(this Dictionary<string, IPoint> inDict, Dictionary<string, IPoint> otherDict)
{
Dictionary<string, IPoint> outDict = new Dictionary<string, IPoint>();
foreach (KeyValuePair<string, IPoint> kvp in inDict)
{
if (!otherDict.ContainsKey(kvp.Key))
outDict.Add(kvp.Key, kvp.Value);
}
return outDict;
}
}
}