年度变更建库软件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.

885 lines
36 KiB

4 months ago
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using KGIS.Framework.AE;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Kingo.Plugin.DataCheck
{
public static class GeometryAPI
{
#region 计算两条线段(包含延长线)的交点
/// <summary>
/// 计算两条线段(包含延长线)的交点
/// </summary>
/// <param name="pLine1"></param>
/// <param name="pLine2"></param>
/// <returns></returns>
public static IPoint GetIntersectPoint(IPolyline pLine1, IPolyline pLine2)
{
IPoint result = null;
var x1 = pLine1.FromPoint.X;
var x2 = pLine1.ToPoint.X;
var y1 = pLine1.FromPoint.Y;
var y2 = pLine1.ToPoint.Y;
var x3 = pLine2.FromPoint.X;
var x4 = pLine2.ToPoint.X;
var y3 = pLine2.FromPoint.Y;
var y4 = pLine2.ToPoint.Y;
var b1 = (y2 - y1) * x1 + (x1 - x2) * y1;
var b2 = (y4 - y3) * x3 + (x3 - x4) * y3;
var D = (x2 - x1) * (y4 - y3) - (x4 - x3) * (y2 - y1);
var D1 = b2 * (x2 - x1) - b1 * (x4 - x3);
var D2 = b2 * (y2 - y1) - b1 * (y4 - y3);
var x0 = D1 / D;
var y0 = D2 / D;
result = new PointClass() { X = x0, Y = y0 };
//}
return result;
}
/// <summary>
/// 计算两点连线和另一条线段的交点(待验证)
/// </summary>
/// <param name="pointStart"></param>
/// <param name="pointEnd"></param>
/// <param name="targetGeo"></param>
/// <returns></returns>
private static IPoint GetIntersectPoint3(IPoint pointStart, IPoint pointEnd, IPolyline targetGeo)
{
//要返回的延长线终点
IPoint returnPoint = null;
IPoint ans, v1, v2;
//延长线的长度:用来判断取延长线长度短的点
double distance = double.MaxValue;
if (targetGeo != null)
{
IGeometryCollection geoCollection = targetGeo as IGeometryCollection;
for (int i = 0; i < geoCollection.GeometryCount; i++)
{
IPointCollection points = geoCollection.get_Geometry(i) as IPointCollection;
for (int j = 0; j < points.PointCount - 1; j++)
{
v1 = points.get_Point(j);
v2 = points.get_Point(j + 1);
if (parallel(pointStart, pointEnd, v1, v2) || !intersect_in(pointStart, pointEnd, v1, v2))
{
continue;
}
else
{
ans = intersection(pointStart, pointEnd, v1, v2);
IPolyline polylineOld = new PolylineClass();
polylineOld.FromPoint = pointStart;
polylineOld.ToPoint = pointEnd;
polylineOld.SpatialReference = targetGeo.SpatialReference;
IPolyline polylineNew = new PolylineClass();
polylineNew.FromPoint = pointEnd;
polylineNew.ToPoint = ans;
polylineNew.SpatialReference = targetGeo.SpatialReference;
if (FeatureAPI.IsInterSect(polylineOld as IPolyline, polylineNew as IPolyline))
{
continue;
}
//延长线的长度:取延长线长度短的点
if (polylineNew.Length < distance)
{
distance = polylineNew.Length;
returnPoint = ans;
returnPoint.SpatialReference = targetGeo.SpatialReference;
}
else
{
continue;
}
}
}
}
return returnPoint;
}
return null;
}
/// <summary>
/// 计算来给你调线段的交点(不包含延长线上的点)
/// </summary>
/// <param name="pLine1"></param>
/// <param name="pLine2"></param>
/// <returns></returns>
public static IPoint GetIntersectPoint2(IPolyline pLine1, IPolyline pLine2)
{
IPoint result = new PointClass();
try
{
ITopologicalOperator pTopo = pLine1 as ITopologicalOperator;
result = pTopo.Intersect(pLine2, esriGeometryDimension.esriGeometry0Dimension) as IPoint;
return result;
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 判两线段相交,包括端点和部分重合
/// </summary>
/// <param name="u1"></param>
/// <param name="u2"></param>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
static bool intersect_in(IPoint u1, IPoint u2, IPoint v1, IPoint v2)
{
if (!dots_inline(u1, u2, v1) || !dots_inline(u1, u2, v2))
{
return !same_side(u1, u2, v1, v2) || !same_side(v1, v2, u1, u2);
}
return dot_online_in(u1, v1, v2) || dot_online_in(u2, v1, v2) || dot_online_in(v1, u1, u2) || dot_online_in(v2, u1, u2);
}
/// <summary>
/// 计算两线段交点,请判线段是否相交(同时还是要判断是否平行!)
/// </summary>
/// <param name="u1"></param>
/// <param name="u2"></param>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
static IPoint intersection(IPoint u1, IPoint u2, IPoint v1, IPoint v2)
{
IPoint ret = new PointClass();
ret.X = u1.X;
ret.Y = u1.Y;
ret.SpatialReference = u1.SpatialReference;
double t = ((u1.X - v1.X) * (v1.Y - v2.Y) - (u1.Y - v1.Y) * (v1.X - v2.X)) / ((u1.X - u2.X) * (v1.Y - v2.Y) - (u1.Y - u2.Y) * (v1.X - v2.X));
ret.X += (u2.X - u1.X) * t;
ret.Y += (u2.Y - u1.Y) * t;
return ret;
}
/// <summary>
/// 计算交叉乘积(P1-P0)x(P2-P0)
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <param name="p0"></param>
/// <returns></returns>
static double xmult(IPoint p1, IPoint p2, IPoint p0)
{
return (p1.X - p0.X) * (p2.Y - p0.Y) - (p2.X - p0.X) * (p1.Y - p0.Y);
}
/// <summary>
/// 判点是否在线段上,包括端点
/// </summary>
/// <param name="p"></param>
/// <param name="l1"></param>
/// <param name="l2"></param>
/// <returns></returns>
static bool dot_online_in(IPoint p, IPoint l1, IPoint l2)
{
double d_xmult = xmult(p, l1, l2);
if (((d_xmult > 0 && d_xmult < 1e-8) || (d_xmult < 0 && -d_xmult < 1e-8)) && (l1.X - p.X) * (l2.X - p.X) == 0 && (l1.Y - p.Y) * (l2.Y - p.Y) == 0)
{
return true;
}
return false;
}
/// <summary>
/// 判两点在线段同侧,点在线段上返回0
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <param name="l1"></param>
/// <param name="l2"></param>
/// <returns></returns>
static bool same_side(IPoint p1, IPoint p2, IPoint l1, IPoint l2)
{
return xmult(l1, p1, l2) * xmult(l1, p2, l2) > 1e-8 ? true : false;
}
/// <summary>
/// 判两直线平行
/// </summary>
/// <param name="u1"></param>
/// <param name="u2"></param>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
static bool parallel(IPoint u1, IPoint u2, IPoint v1, IPoint v2)
{
return (u1.X - u2.X) * (v1.Y - v2.Y) - (v1.X - v2.X) * (u1.Y - u2.Y) == 0 ? true : false;
}
/// <summary>
/// 判三点共线
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <param name="p3"></param>
/// <returns></returns>
static bool dots_inline(IPoint p1, IPoint p2, IPoint p3)
{
double d_xmult = xmult(p1, p2, p3);
if ((d_xmult > 0 && d_xmult < 1e-8) || (d_xmult < 0 && -d_xmult < 1e-8))
{
return true;
}
return false;
}
#endregion
#region 计算两点间距离
public static double TwoPointDistance(IPoint p1, IPoint p2)
{
double result = -1;
result = Math.Abs(Math.Sqrt(Math.Pow((p1.X - p2.X), 2) + Math.Pow((p1.Y - p2.Y), 2)));
return result;
}
#endregion
/// <summary>
/// 获取线段延长线上的点
/// </summary>
/// <param name="pLine"></param>
/// <param name="pLength"></param>
/// <returns></returns>
public static IPoint GetExtendedLinePoint(IPolyline pLine, double pLength)
{
IPoint result = null;
double relativeX = pLine.ToPoint.X - pLine.FromPoint.X;
double relativeY = pLine.ToPoint.Y - pLine.FromPoint.Y;
double hypotenuse = Math.Sqrt(Math.Pow(relativeX, 2) + Math.Pow(relativeY, 2));
double x = relativeX / hypotenuse * pLength;
double y = relativeY / hypotenuse * pLength;
result = new PointClass() { X = pLine.ToPoint.X + x, Y = pLine.ToPoint.Y + y };
return result;
}
public static IGeometry UnionGeometry(IGeometry geo1, IGeometry geo2)
{
IGeometry result = null;
try
{
ITopologicalOperator topo = geo2 as ITopologicalOperator;
topo.Simplify();
topo = geo1 as ITopologicalOperator;
topo.Simplify();
result = topo.Union(geo2);
}
catch (Exception ex)
{
throw ex;
}
return result;
}
public static bool IsEqualGeo(IGeometry geo1, IGeometry geo2)
{
bool result = false;
try
{
IRelationalOperator relat = geo1 as IRelationalOperator;
result = relat.Equals(geo2);
}
catch (Exception ex)
{
throw ex;
}
return result;
}
public static IPolyline GetSegment(IGeometry pGeo, IPoint pPoint, int position = 0)
{
IPolyline result = new PolylineClass();
if (pGeo == null)
return result;
if (pGeo.IsEmpty)
return result;
object o = Type.Missing;
try
{
IHitTest tempLine = null;
if (pGeo.GeometryType == esriGeometryType.esriGeometryPolygon)
{
tempLine = (pGeo as ITopologicalOperator).Boundary as IHitTest;
}
else if (pGeo.GeometryType == esriGeometryType.esriGeometryPolyline)
{
tempLine = pGeo as IHitTest;
}
if (tempLine == null) return result;
double DbHitDis = 0;
var ptDelete = new PointClass();
int LngPrtIdx = 0;
int segIndex = 0;
bool BoolHitRt = false;
bool Hittest = tempLine.HitTest(pPoint, 1, esriGeometryHitPartType.esriGeometryPartBoundary, ptDelete, ref DbHitDis, ref LngPrtIdx, ref segIndex, ref BoolHitRt);
if (Hittest)
{
ISegmentCollection newSegCol = (ISegmentCollection)result;
IGeometryCollection pGeocoll = tempLine as IGeometryCollection;
ISegmentCollection lineSegCol = (ISegmentCollection)pGeocoll.Geometry[LngPrtIdx];
ISegment segment = lineSegCol.Segment[segIndex];
if (position == 1)
{
if (lineSegCol.SegmentCount > segIndex + 1)
{
segment = lineSegCol.Segment[segIndex + 1];
}
else
{
segment = lineSegCol.Segment[lineSegCol.SegmentCount - 1];
}
}
else if (position == -1)
{
if (segIndex == 0)
{
segment = lineSegCol.Segment[lineSegCol.SegmentCount - 1];
}
else
{
segment = lineSegCol.Segment[segIndex - 1];
}
}
newSegCol.AddSegment(segment, ref o, ref o);
newSegCol.SegmentsChanged();
result = newSegCol as IPolyline;
}
}
catch (Exception ex)
{
throw ex;
}
return result;
}
public static int GetSegmentIndex(IGeometry pGeo, IPoint pPoint, int position = 0)
{
int result = -1;
if (pGeo == null)
return result;
if (pGeo.IsEmpty)
return result;
object o = Type.Missing;
try
{
IHitTest tempLine = null;
if (pGeo.GeometryType == esriGeometryType.esriGeometryPolygon)
{
tempLine = (pGeo as ITopologicalOperator).Boundary as IHitTest;
}
else if (pGeo.GeometryType == esriGeometryType.esriGeometryPolyline)
{
tempLine = pGeo as IHitTest;
}
if (tempLine == null) return result;
double DbHitDis = 0;
var ptDelete = new PointClass();
int LngPrtIdx = 0;
int segIndex = 0;
bool BoolHitRt = false;
bool Hittest = tempLine.HitTest(pPoint, 1, esriGeometryHitPartType.esriGeometryPartBoundary, ptDelete, ref DbHitDis, ref LngPrtIdx, ref segIndex, ref BoolHitRt);
if (Hittest)
{
result = segIndex;
}
}
catch (Exception ex)
{
throw ex;
}
return result;
}
/// <summary>
/// 获取一条直线上的所有连续的线段
/// </summary>
/// <param name="pPoint"></param>
/// <param name="pLayer"></param>
/// <returns></returns>
public static List<IPolyline> GetSegmentsOfStraightLine(IPolyline pLine, IFeatureLayer pLayer)
{
List<IPolyline> result = new List<IPolyline>();
try
{
//result.Add(pLine);
IPoint centerPoint = new PointClass()
{
X = (pLine.FromPoint.X + pLine.ToPoint.X) / 2,
Y = (pLine.FromPoint.Y + pLine.ToPoint.Y) / 2
};
double angle = getAngle360(pLine.FromPoint, pLine.ToPoint);
List<IFeature> features = FeatureAPI.Identify(centerPoint, pLayer);
GetSegmentsOfStraightLine2(angle, centerPoint, pLayer, features, ref result);
IPolyline temp = new PolylineClass() { FromPoint = result[0].ToPoint, ToPoint = result[0].FromPoint };
centerPoint = GetExtendedLinePoint(temp, 0.1);
//centerPoint=
features = FeatureAPI.Identify(centerPoint, pLayer);
angle = getAngle360(temp.FromPoint, temp.ToPoint);
GetSegmentsOfStraightLine2(angle, centerPoint, pLayer, features, ref result);
//GetSegmentsOfStraightLine(angle, pLine.ToPoint, pLayer, ref result, 1);
//GetSegmentsOfStraightLine(angle, pLine.FromPoint, pLayer, ref result, -1);
}
catch (Exception ex)
{
throw ex;
}
return result;
}
private static void GetSegmentsOfStraightLine2(double pAngle, IPoint pPoint, IFeatureLayer pLayer, List<IFeature> pFeatures, ref List<IPolyline> pReturnLines, int position = 0)
{
int num = pReturnLines.Count;
while (pFeatures.Count > 0)
{
IGeometry geo = pFeatures[0].ShapeCopy;
pFeatures.Remove(pFeatures[0]);
IPolyline line = GetSegment(geo, pPoint);
if (line.Length == 0)
break;
double tempAngle = getAngle360(line.FromPoint, line.ToPoint);
while (Math.Abs(pAngle - tempAngle) < 3)
{
pFeatures.Clear();
if (pReturnLines.FirstOrDefault(f => f.Length == line.Length) != null)
break;
pReturnLines.Add(line);
pPoint = GetExtendedLinePoint(line, 0.1);
IPolyline tempLine = GetSegment(geo, pPoint);
if (tempLine.Length == 0)
break;
tempAngle = getAngle360(tempLine.FromPoint, tempLine.ToPoint);
if (Math.Abs(pAngle - tempAngle) > 0.1)
{
pPoint = GetExtendedLinePoint(line, 0.1);
}
else
{
line = tempLine;
}
}
while (Math.Abs(Math.Abs(pAngle - tempAngle) - 180) < 3)
{
pFeatures.Clear();
if (pReturnLines.FirstOrDefault(f => f.Length == line.Length) != null)
break;
pReturnLines.Add(line);
IPolyline temp = new PolylineClass() { FromPoint = line.ToPoint, ToPoint = line.FromPoint };
pPoint = GetExtendedLinePoint(temp, 0.1);
IPolyline tempLine = GetSegment(geo, pPoint, -1);
if (tempLine.Length == 0)
break;
tempAngle = getAngle360(tempLine.FromPoint, tempLine.ToPoint);
if (Math.Abs(Math.Abs(pAngle - tempAngle) - 180) > 0.1)
{
pPoint = GetExtendedLinePoint(temp, 0.1);
}
else
{
line = tempLine;
}
}
}
if (num != pReturnLines.Count)
{
List<IFeature> features = FeatureAPI.Identify(pPoint, pLayer);
GetSegmentsOfStraightLine2(pAngle, pPoint, pLayer, features, ref pReturnLines);
}
}
public static IPolyline GetLineByAngle(IPoint pPoint, double pAngle, IFeatureLayer pLayer)
{
IPolyline line = null;
try
{
List<IFeature> features = FeatureAPI.Identify(pPoint, pLayer);
double referAngle = 360;
foreach (var item in features)
{
IPolyline tempLine = GetSegment(item.ShapeCopy, pPoint);
double tempAngle = getAngle360(tempLine.FromPoint, tempLine.ToPoint);
double angleDiff = Math.Round(Math.Abs(Math.Abs(tempAngle - pAngle) - 90), 2);
double angleDiff2 = Math.Round(Math.Abs(Math.Abs(Math.Abs(tempAngle - pAngle) - 180) - 90), 2);
bool pointOnSegment = IsPointOnSegment(pPoint, tempLine, 0.01);
if (referAngle > angleDiff && pointOnSegment)
{
referAngle = angleDiff;
line = tempLine;
}
if (referAngle > angleDiff2 && pointOnSegment)
{
referAngle = angleDiff2;
line = tempLine;
}
if (Math.Abs(pAngle - tempAngle) < 1 || Math.Abs(Math.Abs(pAngle - tempAngle) - 180) < 1)
{
tempLine = GetSegment(item.ShapeCopy, pPoint, 1);
pointOnSegment = IsPointOnSegment(pPoint, tempLine, 0.01);
double tempAngle2 = getAngle360(tempLine.FromPoint, tempLine.ToPoint);
angleDiff = Math.Abs(Math.Abs(tempAngle2 - pAngle) - 90);
angleDiff2 = Math.Abs(Math.Abs(Math.Abs(tempAngle2 - pAngle) - 180) - 90);
if (referAngle > angleDiff && pointOnSegment)
{
referAngle = angleDiff;
line = tempLine;
}
if (referAngle > angleDiff2 && pointOnSegment)
{
referAngle = angleDiff2;
line = tempLine;
}
}
if (Math.Abs(pAngle - tempAngle) < 1 || Math.Abs(Math.Abs(pAngle - tempAngle) - 180) < 1)
{
tempLine = GetSegment(item.ShapeCopy, pPoint, -1);
pointOnSegment = IsPointOnSegment(pPoint, tempLine, 0.01);
double tempAngle2 = getAngle360(tempLine.FromPoint, tempLine.ToPoint);
angleDiff = Math.Abs(Math.Abs(tempAngle2 - pAngle) - 90);
angleDiff2 = Math.Abs(Math.Abs(Math.Abs(tempAngle2 - pAngle) - 180) - 90);
if (referAngle > angleDiff && pointOnSegment)
{
referAngle = angleDiff;
line = tempLine;
}
if (referAngle > angleDiff2 && pointOnSegment)
{
referAngle = angleDiff2;
line = tempLine;
}
}
}
}
catch (Exception ex)
{
throw ex;
}
return line;
}
/// <summary>
/// 判断点pPoint,是否和pLine在同一条直线上
/// </summary>
/// <param name="pPoint"></param>
/// <param name="pLine"></param>
/// <param name="delta"></param>
/// <returns></returns>
public static bool IsPointOnLine(IPoint pPoint, IPolyline pLine, double delta)
{
double xa = pLine.FromPoint.X - pLine.ToPoint.X;
double ya = pLine.FromPoint.Y - pLine.ToPoint.Y;
double xb = pPoint.X - pLine.ToPoint.X;
double yb = pPoint.Y - pLine.ToPoint.Y;
return (Math.Abs(yb / xb - ya / xa) <= delta);
}
/// <summary>
/// 判断点pPoint,是否在pLine上
/// </summary>
/// <param name="pPoint"></param>
/// <param name="pLine"></param>
/// <param name="delta"></param>
/// <returns></returns>
public static bool IsPointOnSegment(IPoint pPoint, IPolyline pLine, double delta)
{
double xa = Math.Round(pLine.FromPoint.X - pLine.ToPoint.X, 5);
double ya = Math.Round(pLine.FromPoint.Y - pLine.ToPoint.Y, 5);
double xb = Math.Round(pPoint.X - pLine.ToPoint.X, 5);
double yb = Math.Round(pPoint.Y - pLine.ToPoint.Y, 5);
if (xb == 0 && yb == 0)
return true;
return (Math.Abs(yb / xb - ya / xa) < delta
&& Math.Round(Math.Min(pLine.ToPoint.X, pLine.FromPoint.X), 5) <= Math.Round(pPoint.X, 5)
&& Math.Round(Math.Max(pLine.ToPoint.X, pLine.FromPoint.X), 5) >= Math.Round(pPoint.X, 5)
&& Math.Round(Math.Min(pLine.ToPoint.Y, pLine.FromPoint.Y), 5) <= Math.Round(pPoint.Y, 5)
&& Math.Round(Math.Max(pLine.ToPoint.Y, pLine.FromPoint.Y), 5) >= Math.Round(pPoint.Y, 5));
}
//判断点是否在线上,在返回1,不在返回0
public static bool IsPointOnSegment(ICurve pSegment, IPoint Q)
{
double maxx, minx, maxy, miny;
maxx = pSegment.FromPoint.X > pSegment.ToPoint.X ? pSegment.FromPoint.X : pSegment.ToPoint.X; //矩形的右边长
minx = pSegment.FromPoint.X > pSegment.ToPoint.X ? pSegment.ToPoint.X : pSegment.FromPoint.X; //矩形的左边长
maxy = pSegment.FromPoint.Y > pSegment.ToPoint.Y ? pSegment.FromPoint.Y : pSegment.ToPoint.Y; //矩形的上边长
miny = pSegment.FromPoint.Y > pSegment.ToPoint.Y ? pSegment.ToPoint.Y : pSegment.FromPoint.Y; //矩形的下边长
if (((Q.X - pSegment.FromPoint.X) * (pSegment.ToPoint.Y - pSegment.FromPoint.Y) == (pSegment.ToPoint.X - pSegment.FromPoint.X) * (Q.Y - pSegment.FromPoint.Y)) && (Q.X >= minx && Q.X <= maxx) && (Q.Y >= miny && Q.Y <= maxy))
return true;
else
return false;
}
public static double getAngle(IPoint p1, IPoint p2)
{
//两点的x、y值
double x = p2.X - p1.X;
double y = p2.Y - p1.Y;
double hypotenuse = Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2));
//斜边长度
double cos = x / hypotenuse;
double radian = Math.Acos(cos);
//求出弧度
double angle = 180 / (Math.PI / radian);
//用弧度算出角度
if (y < 0)
{
angle = -angle;
}
else if ((y == 0) && (x < 0))
{
angle = 180;
}
return angle;
}
public static double getAngle360(IPoint p1, IPoint p2)
{
//两点的x、y值
double x = p2.X - p1.X;
double y = p2.Y - p1.Y;
double hypotenuse = Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2));
//斜边长度
double cos = y / hypotenuse;
double radian = Math.Acos(cos);
//求出弧度
double angle = 180 / (Math.PI / radian);
//用弧度算出角度
if (x < 0)
{
//angle = -angle;
}
else
if (x > 0)
{
angle = 360 - angle;
}
return angle;
}
/// <summary>
/// 垂足
/// </summary>
/// <param name="line"></param>
/// <param name="pnt"></param>
/// <returns></returns>
public static IPoint GetCrossPnt(ICurve line, IPoint pnt)
{
double dAngle360 = getAngle360(line.FromPoint, line.ToPoint);
IPoint pt1 = line.FromPoint;
IPoint pt2 = line.ToPoint;
if (line.Length == 0)
return null;
if (pt1.X == pt2.X || dAngle360 == 180 || dAngle360 == 0)
{
IPoint ptCross = new PointClass();
ptCross.X = pt1.X;
ptCross.Y = pnt.Y;
return ptCross;
}
else
{
double A = (pt1.Y - pt2.Y) / (pt1.X - pt2.X);
double B = (pt1.Y - A * pt1.X);
/// > 0 = ax +b -y;  对应垂线方程为 -x -ay + m = 0;(m为系数)
            /// > A = a; B = b;
double m = pnt.X + A * pnt.Y;
/// 求两直线交点坐标
IPoint ptCross = new PointClass();
ptCross.X = ((m - A * B) / (A * A + 1));
ptCross.Y = (A * ptCross.X + B);
return ptCross;
}
}
public static IPolyline UnionLine(List<IPolyline> pGeometry)
{
try
{
if (pGeometry == null || pGeometry.Count == 0)
return null;
if (pGeometry.Count == 1)
return pGeometry[0];
IPolyline baseGeo = pGeometry[0];
double angle1 = getAngle360(baseGeo.FromPoint, baseGeo.ToPoint);
//IGeometry target = FeatureCopy(baseFeature);
ITopologicalOperator2 topo = baseGeo as ITopologicalOperator2;
foreach (IPolyline f in pGeometry)
{
IPolyline tempLine = new PolylineClass();
if (f != baseGeo)
{
double angle2 = getAngle360(f.FromPoint, f.ToPoint);
if (Math.Abs(Math.Abs(angle1 - angle2) - 180) < 1)
{
tempLine.FromPoint = f.ToPoint;
tempLine.ToPoint = f.FromPoint;
}
else
{
tempLine = f;
}
ITopologicalOperator2 topolog = tempLine as ITopologicalOperator2;
topolog.Simplify();
topo.Simplify();
topo = topo.Union(tempLine) as ITopologicalOperator2;
}
}
if (!topo.IsSimple)
{
topo.Simplify();
}
//target.Shape = topo as IGeometry;
return topo as IPolyline;
}
catch (Exception ex)
{
throw ex;
}
}
public static double GetPointOnLineLeftOrRight(IPolyline line, IPoint pnt)
{
return (line.FromPoint.X - pnt.X) * (line.ToPoint.Y - pnt.Y) - (line.FromPoint.Y - pnt.Y) * (line.ToPoint.X - pnt.X);
}
/// <summary>
/// 重构Geometry
/// </summary>
/// <param name="pGeometry">原始Geometry</param>
/// <returns>重构后的Geometry</returns>
public static IGeometry ResetGeometry(IGeometry pGeometry, Point pPoint = null)
{
try
{
if (pGeometry == null) return null;
//外接矩形左上角的点
Point UpperLeft = pPoint;
if (UpperLeft == null)
{
UpperLeft = new Point();
UpperLeft.X = pGeometry.Envelope.XMin;
UpperLeft.Y = pGeometry.Envelope.YMax;
UpperLeft.SpatialReference = pGeometry.SpatialReference;
}
ITopologicalOperator topologicalOperator = pGeometry as ITopologicalOperator;
if (topologicalOperator == null) return null;
topologicalOperator.Simplify();
//外环图形
GeometryBag ExterGeometryBag = (topologicalOperator as ESRI.ArcGIS.Geometry.IPolygon4).ExteriorRingBag as GeometryBag;
if (ExterGeometryBag == null) return null;
IGeometryCollection ExterRingGeometryCollection = ExterGeometryBag as IGeometryCollection;
IGeometryCollection geometry = new ESRI.ArcGIS.Geometry.PolygonClass() as IGeometryCollection;
//List<IGeometry> geometry = new List<IGeometry>();
for (int g = 0; g < ExterRingGeometryCollection.GeometryCount; g++)
{
IGeometry ExterGeometry = ExterRingGeometryCollection.get_Geometry(g);
IGeometry newGeo = ResetPointCollection(ExterGeometry, UpperLeft) as IGeometry;
if (newGeo == null) continue;
geometry.AddGeometry(newGeo);
//内环图形
IGeometryBag InteriorBag = (topologicalOperator as ESRI.ArcGIS.Geometry.IPolygon4).get_InteriorRingBag(ExterGeometry as IRing);
if (InteriorBag == null) continue;
IGeometryCollection InteriorRingGeometryCollection = InteriorBag as IGeometryCollection;
if (InteriorRingGeometryCollection == null) continue;
for (int IG = 0; IG < InteriorRingGeometryCollection.GeometryCount; IG++)
{
IGeometry interiorGeo = InteriorRingGeometryCollection.get_Geometry(IG);
if (interiorGeo == null) continue;
IGeometry newInteriorGeo = ResetPointCollection(interiorGeo, UpperLeft) as IGeometry;
if (newInteriorGeo == null) continue;
geometry.AddGeometry(newInteriorGeo);
}
}
//ITopologicalOperator iTopological = geometry as ITopologicalOperator;
//if (iTopological == null) return null;
//iTopological.Simplify();
return geometry as IGeometry;
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 界址点重新排列
/// </summary>
/// <param name="pGeo">原始图形</param>
/// <param name="pUpperLeftPoint">原始Geometry外接矩形左上角的点</param>
/// <returns></returns>
private static IPointCollection ResetPointCollection(IGeometry pGeo, Point pUpperLeftPoint)
{
if (pGeo == null) return null;
IPointCollection pointCollection = pGeo as IPointCollection;
if (pointCollection == null) return null;
//图形的起始点
IPoint startPoint = null;
//图形的起始点在原图形中的顺序号
int index = 0;
double length = double.MaxValue;
#region 获取图形的起始点
for (int p = 0; p < pointCollection.PointCount; p++)
{
IPoint tempPoint = pointCollection.get_Point(p);
Polyline line = new PolylineClass();
line.AddPoint(pUpperLeftPoint);
line.AddPoint(tempPoint);
if (length > (line as IPolyline).Length)
{
length = (line as IPolyline).Length;
startPoint = tempPoint;
index = p;
}
}
#endregion
ESRI.ArcGIS.Geometry.IPointCollection poins = new ESRI.ArcGIS.Geometry.Ring() as ESRI.ArcGIS.Geometry.IPointCollection;
#region 按照新的起始点重新排列图形
for (int i = 0; i < pointCollection.PointCount; i++)
{
IPoint point = null;
if (index + i < pointCollection.PointCount)
{
point = pointCollection.get_Point(index + i);
}
else
{
if (index + i == pointCollection.PointCount)
{
continue;
}
point = pointCollection.get_Point(Math.Abs(pointCollection.PointCount - (index + i)));
}
point.SpatialReference = pGeo.SpatialReference;
poins.AddPoint(point);
}
#endregion
startPoint.SpatialReference = pGeo.SpatialReference;
if (index != 0)
poins.AddPoint(startPoint);
return poins;
}
}
}