森林草原湿地荒漠调查
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.
 
 
 

1050 lines
45 KiB

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
{
/// <summary>
/// AE开发公共类
/// </summary>
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);
}
}
/// <summary>
/// 设置数据库容差
/// </summary>
/// <param name="pWS"></param>
/// <param name="pSR"></param>
/// <param name="pTolerance"></param>
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
/// <summary>
/// 从Wkt获取多边形
/// </summary>
/// <param name="pointsStr"></param>
/// <returns></returns>
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<IPoint> 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<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 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;
}
/// <summary>
/// 获取最小角度
/// </summary>
/// <param name="pGeo"></param>
/// <returns></returns>
public static double GetMinAngle(IGeometry pGeo, ref List<IPoint> pointlist)
{
double result = -1;
IPolygon4 poly4 = null;
ITopologicalOperator topo = null;
GeometryBag geoBag = null;
IGeometryCollection geoCollection = null;
pointlist = new List<IPoint>();
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<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 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;
}
/// <summary>
/// 计算角度
/// </summary>
/// <param name="cenPoint"></param>
/// <param name="firstPoint"></param>
/// <param name="secondPoint"></param>
/// <returns></returns>
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
/// <summary>
/// 构成尖锐角较短的边与较长的边做垂线,构成一个直角三角形,将直角三角形擦除
/// </summary>
/// <param name="pointList"></param>
/// <param name="bg_geometry"></param>
/// <param name="diffgeo"></param>
/// <returns></returns>
public static IGeometry Passive_Sharp_Repair(IGeometry geometry)
{
List<IPoint> 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<IPoint> points1 = new List<IPoint>();
IGeometry geometry1 = null;
if (true)
{
IPoint minCenterPoint = getLineCenterPoint(polylinemin);
IPoint maxCenterPoint = getLineCenterPoint(polylinemax);
points1 = new List<IPoint>() { maxCenterPoint, pointList[1], minCenterPoint };
geometry1 = GenerateGeometryFromPoints(points1);
}
else
{
points1 = new List<IPoint>() { 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;
}
/// <summary>
/// 获取尖锐角顶点位置外扩一段距离的垂线
/// </summary>
/// <param name="baseLine"></param>
/// <param name="direction">clockwise顺时针 true为顺时针/false为逆时针</param>
/// <returns></returns>
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;
}
/// <summary>
/// 根据点集合生成图形
/// </summary>
/// <param name="Points"></param>
/// <returns></returns>
private static IGeometry GenerateGeometryFromPoints(List<IPoint> 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 图形操作类
/// <summary>
/// 图斑外扩至“ExpandableArea”平
/// </summary>
/// <param name="geometryBG">参考图形</param>
/// <param name="Insergeometry">向参考图形内扩图斑</param>
/// <param name="ExpandableArea">外扩至面积</param>
/// <returns></returns>
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;
}
}
/// <summary>
/// 图斑内陷至“ExpandableArea”平
/// </summary>
/// <param name="geometryBG">参考图形</param>
/// <param name="Insergeometry">向参考图形内扩图斑</param>
/// <param name="ExpandableArea">内陷至面积</param>
/// <returns></returns>
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;
}
/// <summary>
/// 图形操作
/// </summary>
/// <param name="pGeo1">被擦除项</param>
/// <param name="pGeo2">擦除项</param>
/// <returns></returns>
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属性
/// <summary>
/// 同图层图斑属性赋值
/// </summary>
/// <param name="sFeature"></param>
/// <param name="tFeature"></param>
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);
}
}
/// <summary>
/// 通过基础库图斑赋值过程数据变更前属性
/// </summary>
/// <param name="tFeature"></param>
/// <param name="sFeature"></param>
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);
}
}
/// <summary>
/// 通过更新层/基础库图斑赋值过程数据变更后属性
/// </summary>
/// <param name="tFeature"></param>
/// <param name="sFeature"></param>
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
}
}