You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
572 lines
22 KiB
572 lines
22 KiB
using ESRI.ArcGIS.Geodatabase; |
|
using ESRI.ArcGIS.Geometry; |
|
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Text; |
|
using System.Threading.Tasks; |
|
|
|
namespace Kingo.RuleCheck.CheckHelper |
|
{ |
|
public class CommonHelper |
|
{ |
|
/// <summary> |
|
/// 求两个图形相交部分 |
|
/// </summary> |
|
/// <param name="pGeo1">图形1</param> |
|
/// <param name="pGeo2">图形2</param> |
|
/// <returns></returns> |
|
public static IGeometry InterSect(IGeometry pGeo1, IGeometry pGeo2) |
|
{ |
|
try |
|
{ |
|
IGeometry result = null; |
|
if (pGeo1 == null || pGeo2 == null) |
|
return null; |
|
ITopologicalOperator topo = pGeo1 as ITopologicalOperator; |
|
if (topo != null) |
|
{ |
|
topo.Simplify(); |
|
ITopologicalOperator topo2 = pGeo2 as ITopologicalOperator; |
|
topo2.Simplify(); |
|
if (pGeo1.GeometryType == esriGeometryType.esriGeometryPoint || pGeo2.GeometryType == esriGeometryType.esriGeometryPoint) |
|
{ |
|
result = topo.Intersect(pGeo2, esriGeometryDimension.esriGeometry0Dimension); |
|
} |
|
else if (pGeo1.GeometryType == esriGeometryType.esriGeometryPolyline || pGeo2.GeometryType == esriGeometryType.esriGeometryPolyline) |
|
{ |
|
result = topo.Intersect(pGeo2, esriGeometryDimension.esriGeometry1Dimension); |
|
} |
|
else |
|
{ |
|
result = topo.Intersect(pGeo2, pGeo2.Dimension); |
|
} |
|
if (result != null) |
|
{ |
|
ITopologicalOperator resultTopo = result as ITopologicalOperator; |
|
resultTopo.Simplify(); |
|
} |
|
return result; |
|
} |
|
return null; |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw ex; |
|
} |
|
} |
|
/// <summary> |
|
/// 获取图形最小角的角度 |
|
/// </summary> |
|
/// <param name="pGeo"></param> |
|
/// <returns></returns> |
|
public static double GetMinAngle(IGeometry pGeo, out string jsonGeometry) |
|
{ |
|
double rstAngle = -1; |
|
try |
|
{ |
|
jsonGeometry = string.Empty; |
|
if (pGeo == null || pGeo.IsEmpty) |
|
{ |
|
return rstAngle; |
|
} |
|
IPolygon4 poly4 = pGeo as IPolygon4; |
|
ITopologicalOperator topo = poly4 as ITopologicalOperator; |
|
if (topo != null) |
|
{ |
|
topo.Simplify(); |
|
} |
|
GeometryBag geoBag = null; |
|
try |
|
{ |
|
geoBag = poly4.ExteriorRingBag as GeometryBag; |
|
} |
|
catch (Exception ex) |
|
{ |
|
} |
|
if (geoBag == null) |
|
{ |
|
return rstAngle; |
|
} |
|
IGeometryCollection geoCollection = geoBag as IGeometryCollection; |
|
List<IGeometry> rings = new List<IGeometry>(); |
|
for (int j = 0; j < geoCollection.GeometryCount; j++) |
|
{ |
|
IGeometry geo = geoCollection.get_Geometry(j); |
|
rings.Add(geo); |
|
//内环图形 |
|
IGeometryBag InteriorBag = (pGeo as ESRI.ArcGIS.Geometry.IPolygon4).get_InteriorRingBag(geo as IRing); |
|
if (InteriorBag != null) |
|
{ |
|
IGeometryCollection InteriorRingGeometryCollection = InteriorBag as IGeometryCollection; |
|
for (int IR = 0; IR < InteriorRingGeometryCollection.GeometryCount; IR++) |
|
{ |
|
rings.Add(InteriorRingGeometryCollection.get_Geometry(IR)); |
|
} |
|
} |
|
} |
|
foreach (IGeometry ring in rings) |
|
{ |
|
if (ring.IsEmpty) continue; |
|
IPointCollection points = ring as IPointCollection; |
|
int num = points.PointCount - 1; |
|
for (int i = 0; i < num; i++) |
|
{ |
|
IPoint p1 = null; |
|
IPoint p2 = points.get_Point(i); |
|
IPoint p3 = null; |
|
if (i == 0) |
|
{ |
|
p1 = points.get_Point(num - 1); |
|
p3 = points.get_Point(i + 1); |
|
} |
|
else if (i == num - 1) |
|
{ |
|
p1 = points.get_Point(i - 1); |
|
p3 = points.get_Point(0); |
|
} |
|
else |
|
{ |
|
p1 = points.get_Point(i - 1); |
|
p3 = points.get_Point(i + 1); |
|
} |
|
double angle = GetAngle(p2, p1, p3); |
|
if (rstAngle == -1) |
|
{ |
|
jsonGeometry = GeometryConvertHelper.GeometryToJsonString(p2); |
|
rstAngle = angle; |
|
} |
|
else |
|
{ |
|
if (rstAngle > angle) |
|
{ |
|
jsonGeometry = GeometryConvertHelper.GeometryToJsonString(p2); |
|
rstAngle = angle; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw ex; |
|
} |
|
return rstAngle; |
|
} |
|
private static double GetAngle(IPoint cenPoint, IPoint firstPoint, IPoint secondPoint) |
|
{ |
|
double ma_x = firstPoint.X - cenPoint.X; |
|
double ma_y = firstPoint.Y - cenPoint.Y; |
|
double mb_x = secondPoint.X - cenPoint.X; |
|
double mb_y = secondPoint.Y - cenPoint.Y; |
|
double v1 = (ma_x * mb_x) + (ma_y * mb_y); |
|
double ma_val = Math.Sqrt(ma_x * ma_x + ma_y * ma_y); |
|
double mb_val = Math.Sqrt(mb_x * mb_x + mb_y * mb_y); |
|
if (ma_val * mb_val == 0) |
|
{ |
|
return -1; |
|
} |
|
double cosM = v1 / (ma_val * mb_val); |
|
double angleAMB = Math.Acos(cosM) * 180 / Math.PI; |
|
return angleAMB; |
|
} |
|
|
|
/// <summary> |
|
/// 判断两个图形是否相交(不包含相邻的) |
|
/// </summary> |
|
/// <param name="pGeo1"></param> |
|
/// <param name="pGeo2"></param> |
|
/// <returns></returns> |
|
public static bool IsInterSect(IGeometry pGeo1, IGeometry pGeo2) |
|
{ |
|
IGeometry geo = InterSect(pGeo1, pGeo2); |
|
if (geo == null || geo.IsEmpty) |
|
{ |
|
return false; |
|
} |
|
if (geo.Dimension == esriGeometryDimension.esriGeometry2Dimension) |
|
{ |
|
IArea area = geo as IArea; |
|
if (area == null) |
|
{ |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
/// <summary> |
|
/// 判断两个图形是否相邻 |
|
/// </summary> |
|
/// <param name="pGeo1"></param> |
|
/// <param name="pGeo2"></param> |
|
/// <returns></returns> |
|
public static bool IsAdjacent(IGeometry pGeo1, IGeometry pGeo2) |
|
{ |
|
bool result = false; |
|
//IPolyline polyline; |
|
IRelationalOperator topoOper = pGeo1 as IRelationalOperator; |
|
result = topoOper.Touches(pGeo2); |
|
if (result) |
|
{ |
|
ITopologicalOperator topo = pGeo1 as ITopologicalOperator; |
|
if (topo != null) |
|
{ |
|
topo.Simplify(); |
|
ITopologicalOperator topo2 = pGeo2 as ITopologicalOperator; |
|
topo2.Simplify(); |
|
IGeometry geo = topo.Intersect(pGeo2, esriGeometryDimension.esriGeometry1Dimension); |
|
if (geo == null) |
|
{ |
|
result = false; |
|
} |
|
else if (geo.IsEmpty) |
|
{ result = false; } |
|
} |
|
} |
|
return result; |
|
//IPolyline polyline; |
|
//ITopologicalOperator topoOper = pGeo1 as ITopologicalOperator; |
|
//polyline = topoOper.Intersect(pGeo2, esriGeometryDimension.esriGeometry1Dimension) as IPolyline; |
|
//if (polyline != null && !polyline.IsEmpty) |
|
//{ |
|
// return true; |
|
//} |
|
//return false; |
|
} |
|
|
|
/// <summary> |
|
/// 判断两个图形是否是叠加关系(相邻的也算相交) |
|
/// </summary> |
|
/// <param name="pGeo1"></param> |
|
/// <param name="pGeo2"></param> |
|
/// <returns></returns> |
|
public static bool IsOverlaps(IGeometry pGeo1, IGeometry pGeo2) |
|
{ |
|
if (pGeo1.SpatialReference.FactoryCode != pGeo2.SpatialReference.FactoryCode) |
|
{ |
|
pGeo2.Project(pGeo1.SpatialReference); |
|
} |
|
ITopologicalOperator topological = pGeo1 as ITopologicalOperator; |
|
if (topological != null && !topological.IsKnownSimple) |
|
{ |
|
topological.Simplify(); |
|
} |
|
ITopologicalOperator topological2 = pGeo2 as ITopologicalOperator; |
|
if (topological2 != null && !topological2.IsKnownSimple) |
|
{ |
|
topological2.Simplify(); |
|
} |
|
IRelationalOperator relational = pGeo1 as IRelationalOperator; |
|
if (relational != null) |
|
{ |
|
bool b = relational.Overlaps(pGeo2); |
|
if (!b) |
|
{ |
|
relational = pGeo1 as IRelationalOperator; |
|
b = relational.Touches(pGeo2); |
|
} |
|
return b; |
|
} |
|
return false; |
|
} |
|
|
|
|
|
/// <summary> |
|
/// 合并 |
|
/// </summary> |
|
/// <param name="pGeo1"></param> |
|
/// <param name="pGeo2"></param> |
|
/// <returns></returns> |
|
public static IGeometry Union(IGeometry pGeo1, IGeometry pGeo2) |
|
{ |
|
if (pGeo1==null && pGeo2 != null) |
|
{ |
|
return pGeo2; |
|
} |
|
if (pGeo1 != null && pGeo2 == null) |
|
{ |
|
return pGeo1; |
|
} |
|
ITopologicalOperator pTopologBoundary = pGeo1 as ITopologicalOperator; |
|
IGeometry pUnionGeo = pTopologBoundary.Union(pGeo2); |
|
|
|
return pUnionGeo; |
|
} |
|
|
|
/// <summary> |
|
/// pGeo1与pGeo2不同的部分 |
|
/// </summary> |
|
/// <param name="pGeo1">图形1</param> |
|
/// <param name="pGeo2">图形2</param> |
|
/// <returns></returns> |
|
public static IGeometry Difference(IGeometry pGeo1, IGeometry pGeo2) |
|
{ |
|
try |
|
{ |
|
ITopologicalOperator pTopologBoundary = pGeo1 as ITopologicalOperator; |
|
IGeometry pResultGeo = pTopologBoundary.Difference(pGeo2); |
|
return pResultGeo; |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw ex; |
|
} |
|
} |
|
|
|
|
|
/// <summary> |
|
/// pGeo1与pGeo2不同的部分(打散处理) |
|
/// </summary> |
|
/// <param name="pGeo1">图形1</param> |
|
/// <param name="pGeo2">图形2</param> |
|
/// <returns></returns> |
|
public static List<IGeometry> DifferenceWithSingle(IGeometry pGeo1, IGeometry pGeo2) |
|
{ |
|
try |
|
{ |
|
ITopologicalOperator pTopologBoundary = pGeo1 as ITopologicalOperator; |
|
IGeometry pResultGeo = pTopologBoundary.Difference(pGeo2); |
|
IsMuiltPart(pResultGeo, out List<IGeometry> listGeometry); |
|
return listGeometry; |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw ex; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 多部件处理 |
|
/// </summary> |
|
/// <param name="pGeometry">任一要素</param> |
|
/// <param name="listGeometry">多部件打散的列表</param> |
|
/// <returns>是否为多部件</returns> |
|
public static bool IsMuiltPart(IGeometry pGeometry, out List<IGeometry> listGeometry) |
|
{ |
|
listGeometry = new List<IGeometry>(); |
|
IGeometryCollection pGeoColl = pGeometry as IGeometryCollection; |
|
if (pGeoColl == null) |
|
{ |
|
return false; |
|
} |
|
if (pGeoColl.GeometryCount <= 1) |
|
{ |
|
listGeometry.Add(pGeometry); |
|
return false; |
|
} |
|
|
|
IPolygon pGeoPolygon = pGeometry as IPolygon; |
|
int iRCnt = pGeoPolygon.ExteriorRingCount; |
|
if (iRCnt >= 1) |
|
{ |
|
IGeometryBag pExRings = (pGeometry as IPolygon4).ConnectedComponentBag; |
|
IGeometryCollection geoColl = pExRings as IGeometryCollection; |
|
for (int i = 0; i < iRCnt; i++) |
|
{ |
|
if (pGeometry.GeometryType == esriGeometryType.esriGeometryPolygon) |
|
{ |
|
IGeometry newGeom = geoColl.Geometry[i]; |
|
newGeom.SpatialReference = pGeometry.SpatialReference; |
|
IGeometryCollection newGeoColl = new PolygonClass(); |
|
newGeoColl.AddGeometryCollection(newGeom as IGeometryCollection); |
|
IGeometry pGeoNew2 = newGeoColl as IGeometry; |
|
if (pGeoNew2 == null || pGeoNew2.IsEmpty) |
|
{ |
|
continue; |
|
} |
|
if (pGeoNew2.SpatialReference == null && pGeometry.SpatialReference != null) |
|
{ |
|
pGeoNew2.SpatialReference = pGeometry.SpatialReference; |
|
} |
|
listGeometry.Add(pGeoNew2); |
|
} |
|
} |
|
if (iRCnt > 1) |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
/// <summary> |
|
/// 从源数据集获取字段集合 |
|
/// </summary> |
|
/// <param name="fClass">源数据集</param> |
|
/// <returns></returns> |
|
public static IFields GetFieldsBySource(IFeatureClass fClass) |
|
{ |
|
IFields flds = new FieldsClass(); |
|
IFieldsEdit fldsEdit = flds as IFieldsEdit; |
|
for (int i = 0; i < fClass.Fields.FieldCount; i++) |
|
{ |
|
if (!fClass.Fields.Field[i].Required) //过滤必要字段 Geometry字段为必要字段但可编辑 |
|
fldsEdit.AddField(fClass.Fields.Field[i]); |
|
} |
|
|
|
//修改IField字段 |
|
IField pGeometryField = fClass.Fields.get_Field(fClass.FindField(fClass.ShapeFieldName)); |
|
|
|
IGeometryDef pGeomDef = new GeometryDefClass(); |
|
IGeometryDefEdit pGeomDefEdit = pGeomDef as IGeometryDefEdit; |
|
pGeomDefEdit.GeometryType_2 = pGeometryField.GeometryDef.GeometryType; |
|
pGeomDefEdit.SpatialReference_2 = pGeometryField.GeometryDef.SpatialReference; |
|
|
|
IFieldEdit pGeometryFieldEdit = pGeometryField as IFieldEdit; |
|
pGeometryFieldEdit.GeometryDef_2 = pGeomDefEdit; |
|
fldsEdit.AddField(pGeometryField); |
|
|
|
return flds; |
|
} |
|
|
|
/// <summary> |
|
/// 打开要素类(根据匹配符) |
|
/// </summary> |
|
/// <param name="pWorkspace"></param> |
|
/// <param name="wild_card"></param> |
|
/// <returns></returns> |
|
public static IFeatureClass GetFeatureClass(IWorkspace pWorkspace, string wild_card) |
|
{ |
|
IEnumDatasetName datasetNames = pWorkspace.DatasetNames[esriDatasetType.esriDTFeatureClass]; |
|
datasetNames.Reset(); |
|
IDatasetName dsName; |
|
string sName = string.Empty; |
|
bool hasClass = false; |
|
while ((dsName = datasetNames.Next()) != null) |
|
{ |
|
sName = dsName.Name; |
|
if (sName.Contains(wild_card)) |
|
{ |
|
hasClass = true; |
|
break; |
|
} |
|
} |
|
if (dsName != null) |
|
System.Runtime.InteropServices.Marshal.ReleaseComObject(dsName); |
|
System.Runtime.InteropServices.Marshal.ReleaseComObject(datasetNames); |
|
return hasClass ? (pWorkspace as IFeatureWorkspace).OpenFeatureClass(sName) : null; |
|
} |
|
public static void SetGeoDatasetSpatialReference(IWorkspace pWS, ISpatialReference pSR, double pTolerance) |
|
{ |
|
try |
|
{ |
|
//double a = 0; |
|
//double b = 0; |
|
//double c = 0; |
|
//double d = 0; |
|
//pSR.SetDomain(-100000000, 0, 0, 0); |
|
//pSR.GetDomain(out a, out b, out c, out d); |
|
if (pSR != null) |
|
{ |
|
//ISpatialReferenceResolution toleranceResolution = pSR as ISpatialReferenceResolution; |
|
//toleranceResolution.set_XYResolution(true, 0.00005); |
|
ISpatialReferenceTolerance tolerance = pSR as ISpatialReferenceTolerance; |
|
if (tolerance != null) |
|
{ |
|
tolerance.XYTolerance = pTolerance; |
|
tolerance.ZTolerance = pTolerance; |
|
tolerance.MTolerance = pTolerance; |
|
} |
|
} |
|
IEnumDataset pEnumDataset = pWS.Datasets[esriDatasetType.esriDTFeatureDataset]; |
|
IDataset ds = null; |
|
if (pEnumDataset != null) |
|
{ |
|
while ((ds = pEnumDataset.Next()) != null) |
|
{ |
|
if (ds is IGeoDataset) |
|
{ |
|
if ((ds as IGeoDataset).SpatialReference != pSR) |
|
(ds as IGeoDatasetSchemaEdit).AlterSpatialReference(pSR); |
|
|
|
} |
|
} |
|
} |
|
pEnumDataset = pWS.Datasets[esriDatasetType.esriDTFeatureClass]; |
|
if (pEnumDataset == null) |
|
{ |
|
return; |
|
} |
|
while ((ds = pEnumDataset.Next()) != null) |
|
{ |
|
if (ds is IGeoDataset) |
|
{ |
|
if ((ds as IGeoDataset).SpatialReference != pSR) |
|
(ds as IGeoDatasetSchemaEdit).AlterSpatialReference(pSR); |
|
} |
|
} |
|
//设置坐标参考精度XYUnits 为二万分之一 |
|
try |
|
{ |
|
pWS.ExecuteSQL(string.Format("UPDATE GDB_SpatialRefs SET XYUnits = 20000 ,XYTolerance = {0}", pTolerance)); |
|
//pWS.ExecuteSQL("UPDATE GDB_SpatialRefs SET FalseX=0,FalseY=0,XYUnits=100000,FalseZ=0,ZUnits=0,FalseM=0,MUnits=0,XYTolerance=0.0001,ZTolerance=0,MTolerance=0"); |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw new Exception("设置坐标参考坐标精度和容差异常:" + ex.Message); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw ex; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 面转线 |
|
/// </summary> |
|
/// <param name="pGeom"></param> |
|
/// <returns></returns> |
|
public static IPolyline GeometryToPolyline(IGeometry pGeom) |
|
{ |
|
IPolygon polygon = pGeom as IPolygon; |
|
ITopologicalOperator topo = polygon as ITopologicalOperator; |
|
//获取面的边,面的边是线 |
|
IPolyline polyline = topo.Boundary as IPolyline; |
|
return polyline; |
|
//IGeometryCollection col = polygon as IGeometryCollection; |
|
//IRing ring = col.get_Geometry(0) as IRing; |
|
//IPointCollection pc = ring as IPointCollection; |
|
//IPointCollection polyline = new PolylineClass(); |
|
//for (int i = 0; i < pc.PointCount; i++) |
|
//{ |
|
// IPoint p = pc.get_Point(i); |
|
// polyline.AddPoint(p); |
|
//} |
|
//return polyline as IPolyline; |
|
} |
|
|
|
/// <summary> |
|
/// 判断图形1是否包含图形2 |
|
/// </summary> |
|
/// <param name="pGeo1">图形1</param> |
|
/// <param name="pGeo2">图形2</param> |
|
/// <returns></returns> |
|
public static bool IsContains(IGeometry pGeo1, IGeometry pGeo2) |
|
{ |
|
try |
|
{ |
|
ITopologicalOperator topological = pGeo1 as ITopologicalOperator; |
|
if (topological != null && !topological.IsKnownSimple) |
|
{ |
|
topological.Simplify(); |
|
} |
|
ITopologicalOperator topological2 = pGeo2 as ITopologicalOperator; |
|
pGeo2.SpatialReference = pGeo1.SpatialReference; |
|
if (topological2 != null && !topological2.IsKnownSimple) |
|
{ |
|
topological2.Simplify(); |
|
} |
|
IRelationalOperator relational = pGeo1 as IRelationalOperator; |
|
if (relational != null) |
|
{ |
|
return relational.Contains(pGeo2); |
|
} |
|
return false; |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw ex; |
|
} |
|
} |
|
} |
|
}
|
|
|