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
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 |
|
} |
|
}
|
|
|