using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.Geometry; using KGIS.Framework.AE; using KGIS.Framework.AE.ExtensionMethod; using KGIS.Framework.Utils; using KGIS.Framework.Utils.ExtensionMethod; using System; using System.Collections.Generic; using System.Data; using System.Runtime.InteropServices; namespace Kingo.PluginServiceInterface.Helper { /// /// AE开发公共类 /// public static class AECommonHelper { public static DataTable GetTableByFeatureClass(IFeatureClass featureClass, IQueryFilter queryFilter = null) { DataTable dataTable = new DataTable(); ITable tableTemp = featureClass as ITable; int fieldCount = tableTemp.Fields.FieldCount; try { for (int i = 0; i < fieldCount; i++) { IField field = tableTemp.Fields.Field[i]; dataTable.Columns.Add(field.Name, GetSystemType(field.Type)); } ICursor cursor = tableTemp.Search(queryFilter, true); IRow row = null; while ((row = cursor.NextRow()) != null) { DataRow dataRow = dataTable.NewRow(); for (int i = 0; i < fieldCount; i++) { object value = row.Value[i]; dataRow[i] = value; } dataTable.Rows.Add(dataRow); } if (cursor != null) Marshal.ReleaseComObject(cursor); } catch (Exception ex) { LogAPI.Debug("GetTableByFeatureClass异常:" + ex.Message); LogAPI.Debug("GetTableByFeatureClass异常:" + ex.StackTrace); } return dataTable; } private static Type GetSystemType(esriFieldType fieldType) { switch (fieldType) { case esriFieldType.esriFieldTypeSmallInteger: case esriFieldType.esriFieldTypeInteger: return typeof(int); case esriFieldType.esriFieldTypeSingle: return typeof(float); case esriFieldType.esriFieldTypeDouble: return typeof(double); case esriFieldType.esriFieldTypeDate: return typeof(DateTime); default: return typeof(string); } } /// /// 设置数据库容差 /// /// /// /// public static void SetGeoDatasetSpatialReference(IWorkspace pWS, ISpatialReference pSR, double pTolerance) { try { //KGIS.Framework.AE.GeoDBAPI.SetGeoDatasetSpatialReference(pWS, pSR, pTolerance); if (pSR != null) { ISpatialReferenceResolution toleranceResolution = pSR as ISpatialReferenceResolution; //toleranceResolution.ConstructFromHorizon(); //toleranceResolution.SetDefaultXYResolution(); toleranceResolution.set_XYResolution(true, 0.00005); if (pSR is ISpatialReferenceTolerance tolerance) { 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[ESRI.ArcGIS.Geodatabase.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); } } try { pWS.ExecuteSQL(string.Format("UPDATE GDB_SpatialRefs SET XYUnits = 20000 ,XYTolerance = {0}", pTolerance)); } catch (Exception ex) { throw new Exception("设置坐标参考坐标精度和容差异常:" + ex.Message); } } catch (Exception ex) { throw new Exception("设置坐标参考坐标精度和容差异常:" + ex.Message); } } #region GetPolygonFromWkt /// /// 从Wkt获取多边形 /// /// /// public static IGeometry GetPolygonFromWkt(string pointsStr) { try { if (string.IsNullOrWhiteSpace(pointsStr)) return null; if (!pointsStr.StartsWith("POLYGON") && !pointsStr.StartsWith("MULTIPOLYGON")) pointsStr = DispalySQ_Click(pointsStr); //OSGeo.OGR.Ogr.RegisterAll(); IGeometry geometry = new PolygonClass(); OSGeo.OGR.Geometry rstGeometry = OSGeo.OGR.Geometry.CreateFromWkt(pointsStr); byte[] geometryBytes = new byte[rstGeometry.WkbSize()]; rstGeometry.ExportToWkb(geometryBytes); IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3; int bytesLen = geometryBytes.Length; factory.CreateGeometryFromWkbVariant(geometryBytes, out geometry, out bytesLen); double area = (geometry as IArea).Area; IPolygon polygon = geometry as IPolygon; if (area < 0) { polygon.ReverseOrientation(); } polygon.Close(); ITopologicalOperator pBoundaryTop = polygon as ITopologicalOperator; pBoundaryTop.Simplify(); return geometry; } catch (Exception ex) { LogAPI.Debug("GetPolygonFromWkt异常:" + ex.Message); return null; } } private static string DispalySQ_Click(string Coord) { string SQstring = Coord.Replace('\r', ' ').ToTrim(); if (!string.IsNullOrWhiteSpace(SQstring)) { string[] rings = SQstring.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries); string coord = string.Empty; if (rings.Length == 1) { foreach (var geoRing in rings) { string strGeo = geoRing.Replace('\r', ' ').ToTrim(); if (strGeo.Split(new char[] { ';' }).Length < 10) strGeo = geoRing.Replace(";", ","); if (strGeo.Contains(";")) { coord = string.Format("POLYGON(("); string[] ps = strGeo.TrimEnd(';').Split(';'); foreach (var item in ps) { coord += item.Replace('\r', ' ').Replace(',', ' ') + ","; } } else { coord = string.Format("POLYGON(("); coord += strGeo; } coord = coord.TrimEnd(','); coord += "))"; } return coord; } else if (rings.Length > 1) { coord = "MULTIPOLYGON("; foreach (var ring in rings) { string Temp_Coordinate = string.Empty; string[] points = ring.TrimEnd(';').Split(';'); string strRing = "(("; if (points.Length == 1) { strRing += points[0]; } else { foreach (var item in points) { strRing += item.Replace(',', ' ') + ","; } } char[] charsToTrim = { ',' }; strRing = strRing.TrimEnd(charsToTrim); strRing = strRing.ToTrim(); strRing = strRing.TrimEnd(charsToTrim); strRing += ")),"; coord += strRing; } coord = coord.TrimEnd(','); coord += ")"; } return coord; //AreaEnvOfeat(ConvertWKTToIGeometry(SQstring)); } return string.Empty; } //public static IGeometry GetPolygonFromWkt(string pointsStr) //{ // IGeometry geometry = new PolygonClass(); // OSGeo.OGR.Geometry rstGeometry = OSGeo.OGR.Geometry.CreateFromWkt(pointsStr); // byte[] geometryBytes = new byte[rstGeometry.WkbSize()]; // rstGeometry.ExportToWkb(geometryBytes); // IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3; // int bytesLen = geometryBytes.Length; // factory.CreateGeometryFromWkbVariant(geometryBytes, out geometry, out bytesLen); // return geometry; //} //public static IGeometry GetPolygonFromWkt(string pointsStr) //{ // try // { // IGeometry geometry = new PolygonClass(); // OSGeo.OGR.Geometry rstGeometry = OSGeo.OGR.Geometry.CreateFromWkt(pointsStr); // byte[] geometryBytes = new byte[rstGeometry.WkbSize()]; // rstGeometry.ExportToWkb(geometryBytes); // IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3; // int bytesLen = geometryBytes.Length; // factory.CreateGeometryFromWkbVariant(geometryBytes, out geometry, out bytesLen); // IPolygon polygon = geometry as IPolygon; // polygon.Close(); // ITopologicalOperator pBoundaryTop = polygon as ITopologicalOperator; // pBoundaryTop.Simplify(); // return geometry; // } // catch (Exception ex) // { // LogAPI.Debug("GetPolygonFromWkt获取图形异常:" + ex); // throw ex; // } //} #endregion #region 要素存在尖锐角和局部狭长图形(即不允许存在一个角度小于10度,或局部图形狭长的情况) public static bool SharpAngleDataCheck(IGeometry geometry, ref List pointList, ref double angle) { if (geometry == null || geometry.IsEmpty) { return false; // 或者抛出一个异常,取决于你的错误处理策略 } try { angle = GetMinAngle(geometry, ref pointList); // 获取图形的最小角度 if (angle < 10) return true; ITopologicalOperator topo = geometry as ITopologicalOperator; if (topo == null) { // 记录日志并返回false或抛出异常 LogAPI.Debug("几何对象不支持ITopologicalOperator接口。"); return false; } IPolyline line1 = topo.Boundary as IPolyline; if (line1 == null) { // 记录日志并返回false或抛出异常 LogAPI.Debug("几何对象的边界不是IPolyline类型。"); return false; } double length1 = line1.Length; // 原始图形的周长 int pointCount1 = (geometry as IPointCollection).PointCount; if (geometry.GeometryType != esriGeometryType.esriGeometryPolygon) return false; // 确保负缓冲值不超过几何体的最小尺寸 IArea area = geometry as IArea; double bufferValue = -0.05; if (area != null && Math.Abs(bufferValue) > Math.Sqrt(area.Area)) { bufferValue = -Math.Sqrt(area.Area) / 2; // 动态调整缓冲值 } IGeometry geo = topo.Buffer(bufferValue); if (geo == null || geo.IsEmpty) { return false; // 或者抛出一个异常 } ITopologicalOperator topo2 = geo as ITopologicalOperator; if (topo2 == null) { // 记录日志并返回false或抛出异常 LogAPI.Debug("缓冲后的几何对象不支持ITopologicalOperator接口。"); return false; } IPolyline line2 = topo2.Boundary as IPolyline; if (line2 == null) { // 记录日志并返回false或抛出异常 LogAPI.Debug("缓冲后的几何对象的边界不是IPolyline类型。"); return false; } double length2 = line2.Length; // 向内缓冲后的图形的周长 double delta_length = length1 - length2; // 周长差 double avg_halfangle = 180 * (pointCount1 - 1 - 2) / (pointCount1 - 1) / 2; // 平均 double conner_normal_length = 2 * 0.05 / Math.Tan(avg_halfangle * (Math.PI / 180)); return (delta_length > 8 * conner_normal_length * (pointCount1 - 1)) || angle < 10; } catch (Exception ex) { LogAPI.Debug("SharpAngleDataCheck数据检查时发生异常,异常信息如下:"); LogAPI.Debug(ex); // 可以选择重新抛出异常,让调用者处理 // throw; return false; // 或者根据你的错误处理策略返回一个特定的值 } } public static bool SharpAngleDataCheck(IGeometry geometry, ref IPoint point, ref IPolyline polyline) { bool isSharpAngle = false; try { if (geometry == null) return isSharpAngle; double angle = GetMinAngle(geometry, ref point, ref polyline);//获取图形的最小角度 ITopologicalOperator topo = geometry as ITopologicalOperator; IPolyline line1 = topo.Boundary as IPolyline; double length1 = line1.Length;//原始图形的周长 int pointCount1 = (geometry as IPointCollection).PointCount; IGeometry geo = topo.Buffer(-0.05); ITopologicalOperator topo2 = geo as ITopologicalOperator; IPolyline line2 = topo2.Boundary as IPolyline; double length2 = line2.Length;//向内缓冲后的图形的周长 double delta_length = length1 - length2;//周长差 double avg_halfangle = 180 * (pointCount1 - 1 - 2) / (pointCount1 - 1) / 2;//平均 double conner_normal_length = 2 * 0.05 / Math.Tan(avg_halfangle * (Math.PI / 180)); if ((delta_length > 8 * conner_normal_length * (pointCount1 - 1)) || angle < 10) { if ((delta_length > 8 * conner_normal_length * (pointCount1 - 1)) && angle < 10) return true; else if (delta_length > 8 * conner_normal_length * (pointCount1 - 1)) return true; else if (angle < 10) return true; } //if (topo != null) // Marshal.ReleaseComObject(topo); //if (line1 != null) // Marshal.ReleaseComObject(line1); //if (topo2 != null) // Marshal.ReleaseComObject(topo2); //if (line2 != null) // Marshal.ReleaseComObject(line2); //if (geo != null) // Marshal.ReleaseComObject(geo); } catch (Exception ex) { LogAPI.Debug("数据检查时发生异常,异常信息如下:"); LogAPI.Debug(ex); } finally { //GC.Collect(); } return isSharpAngle; } public static double GetMinAngle(IGeometry pGeo, ref IPoint point, ref IPolyline polyline) { double result = -1; IPolygon4 poly4 = null; ITopologicalOperator topo = null; GeometryBag geoBag = null; IGeometryCollection geoCollection = null; try { if (pGeo == null || pGeo.IsEmpty) return result; poly4 = pGeo as IPolygon4; topo = poly4 as ITopologicalOperator; topo?.Simplify(); geoBag = poly4.ExteriorRingBag as GeometryBag; if (geoBag == null) return result; 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 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); } if ((p2.X == p1.X && p2.Y == p1.Y) || (p2.X == p3.X && p2.Y == p3.Y)) continue; double angle = GetAngle(p2, p1, p3); if (result == -1) { result = angle; } else { if (result > angle) { result = angle; point = p3; point.SpatialReference = p1.SpatialReference; polyline = (IPolyline)new PolylineClass(); polyline.SpatialReference = p1.SpatialReference; polyline.FromPoint = p1; polyline.ToPoint = p2; } } //Marshal.ReleaseComObject(p1); //Marshal.ReleaseComObject(p2); //Marshal.ReleaseComObject(p3); } //Marshal.ReleaseComObject(ring); } } catch (Exception ex) { LogAPI.Debug("获取最小角度异常:" + ex); throw ex; } finally { //if (poly4 != null) // Marshal.ReleaseComObject(poly4); //if (topo != null) // Marshal.ReleaseComObject(topo); //if (geoBag != null) // Marshal.ReleaseComObject(geoBag); //if (geoCollection != null) // Marshal.ReleaseComObject(geoCollection); } return result; } /// /// 获取最小角度 /// /// /// public static double GetMinAngle(IGeometry pGeo, ref List pointlist) { double result = -1; IPolygon4 poly4 = null; ITopologicalOperator topo = null; GeometryBag geoBag = null; IGeometryCollection geoCollection = null; pointlist = new List(); try { if (pGeo == null || pGeo.IsEmpty) return result; poly4 = pGeo as IPolygon4; topo = poly4 as ITopologicalOperator; topo?.Simplify(); geoBag = poly4.ExteriorRingBag as GeometryBag; if (geoBag == null) return result; 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 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); } if ((p2.X == p1.X && p2.Y == p1.Y) || (p2.X == p3.X && p2.Y == p3.Y) || (p1.X == p3.X && p1.Y == p3.Y)) continue; double angle = GetAngle(p2, p1, p3); if (double.IsNaN(angle)) continue; if (result == -1) { result = angle; pointlist.Add(p1); pointlist.Add(p2); pointlist.Add(p3); } else { if (double.IsNaN(result)) { result = angle; } if (result > angle) { result = angle; if (pointlist.Count > 0) pointlist.Clear(); pointlist.Add(p1); pointlist.Add(p2); pointlist.Add(p3); } } //Marshal.ReleaseComObject(p1); //Marshal.ReleaseComObject(p2); //Marshal.ReleaseComObject(p3); } //Marshal.ReleaseComObject(ring); } } catch (Exception ex) { LogAPI.Debug("获取最小角度异常:" + ex); throw ex; } finally { //if (poly4 != null) // Marshal.ReleaseComObject(poly4); //if (topo != null) // Marshal.ReleaseComObject(topo); //if (geoBag != null) // Marshal.ReleaseComObject(geoBag); //if (geoCollection != null) // Marshal.ReleaseComObject(geoCollection); } return result; } /// /// 计算角度 /// /// /// /// /// public 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; } #endregion #region Passive_Sharp_Repair /// /// 构成尖锐角较短的边与较长的边做垂线,构成一个直角三角形,将直角三角形擦除 /// /// /// /// /// public static IGeometry Passive_Sharp_Repair(IGeometry geometry) { List pointList = null; double angle1 = 0; try { //检查图形是否为尖锐角 if (AECommonHelper.SharpAngleDataCheck(geometry, ref pointList, ref angle1)) { if (angle1 > 10) { return geometry; }//仅修复图形为尖锐角的 if (pointList != null && pointList.Count == 3) { //构成尖锐角的两条边 IPoint pointmax = pointList[0]; IPolyline polylinemax = new PolylineClass(); polylinemax.FromPoint = pointList[0]; polylinemax.ToPoint = pointList[1]; IPoint pointmin = pointList[2]; IPolyline polylinemin = new PolylineClass(); polylinemin.FromPoint = pointList[2]; polylinemin.ToPoint = pointList[1]; IPolyline polyline_vertical = null;//获取较短的边做垂线 if (polylinemax.Length < polylinemin.Length) { IPolyline temppolylinemin = new PolylineClass(); temppolylinemin = polylinemax; polylinemax = polylinemin; polylinemin = temppolylinemin; IPoint temppoint = new PointClass(); temppoint = pointmax; pointmax = pointmin; pointmin = temppoint; } polyline_vertical = GetPerpendicularLine(polylinemin, true, polylinemin.Length); IPointCollection pPointCol = polyline_vertical as IPointCollection; IPoint fPoint = new PointClass(); IPoint ePoint = new PointClass(); object missing2 = Type.Missing; polyline_vertical.QueryPoint(esriSegmentExtension.esriExtendAtFrom, -1 * polylinemin.Length, false, fPoint); pPointCol.InsertPoints(0, 1, ref fPoint); polyline_vertical.QueryPoint(esriSegmentExtension.esriExtendAtTo, polylinemin.Length + polylinemin.Length, false, ePoint); pPointCol.AddPoint(ePoint, ref missing2, ref missing2); IPolyline polyline = pPointCol as IPolyline; ITopologicalOperator topo = polyline_vertical as ITopologicalOperator; IGeometry extendgeo = topo.Intersect(polylinemax, esriGeometryDimension.esriGeometry0Dimension); IPoint point = null; if (extendgeo.GeometryType == esriGeometryType.esriGeometryPoint) { point = extendgeo as IPoint; } else { if (extendgeo.GeometryType == esriGeometryType.esriGeometryMultipoint) { IPointCollection pointCollection = extendgeo as IPointCollection; if (pointCollection.PointCount > 0) { point = pointCollection.get_Point(0); } else { point = pointmax; } } } List points1 = new List(); IGeometry geometry1 = null; if (true) { IPoint minCenterPoint = getLineCenterPoint(polylinemin); IPoint maxCenterPoint = getLineCenterPoint(polylinemax); points1 = new List() { maxCenterPoint, pointList[1], minCenterPoint }; geometry1 = GenerateGeometryFromPoints(points1); } else { points1 = new List() { point, pointList[1], pointmin }; geometry1 = GenerateGeometryFromPoints(points1); } geometry1.SpatialReference = geometry.SpatialReference; if (geometry1 == null || geometry1.IsEmpty) { //仅四个点的图斑修复异常 return geometry; } else if (!geometry1.IsEmpty && geometry1.GetEllipseArea() > 30) { geometry1 = AECommonHelper.IndentationGeometry(geometry, geometry1, 30); } else if (!geometry1.IsEmpty && geometry1.GetEllipseArea() < 0.01) { geometry1 = AECommonHelper.ExpandableGeometry(geometry, geometry1, 0.01); } geometry = FeatureAPI.Difference(geometry, geometry1); if (geometry != null && !geometry.IsEmpty && AECommonHelper.SharpAngleDataCheck(geometry, ref pointList, ref angle1)) { geometry = Passive_Sharp_Repair(geometry); } else { return geometry; } } } else { return geometry; } return geometry; } catch (Exception ex) { return geometry; } } public static IPoint getLineCenterPoint(IPolyline pPolyline) { double d = pPolyline.Length; IPoint pPoint = new PointClass(); pPolyline.QueryPoint(esriSegmentExtension.esriNoExtension, d / 1.2, false, pPoint); return pPoint; } /// /// 获取尖锐角顶点位置外扩一段距离的垂线 /// /// /// clockwise顺时针 true为顺时针/false为逆时针 /// private static IPolyline GetPerpendicularLine(IPolyline baseLine, bool clockwise, double length = 1) { // 获取baseLine的第一个点作为起点 IPoint startPoint = baseLine.FromPoint; if (!startPoint.IsEmpty) { // 获取非起点的任一点 IPoint endPoint = baseLine.ToPoint; // 计算向量 double vectorX = endPoint.X - startPoint.X; double vectorY = endPoint.Y - startPoint.Y; // 旋转90度得到垂直向量 double perpendicularX = 0; double perpendicularY = 0; if (clockwise) { perpendicularX = -vectorY; perpendicularY = vectorX; } else { perpendicularX = vectorY; perpendicularY = -vectorX; } perpendicularX *= length / Math.Sqrt(perpendicularX * perpendicularX + perpendicularY * perpendicularY); perpendicularY *= length / Math.Sqrt(perpendicularX * perpendicularX + perpendicularY * perpendicularY); // 计算垂直线的终点 IPoint perpendicularEndPoint = new PointClass(); perpendicularEndPoint.X = startPoint.X + perpendicularX; perpendicularEndPoint.Y = startPoint.Y + perpendicularY; // 创建并返回垂直线 IPolyline perpendicularLine = new PolylineClass(); IPointCollection pointCollection = perpendicularLine as IPointCollection; pointCollection.AddPoint(startPoint); pointCollection.AddPoint(perpendicularEndPoint); return perpendicularLine; } return null; } /// /// 根据点集合生成图形 /// /// /// private static IGeometry GenerateGeometryFromPoints(List Points) { try { Ring ring = new RingClass(); object missing = Type.Missing; IPointCollection pointCollection2 = new MultipointClass(); if (Points != null && Points.Count == 3) { if (Points[0] != null && Points[1] != null && Points[2] != null)//Points中不为空 { pointCollection2.AddPoint(Points[0]); pointCollection2.AddPoint(Points[1]); pointCollection2.AddPoint(Points[2]); } } ring.AddPointCollection(pointCollection2); IGeometryCollection pointPolygon = new PolygonClass(); pointPolygon.AddGeometry(ring as IGeometry, ref missing, ref missing); IPolygon polyGonGeo = pointPolygon as IPolygon; //polyGonGeo.Close(); polyGonGeo.SimplifyPreserveFromTo(); return polyGonGeo as IGeometry; } catch (Exception ex) { throw ex; } } #endregion #region 图形操作类 /// /// 图斑外扩至“ExpandableArea”平 /// /// 参考图形 /// 向参考图形内扩图斑 /// 外扩至面积 /// public static IGeometry ExpandableGeometry(IGeometry geometryBG, IGeometry Insergeometry, double ExpandableArea = 30) { IGeometry TempInsergeometry = null; try { IGeometry geometry = null; ITopologicalOperator topo = Insergeometry as ITopologicalOperator; double WKArea = 0; double WKBoundary = 0.1; while (WKArea <= ExpandableArea) { geometry = topo.Buffer(WKBoundary); geometry = GeometryConvertHelper.ConvertWKTToIGeometry(GeometryConvertHelper.ConvertIGeoemtryToWKT(geometry)); TempInsergeometry = FeatureAPI.InterSect(geometryBG, geometry); WKArea = TempInsergeometry.GetEllipseArea(); WKBoundary += 0.1; } if (geometry != null) Marshal.ReleaseComObject(geometry); return TempInsergeometry; } catch (Exception ex) { //防止抛出异常 LogAPI.Debug("ExpandableGeometry执行异常:" + ex.Message + ex.StackTrace); return TempInsergeometry ?? Insergeometry; } } /// /// 图斑内陷至“ExpandableArea”平 /// /// 参考图形 /// 向参考图形内扩图斑 /// 内陷至面积 /// public static IGeometry IndentationGeometry(IGeometry geometryBG, IGeometry Insergeometry, double ExpandableArea = 30) { IGeometry geometry = EraseGeometry(geometryBG, Insergeometry); if (geometry.IsEmpty || geometry.GetEllipseArea() == 0) { return Insergeometry; } IGeometry TempInsergeometry = null; ITopologicalOperator topo = geometry as ITopologicalOperator; double WKArea = Insergeometry.GetEllipseArea().ToDouble(2); double WKBoundary = 0.1; while (WKArea > ExpandableArea) { geometry = topo.Buffer(WKBoundary); geometry = GeometryConvertHelper.ConvertWKTToIGeometry(GeometryConvertHelper.ConvertIGeoemtryToWKT(geometry)); TempInsergeometry = FeatureAPI.Difference(Insergeometry, geometry); WKArea = TempInsergeometry.GetEllipseArea(); WKBoundary += 0.2; } if (geometry != null) Marshal.ReleaseComObject(geometry); return TempInsergeometry; } /// /// 图形操作 /// /// 被擦除项 /// 擦除项 /// public static IGeometry EraseGeometry(IGeometry pGeo1, IGeometry pGeo2) { try { IGeometry geometTemp = FeatureAPI.InterSect(pGeo1, pGeo2); if (pGeo1 == null || pGeo2 == null || geometTemp == null || geometTemp.IsEmpty) { return null; } if (pGeo1 is ITopologicalOperator topologicalOperator) { topologicalOperator.Simplify(); IGeometry geometry = FeatureAPI.Difference(pGeo1, geometTemp); (geometry as ITopologicalOperator).Simplify(); return geometry; } return null; } catch (Exception) { throw; } } #endregion #region 复制IFeature属性 /// /// 同图层图斑属性赋值 /// /// /// public static void CopyFeatureAtt(this IFeature tFeature, IFeature sFeature) { try { for (int i = 0; i < sFeature.Class.Fields.FieldCount; i++) { IField field = sFeature.Class.Fields.Field[i]; if (!field.Editable || field.Name.ToUpper().Contains("SHAPE")) continue; if (tFeature.Class.FindField(field.Name) != -1) tFeature.Value[tFeature.Class.FindField(field.Name)] = sFeature.Value[i]; } } catch (Exception ex) { LogAPI.Debug("CopyFeatureAtt执行异常:" + ex.Message); } } public static void CopyFeatureAtt_1(this IFeature tFeature, IFeature sFeature) { try { for (int i = 0; i < tFeature.Class.Fields.FieldCount; i++) { IField field = tFeature.Class.Fields.Field[i]; if (!field.Editable || field.Name.ToUpper().Contains("SHAPE")) continue; if (sFeature.Class.FindField(field.Name + "_1") != -1) tFeature.Value[i] = sFeature.Value[sFeature.Class.FindField(field.Name + "_1")]; } } catch (Exception ex) { LogAPI.Debug(ex.Message); } } /// /// 通过基础库图斑赋值过程数据变更前属性 /// /// /// public static void AssignBGQFeatureAtt(this IFeature tFeature, IFeature sFeature) { try { for (int i = 0; i < sFeature.Class.Fields.FieldCount; i++) { IField field = sFeature.Class.Fields.Field[i]; if (!field.Editable || field.Name.ToUpper().Contains("SHAPE")) continue; if (tFeature.Class.FindField("BGQ" + field.Name) != -1) tFeature.Value[tFeature.Class.FindField("BGQ" + field.Name)] = sFeature.Value[i]; } } catch (Exception ex) { LogAPI.Debug("AssignBGQFeatureAtt执行异常:" + ex.Message); } } /// /// 通过更新层/基础库图斑赋值过程数据变更后属性 /// /// /// public static void AssignBGHFeatureAtt(this IFeature tFeature, IFeature sFeature) { try { for (int i = 0; i < sFeature.Class.Fields.FieldCount; i++) { IField field = sFeature.Class.Fields.Field[i]; if (!field.Editable || field.Name.ToUpper().Contains("SHAPE")) continue; if (tFeature.Class.FindField("BGH" + field.Name) != -1) tFeature.Value[tFeature.Class.FindField("BGH" + field.Name)] = sFeature.Value[i]; } } catch (Exception ex) { LogAPI.Debug("AssignBGHFeatureAtt执行异常:" + ex.Message); } } #endregion } }