方法一:基于arcgis engine 处理,因为基于AE的拓扑检查规则中只有线自相交检查,所以这里的处理逻辑就是遍历面要素,然后渠道每个面要素的内外环,再独立构建成线要素,使用拓扑去检查,代码如下:
void topTest()
{
string topGdbPath = @"E:\Data\topology.gdb";
string err = "";
IWorkspaceFactory pWf = new FileGDBWorkspaceFactoryClass();
IWorkspace workspace = pWf.OpenFromFile(topGdbPath , 0)
IFeatureWorkspace pFeatureWorkspace = pWs as IFeatureWorkspace;
string mes = "";
IFeatureClass featureClass =pFeatureWorkspace.OpenFeatureClass("SLZY");
try
{
long fCount = featureClass.FeatureCount(null);
IFeatureCursor cursor = featureClass.Search(null, true);
IFeature feature = cursor.NextFeature();
while (feature != null)
{
int ind = feature.Fields.FindField("OBJECTID");
string oid = feature.Value[ind].ToString();
IGeometryBag pgeometryBag = null;
if (CheckFeatureSelfInsect2(feature))
{
mes += String.Format("图层OBJECTID为{0}的要素存在自相交错误", feature.OID);
}
feature = cursor.NextFeature();
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(cursor);
if (feature != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(feature);
}
catch (Exception ex)
{
}
}
private bool CheckFeatureSelfInsect2(IFeature feature)
{
ISpatialReference prj = feature.Shape.SpatialReference;
IPolygon4 pPolygon4 = feature.Shape as IPolygon4;
IGeometryBag pOutGeometryBag = pPolygon4.ExteriorRingBag; //获取外部环
IGeometryCollection pOutGmtyCollection = pOutGeometryBag as IGeometryCollection;
bool isInsect = false;
for (int i = 0; i < pOutGmtyCollection.GeometryCount; i++) //对外部环遍历
{
IGeometry pOutRing = pOutGmtyCollection.get_Geometry(i); //外部环
IPointCollection pCol = pOutRing as IPointCollection;//外环节点集合
IPointCollection polylinePointCollection = new PolylineClass();
for (int j = 0; j < pCol.PointCount - 1; j++)
{
polylinePointCollection.AddPoint(pCol.get_Point(j));
}
IPolyline pPolyline = polylinePointCollection as IPolyline;
isInsect = Check(pPolyline);
if (isInsect)
break;
IGeometryBag pInteriotGeometryBag = pPolygon4.get_InteriorRingBag(pOutRing as IRing); //获取内部环
IGeometryCollection pInteriorGeometryCollection = pInteriotGeometryBag as IGeometryCollection;
for (int k = 0; k < pInteriorGeometryCollection.GeometryCount; k++)
{
IGeometry pInteriorGeometry = pInteriorGeometryCollection.get_Geometry(k);
IPointCollection pincol = pInteriorGeometry as IPointCollection;//内环节点集合
IPointCollection polylineInPointCollection = new PolylineClass();
for (int j = 0; j < pincol.PointCount - 1; j++)
{
polylineInPointCollection.AddPoint(pincol.get_Point(j));
}
IPolyline pInPolyline = polylineInPointCollection as IPolyline;
isInsect = Check(pInPolyline);
if (isInsect)
break;
}
if (isInsect)
break;
}
return isInsect;
}
bool Check(IPolyline polylineA)
{
ITopologicalOperator3 pTopologicalOperator3 = polylineA as ITopologicalOperator3;
pTopologicalOperator3.IsKnownSimple_2 = false;
// 检查自相交
esriNonSimpleReasonEnum reason = esriNonSimpleReasonEnum.esriNonSimpleOK;
if (!pTopologicalOperator3.get_IsSimpleEx(out reason))
{
if (reason == esriNonSimpleReasonEnum.esriNonSimpleSelfIntersections)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(polylineA);
return true;
}
}
return false;
}
方法二:基于NetTopologySuite类库, NetTopologySuite库里有专门判断图形是否有效的方法,使用这个方法也可检查,因为我原框架是基于arcgis engine的,所以这里还存在要将esri的geometry转换为GeoAPI.Geometries.IGeometry 代码如下:
//需引用以下库
using NetTopologySuite.IO;
using NetTopologySuite.Geometries;
using NetTopologySuite.Operation.Valid;
void topTest()
{
string topGdbPath = @"E:\Data\topology.gdb";
string err = "";
IWorkspaceFactory pWf = new FileGDBWorkspaceFactoryClass();
IWorkspace workspace = pWf.OpenFromFile(topGdbPath , 0)
IFeatureWorkspace pFeatureWorkspace = pWs as IFeatureWorkspace;
string mes = "";
IFeatureClass featureClass =pFeatureWorkspace.OpenFeatureClass("SLZY");
try
{
long fCount = featureClass.FeatureCount(null);
IFeatureCursor cursor = featureClass.Search(null, true);
IFeature feature = cursor.NextFeature();
while (feature != null)
{
int ind = feature.Fields.FindField("OBJECTID");
string oid = feature.Value[ind].ToString();
if (!CheckIsvalid(feature.ShapeCopy) )
{
mes += String.Format("图层OBJECTID为{0}的要素存在自相交错误", feature.OID);
}
feature = cursor.NextFeature();
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(cursor);
if (feature != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(feature);
}
catch (Exception ex)
{
}
}
public bool CheckIsvalid(IGeometry polygon)
{
var validator = new IsValidOp(ConvertESRIToGeoAPI(polygon));
return validator.IsValid;
}
public GeoAPI.Geometries.IGeometry ConvertESRIToGeoAPI(IGeometry geometry)
{
byte[] wkb = ConvertGeometryToWKB(geometry);
WKBReader reader = new WKBReader();
return reader.Read(wkb);
}
public string ConvertGeometryToWKT(IGeometry geometry)
{
byte[] b = ConvertGeometryToWKB(geometry);
WKBReader reader = new WKBReader();
GeoAPI.Geometries.IGeometry g = reader.Read(b);
WKTWriter writer = new WKTWriter();
return writer.Write(g);
}
public byte[] ConvertGeometryToWKB(IGeometry geometry)
{
IWkb wkb = geometry as IWkb;
IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3;
byte[] b = factory.CreateWkbVariantFromGeometry(geometry) as byte[];
return b;
}