年度变更建库软件5.0版本
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

572 lines
22 KiB

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