Приведенный ниже код иллюстрирует способы сделать это с помощью методов расширения. 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;
}
}
}