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