我有一个道路图层。我需要将一个点添加到道路相交的另一个点层。如何将这些点添加到现有的点图层。
我手头有线层、线特征/到点和起点,以及点层。我只需要一个关于如何在点层中创建点的指针。
我正在使用 C#
谢谢你。
我有一个道路图层。我需要将一个点添加到道路相交的另一个点层。如何将这些点添加到现有的点图层。
我手头有线层、线特征/到点和起点,以及点层。我只需要一个关于如何在点层中创建点的指针。
我正在使用 C#
谢谢你。
下面的代码说明了通过使用扩展方法来做到这一点的方法。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;
}
}
}