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 { /// /// 求两个图形相交部分 /// /// 图形1 /// 图形2 /// 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; } } /// /// 获取图形最小角的角度 /// /// /// 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 rings = new List(); 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; } /// /// 判断两个图形是否相交(不包含相邻的) /// /// /// /// 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; } /// /// 判断两个图形是否相邻 /// /// /// /// 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; } /// /// 判断两个图形是否是叠加关系(相邻的也算相交) /// /// /// /// 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; } /// /// 合并 /// /// /// /// 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; } /// /// pGeo1与pGeo2不同的部分 /// /// 图形1 /// 图形2 /// 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; } } /// /// pGeo1与pGeo2不同的部分(打散处理) /// /// 图形1 /// 图形2 /// public static List DifferenceWithSingle(IGeometry pGeo1, IGeometry pGeo2) { try { ITopologicalOperator pTopologBoundary = pGeo1 as ITopologicalOperator; IGeometry pResultGeo = pTopologBoundary.Difference(pGeo2); IsMuiltPart(pResultGeo, out List listGeometry); return listGeometry; } catch (Exception ex) { throw ex; } } /// /// 多部件处理 /// /// 任一要素 /// 多部件打散的列表 /// 是否为多部件 public static bool IsMuiltPart(IGeometry pGeometry, out List listGeometry) { listGeometry = new List(); 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; } /// /// 从源数据集获取字段集合 /// /// 源数据集 /// 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; } /// /// 打开要素类(根据匹配符) /// /// /// /// 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; } } /// /// 面转线 /// /// /// 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; } /// /// 判断图形1是否包含图形2 /// /// 图形1 /// 图形2 /// 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; } } } }