The thing I miss about polygon coverages is the way you could BUILD them with the LINE option then set up two relates, one for LPOLY# and the other for RPOLY# to find arcs that separate different polygons of interest. As a workaround the code below populates the polyline featureclass being edited with edges from a polygon featureclass which participates in a topology. It calculates the Left_OID and Right_OID fields based on what it borders. After running this the interior polylines can be found by applying a Definition expression "Left_OID" <> -1 and "Right_OID" <> -1
You could also set up joins to find polylines that separate particular polygons.
protected override void OnClick()
{
try
{
IMouseCursor mc = new MouseCursorClass();
mc.SetCursor(2);
var polygonLayer = ArcMap.Document.SelectedItem as IFeatureLayer;
if (polygonLayer == null || polygonLayer.FeatureClass == null || polygonLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryPolygon)
{
MessageBox.Show("select a polygon featureclass in the TOC first");
return;
}
var editor = ArcMap.Application.FindExtensionByName("ESRI Object Editor") as IEditor;
if (editor.EditState != esriEditState.esriStateEditing)
{
MessageBox.Show("start editing first");
return;
}
var edgeLayer = ((IEditLayers)editor).CurrentLayer;
if (edgeLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryPolyline)
{
MessageBox.Show("edit target layer must be polylines");
return;
}
try
{
var tc = new CancelTrackerClass() as ITrackCancel;
tc.CancelOnKeyPress = true;
editor.StartOperation();
DumpEdges(polygonLayer, edgeLayer,tc,ArcMap.Application.StatusBar);
if (tc.Continue())
editor.StopOperation("dump edges");
else
editor.AbortOperation();
}
catch
{
editor.AbortOperation();
throw;
}
}
catch (Exception ex)
{
StringBuilder sb = new StringBuilder();
while (ex != null)
{
sb.AppendLine(ex.Message);
//sb.AppendLine(ex.StackTrace);
ex = ex.InnerException;
}
MessageBox.Show(sb.ToString());
}
}
private void DumpEdges(IFeatureLayer polygonLayer, IFeatureLayer edgeLayer, ITrackCancel tc, IStatusBar sb)
{
// write edges from polygonlayer to edgelayer, populating Left_OID and Right_OID
var topoClass = polygonLayer.FeatureClass as ITopologyClass;
if (!topoClass.IsInTopology)
throw new Exception(polygonLayer.Name + " is not in a topology");
int leftIdx = GetFieldIdx(edgeLayer.FeatureClass,"Left_OID");
int rightIdx = GetFieldIdx(edgeLayer.FeatureClass, "Right_OID");
var extent = ((IGeoDataset)topoClass).Extent;
var graph = topoClass.Topology.Cache;
sb.set_Message(0, "building topology ...");
graph.Build(extent, false);
var edges = graph.Edges;
edges.Reset();
sb.set_Message(0, "topology built");
sb.ProgressBar.Position=0;
sb.ShowProgressBar("dumping edges, press escape key to cancel",0,edges.Count,1,false);
for (int i = 0; i < edges.Count; i++)
{
var edge = edges.Next();
DumpEdge(polygonLayer, edgeLayer, leftIdx, rightIdx, edge);
sb.ProgressBar.Position=i;
if (!tc.Continue())
{
sb.set_Message(0, "canceled");
break;
}
}
sb.HideProgressBar();
}
private void DumpEdge(IFeatureLayer polygonLayer, IFeatureLayer edgeLayer, int leftIdx, int rightIdx, ITopologyEdge edge)
{
int leftOID = GetOID(edge.get_LeftParents(false), polygonLayer.FeatureClass);
int rightOID = GetOID(edge.get_RightParents(false), polygonLayer.FeatureClass);
var edgeFeat = edgeLayer.FeatureClass.CreateFeature();
edgeFeat.set_Value(leftIdx, leftOID);
edgeFeat.set_Value(rightIdx, rightOID);
var geom = ((IClone)edge.Geometry).Clone() as IGeometry;
FixZs(geom);
edgeFeat.Shape = geom;
edgeFeat.Store();
}
private void FixZs(IGeometry geom)
{
// no need for z's
var zAware = geom as IZAware;
if (zAware != null && zAware.ZAware)
{
zAware.ZAware = false;
zAware.DropZs();
}
}
private int GetFieldIdx(IFeatureClass fc,string fldName)
{
int idx = fc.Fields.FindField(fldName);
if (idx == -1)
throw new Exception(String.Format("Field {0} not found on {1}", fldName, ((IDataset)fc).Name));
return idx;
}
private int GetOID(IEnumTopologyParent parents, IFeatureClass parentFC)
{
int oid = -1;
for (int i = 0; i < parents.Count; i++)
{
var parent = parents.Next();
if (parent.m_pFC.ObjectClassID == parentFC.ObjectClassID)
oid = parent.m_FID;
}
return oid;
}