/// <summary> /// Constructor. Copies the contents of the xyPolygon parameter. /// </summary> /// <param name="xyPolygon">Polygon to copy.</param> /// <returns>None</returns> public XYPolygon(XYPolygon xyPolygon) { // Points = new ArrayList(); foreach (XYPoint xypoint in xyPolygon.Points) { Points.Add(new XYPoint(xypoint.X, xypoint.Y)); } }
/// <summary> /// Constructor. Copies the contents of the xyPolygon parameter. /// </summary> /// <param name="xyPolygon">Polygon to copy.</param> /// <returns>None</returns> public XYPolygon(XYPolygon xyPolygon) { // Points = new ArrayList(); foreach (XYPoint xypoint in xyPolygon.Points) { Points.Add(xypoint); } }
public void Equals() { XYPolygon p1 = new XYPolygon(); p1.Points.Add(new XYPoint(0, 3)); p1.Points.Add(new XYPoint(3, 0)); p1.Points.Add(new XYPoint(8, 0)); p1.Points.Add(new XYPoint(8, 2)); p1.Points.Add(new XYPoint(3, 1)); p1.Points.Add(new XYPoint(3, 3)); p1.Points.Add(new XYPoint(8, 3)); p1.Points.Add(new XYPoint(4, 7)); XYPolygon p2 = new XYPolygon(); p2.Points.Add(new XYPoint(0, 3)); p2.Points.Add(new XYPoint(3, 0)); p2.Points.Add(new XYPoint(8, 0)); p2.Points.Add(new XYPoint(8, 2)); p2.Points.Add(new XYPoint(3, 1)); p2.Points.Add(new XYPoint(3, 3)); p2.Points.Add(new XYPoint(8, 3)); p2.Points.Add(new XYPoint(4, 7)); XYPolygon p3 = new XYPolygon(); p3.Points.Add(new XYPoint(0, 3)); p3.Points.Add(new XYPoint(3, 0)); p3.Points.Add(new XYPoint(8, 0)); p3.Points.Add(new XYPoint(8, 2)); p3.Points.Add(new XYPoint(3, 1.1)); p3.Points.Add(new XYPoint(3, 3)); p3.Points.Add(new XYPoint(8, 3)); p3.Points.Add(new XYPoint(4, 7)); XYPolygon p4 = new XYPolygon(); p4.Points.Add(new XYPoint(0, 3)); p4.Points.Add(new XYPoint(3, 0)); p4.Points.Add(new XYPoint(8, 0)); p4.Points.Add(new XYPoint(8, 2)); p4.Points.Add(new XYPoint(3, 1)); p4.Points.Add(new XYPoint(3, 3)); p4.Points.Add(new XYPoint(8, 3)); XYPolyline p5 = new XYPolyline(); p5.Points.Add(new XYPoint(0, 3)); p5.Points.Add(new XYPoint(3, 0)); p5.Points.Add(new XYPoint(8, 0)); p5.Points.Add(new XYPoint(8, 2)); p5.Points.Add(new XYPoint(3, 1.1)); p5.Points.Add(new XYPoint(3, 3)); p5.Points.Add(new XYPoint(8, 3)); p5.Points.Add(new XYPoint(4, 7)); Assert.AreEqual(true, p1.Equals(p1),"Test1"); Assert.AreEqual(true, p1.Equals(p2),"Test2"); Assert.AreEqual(false, p1.Equals(p3),"Test3"); Assert.AreEqual(false, p1.Equals(p4),"Test4"); Assert.AreEqual(false, p1.Equals(p5),"Test5"); }
public static XYPolygon CreateFromXYPolygon(IElementSet elementSet, int index) { if (elementSet.ElementType != ElementType.Polygon) { throw new Exception("Cannot create XYPolyline"); } XYPolygon xyPolygon = new XYPolygon(); for (int i = 0; i < elementSet.GetVertexCount(index); i++) { xyPolygon.Points.Add(new XYPoint(elementSet.GetVertexXCoordinate(index, i), elementSet.GetVertexYCoordinate(index, i))); } return(xyPolygon); }
/// <summary> /// The method decides if the triangle formed by P(i-1), P(i) and /// P(i+1) from Polygon are intersected by any of the other points /// of the polygon. /// </summary> /// <param name="i">Middle index for the three points that forms the triangle</param> /// <returns> /// <p>true: If the triangle P(i-1), P(i), P(i+1) is intersected by other parts of Polygon</p> /// <p>false: otherwise</p> /// </returns> protected bool IsIntersected(int i) { double x = 0; double y = 0; int n = Points.Count; int im1 = i - 1; int ip1 = i + 1; if (i == 0) { im1 = n - 1; } else if (i == n - 1) { ip1 = 0; } XYPoint nodeim1 = new XYPoint((XYPoint)Points[im1]); XYPoint nodei = new XYPoint((XYPoint)Points[i]); XYPoint nodeip1 = new XYPoint((XYPoint)Points[ip1]); XYPolygon localPolygon = new XYPolygon(); localPolygon.Points.Add(nodeim1); localPolygon.Points.Add(nodei); localPolygon.Points.Add(nodeip1); int j = 0; bool intersected = false; while (((j < n - 1) && (!intersected))) { x = ((XYPoint)Points[j]).X; y = ((XYPoint)Points[j]).Y; if (((((j != im1) && (j != i)) && (j != ip1)) && XYGeometryTools.IsPointInPolygon(x, y, localPolygon))) { return(true); } else { j++; } } return(false); }
/// <summary> /// Determines if a point in inside or outside a polygon. /// Works for both convex and concave polygons (Winding number test) /// </summary> /// <param name="x">x-coordinate for the point</param> /// <param name="y">y-coordiante for the point</param> /// <param name="polygon">Polygon</param> /// <returns> /// <p>true: If the point is inside the polygon</p> /// <p>false: If the point is outside the polygon.</p> /// </returns> public static bool IsPointInPolygon(double x, double y, XYPolygon polygon) { double x1, x2, y1, y2; double xinters; bool isInside = false; int n = polygon.Points.Count; for (int i = 0; i < n; i++) { if (i < n - 1) { x1 = ((XYPoint)polygon.Points[i]).X; x2 = ((XYPoint)polygon.Points[i + 1]).X; y1 = ((XYPoint)polygon.Points[i]).Y; y2 = ((XYPoint)polygon.Points[i + 1]).Y; } else { x1 = ((XYPoint)polygon.Points[n - 1]).X; x2 = ((XYPoint)polygon.Points[0]).X; y1 = ((XYPoint)polygon.Points[n - 1]).Y; y2 = ((XYPoint)polygon.Points[0]).Y; } if (y > Math.Min(y1, y2)) { if (y <= Math.Max(y1, y2)) { if (x <= Math.Max(x1, x2)) { if (y1 != y2) { xinters = (y - y1) * (x2 - x1) / (y2 - y1) + x1; if (x1 == x2 || x <= xinters) { isInside = !isInside; } } } } } } return(isInside); }
/// <summary> /// The methods calculates the shared area of two arbitrarily shaped /// polygons. /// </summary> /// <param name="polygonA">Polygon</param> /// <param name="polygonB">Polygon</param> /// <returns> /// <p>The shared area.</p> /// </returns> public static double CalculateSharedArea(XYPolygon polygonA, XYPolygon polygonB) { ArrayList triangleListA = polygonA.GetTriangulation(); ArrayList triangleListB = polygonB.GetTriangulation(); double area = 0; for (int ia = 0; ia < triangleListA.Count; ia++) { XYPolygon triangleA = new XYPolygon((XYPolygon)triangleListA[ia]); for (int ib = 0; ib < triangleListB.Count; ib++) { XYPolygon triangleB = new XYPolygon((XYPolygon)triangleListB[ib]); area = area + TriangleIntersectionArea(triangleA, triangleB); } } return(area); }
protected void CalculateFactors(IElementSet elementSet) { for (int i = 0; i < elementSet.ElementCount; i++) { XYPolygon element = ElementMapper.CreateXYPolygon(elementSet, i); double area = element.GetArea(); if (_areaExponent == 1) { _factors[i] = area; } else if (_areaExponent == -1) { _factors[i] = 1.0 / area; } else { _factors[i] = Math.Pow(area, _areaExponent); } } }
/// <summary> /// Determines if a point in inside or outside a polygon. Inside /// includes on the edge for this method. /// Works for both convex and concave polygons (Winding number test) /// </summary> /// <param name="x">x-coordinate for the point</param> /// <param name="y">y-coordiante for the point</param> /// <param name="polygon">Polygon</param> /// <returns> /// <p>true: If the point is inside the polygon</p> /// <p>false: If the point is outside the polygon.</p> /// </returns> protected static bool IsPointInPolygonOrOnEdge(double x, double y, XYPolygon polygon) { bool result = IsPointInPolygon(x, y, polygon); if (result) { return(result); } else { int iLine = 0; while ((!result) && (iLine < polygon.Points.Count)) { var line = polygon.GetLine(iLine); result = IsPointInLine(x, y, line); iLine++; } } return(result); }
public void GetArea() { // -- Rectangle -- XYPolygon xypolygon = new XYPolygon(); xypolygon.Points.Add(new XYPoint(1,1)); xypolygon.Points.Add(new XYPoint(9,1)); xypolygon.Points.Add(new XYPoint(9,6)); xypolygon.Points.Add(new XYPoint(1,6)); Assert.AreEqual((double) 40, xypolygon.GetArea()); // -- Triangle -- XYPolygon xypolygon2 = new XYPolygon(); xypolygon2.Points.Add(new XYPoint(1,1)); xypolygon2.Points.Add(new XYPoint(9,1)); xypolygon2.Points.Add(new XYPoint(9,6)); Assert.AreEqual((double) 20, xypolygon2.GetArea()); // -- concave -- XYPolygon xypolygon3 = new XYPolygon(); xypolygon3.Points.Add(new XYPoint(1,1)); xypolygon3.Points.Add(new XYPoint(5,3)); xypolygon3.Points.Add(new XYPoint(9,1)); xypolygon3.Points.Add(new XYPoint(9,6)); xypolygon3.Points.Add(new XYPoint(1,6)); Assert.AreEqual((double) 32, xypolygon3.GetArea()); // -- concave -- XYPolygon xypolygon4 = new XYPolygon(); xypolygon4.Points.Add(new XYPoint(1,1)); xypolygon4.Points.Add(new XYPoint(9,1)); xypolygon4.Points.Add(new XYPoint(5,5)); xypolygon4.Points.Add(new XYPoint(5,3)); xypolygon4.Points.Add(new XYPoint(3,3)); xypolygon4.Points.Add(new XYPoint(3,8)); xypolygon4.Points.Add(new XYPoint(9,8)); xypolygon4.Points.Add(new XYPoint(9,11)); xypolygon4.Points.Add(new XYPoint(1,11)); Assert.AreEqual((double) 50, xypolygon4.GetArea()); }
/// <summary> /// Returns an ArrayList of triangles of type XYPolygon describing the /// triangalation of the polygon. /// </summary> /// <param></param> /// <returns> /// A triangulation of the polygon. /// </returns> public ArrayList GetTriangulation() { int i = 0; int im1 = 0; int ip1 = 0; int n = 0; XYPolygon LocalPolygon = new XYPolygon(this); ArrayList TriangleList = new ArrayList(); while (LocalPolygon.Points.Count > 3) { i = LocalPolygon.FindEar(); n = LocalPolygon.Points.Count; im1 = i - 1; ip1 = i + 1; if (i == 0) { im1 = n - 1; } else if (i == n - 1) { ip1 = 0; } XYPoint Nodeim1 = new XYPoint((XYPoint)LocalPolygon.Points[im1]); XYPoint Nodei = new XYPoint((XYPoint)LocalPolygon.Points[i]); XYPoint Nodeip1 = new XYPoint((XYPoint)LocalPolygon.Points[ip1]); XYPolygon Triangle = new XYPolygon(); Triangle.Points.Add(Nodeim1); Triangle.Points.Add(Nodei); Triangle.Points.Add(Nodeip1); TriangleList.Add(Triangle); LocalPolygon.Points.RemoveAt(i); } TriangleList.Add(LocalPolygon); return(TriangleList); }
/// <summary> /// Determines if a point in inside or outside a polygon. /// Works for both convex and concave polygons (Winding number test) /// </summary> /// <param name="x">x-coordinate for the point</param> /// <param name="y">y-coordiante for the point</param> /// <param name="polygon">Polygon</param> /// <returns> /// <p>true: If the point is inside the polygon</p> /// <p>false: If the point is outside the polygon.</p> /// </returns> public static bool IsPointInPolygon(double x, double y, XYPolygon polygon) { double x1,x2,y1,y2; double xinters; bool isInside = false; int n = polygon.Points.Count; for (int i = 0; i < n; i++) { if (i < n - 1) { x1 = ((XYPoint)polygon.Points[i]).X; x2 = ((XYPoint)polygon.Points[i+1]).X; y1 = ((XYPoint)polygon.Points[i]).Y; y2 = ((XYPoint)polygon.Points[i+1]).Y; } else { x1 = ((XYPoint)polygon.Points[n-1]).X; x2 = ((XYPoint)polygon.Points[0]).X; y1 = ((XYPoint)polygon.Points[n-1]).Y; y2 = ((XYPoint)polygon.Points[0]).Y; } if (y > Math.Min(y1,y2)) { if (y <= Math.Max(y1,y2)) { if ( x <= Math.Max(x1,x2)) { if (y1 != y2) { xinters = (y - y1)*(x2 - x1)/(y2 - y1) + x1; if (x1 == x2 || x <= xinters) { isInside = !isInside; } } } } } } return isInside; }
/// <summary> /// Static method that validates an object with an IElementSet interface. The method /// raises an Exception in case IElementSet does not describe a valid ElementSet. /// The checks made are: /// <p>ElementType: Check</p> /// <p>XYPoint: Only one vertex in each element.</p> /// <p>XYPolyline: At least two vertices in each element.</p> /// <p> All line segments in each element has length > 0</p> /// <p>XYPolygon: At least three vertices in each element.</p> /// <p> Area of each element is larger than 0</p> /// <p> All line segments in each element has length > 0</p> /// <p> No line segments within an element crosses.</p> /// </summary> /// /// <param name="elementSet">Object that implement the IElementSet interface</param> /// /// <returns> /// The method has no return value. /// </returns> public static void CheckElementSet(IElementSet elementSet) { try { if(elementSet.ElementType == ElementType.XYPoint) { for (int i = 0; i < elementSet.ElementCount; i++) { try { if(elementSet.GetVertexCount(i) != 1) { throw new System.Exception("Number of vertices in point element is different from 1."); } } catch (System.Exception e) { throw new System.Exception("ElementID = "+elementSet.GetElementID(i),e); } } } else if(elementSet.ElementType == ElementType.XYPolyLine) { for (int i = 0; i < elementSet.ElementCount; i++) { try { XYPolyline xypolyline = new XYPolyline(); for (int j = 0; j < elementSet.GetVertexCount(i); j++) { XYPoint xypoint = new XYPoint(elementSet.GetXCoordinate(i,j),elementSet.GetYCoordinate(i,j)); xypolyline.Points.Add(xypoint); } xypolyline.Validate(); } catch (System.Exception e) { throw new System.Exception("ElementID = "+elementSet.GetElementID(i),e); } } } else if(elementSet.ElementType == ElementType.XYPolygon) { for (int i = 0; i < elementSet.ElementCount; i++) { try { XYPolygon xypolygon = new XYPolygon(); for (int j = 0; j < elementSet.GetVertexCount(i); j++) { XYPoint xypoint = new XYPoint(elementSet.GetXCoordinate(i,j),elementSet.GetYCoordinate(i,j)); xypolygon.Points.Add(xypoint); } xypolygon.Validate(); } catch (System.Exception e) { throw new System.Exception("ElementID = "+elementSet.GetElementID(i),e); } } } } catch (System.Exception e) { throw new System.Exception("ElementSet with ID = "+elementSet.ID+" is invalid",e); } }
public void Protected_CalculateLengthOfLineInsidePolygon() { XYPolygon xypolygon = new XYPolygon(); xypolygon.Points.Add(new XYPoint(1,1)); xypolygon.Points.Add(new XYPoint(9,1)); xypolygon.Points.Add(new XYPoint(5,5)); xypolygon.Points.Add(new XYPoint(5,3)); xypolygon.Points.Add(new XYPoint(3,3)); xypolygon.Points.Add(new XYPoint(3,8)); xypolygon.Points.Add(new XYPoint(9,8)); xypolygon.Points.Add(new XYPoint(9,11)); xypolygon.Points.Add(new XYPoint(1,11)); Assert.AreEqual(0, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,12,11,12),xypolygon),"Test1"); Assert.AreEqual(4, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,11,11,11),xypolygon),"Test2"); Assert.AreEqual(8, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,10,11,10),xypolygon),"Test3"); Assert.AreEqual(8, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,9,11,9),xypolygon),"Test4"); Assert.AreEqual(5, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,8,11,8),xypolygon),"Test5"); Assert.AreEqual(2, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,7,11,7),xypolygon),"Test6"); Assert.AreEqual(2, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,5,11,5),xypolygon),"Test7"); Assert.AreEqual(3, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,4,11,4),xypolygon),"Test8"); Assert.AreEqual(3, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,4,11,4),xypolygon),"Test9"); Assert.AreEqual(5, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,3,11,3),xypolygon),"Test10"); Assert.AreEqual(7, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,2,11,2),xypolygon),"Test11"); Assert.AreEqual(4, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,1,11,1),xypolygon),"Test12"); Assert.AreEqual(0, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,0,11,0),xypolygon),"Test13"); Assert.AreEqual(10, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(2,12,2,0),xypolygon),"Test14"); Assert.AreEqual(6, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(6,12,6,0),xypolygon),"Test15"); Assert.AreEqual(Math.Sqrt(8)+1.5*Math.Sqrt(0.5),AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(1,0.5,10,9.5),xypolygon),"Test16"); Assert.AreEqual(1, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(-2,4,2,4),xypolygon),"Test17"); Assert.AreEqual(5, AXYGeometryTools.ACalculateLengthOfLineInsidePolygon(new XYLine(4,12,4,0),xypolygon),"Test18"); }
public void CalculateSharedArea() { XYPolygon p1 = new XYPolygon(); p1.Points.Add(new XYPoint(0, 3)); p1.Points.Add(new XYPoint(3, 0)); p1.Points.Add(new XYPoint(8, 0)); p1.Points.Add(new XYPoint(8, 2)); p1.Points.Add(new XYPoint(3, 1)); p1.Points.Add(new XYPoint(3, 3)); p1.Points.Add(new XYPoint(8, 3)); p1.Points.Add(new XYPoint(4, 7)); XYPolygon p2 = new XYPolygon(); p2.Points.Add(new XYPoint(3, 3)); p2.Points.Add(new XYPoint(4, 3)); p2.Points.Add(new XYPoint(4, 4)); p2.Points.Add(new XYPoint(3, 4)); XYPolygon p3 = new XYPolygon(); p3.Points.Add(new XYPoint(0, 0)); p3.Points.Add(new XYPoint(8, 0)); p3.Points.Add(new XYPoint(8, 8)); p3.Points.Add(new XYPoint(0, 8)); XYPolygon p4 = new XYPolygon(); p4.Points.Add(new XYPoint(-2, 0)); p4.Points.Add(new XYPoint(3, 0)); p4.Points.Add(new XYPoint(3, 2)); p4.Points.Add(new XYPoint(0, 2)); p4.Points.Add(new XYPoint(0, 5)); p4.Points.Add(new XYPoint(4, 5)); p4.Points.Add(new XYPoint(4, 7)); p4.Points.Add(new XYPoint(-2, 7)); Assert.AreEqual(p1.GetArea(),XYGeometryTools.CalculateSharedArea(p1,p1),1e-12,"Test1 - Polygon1 in Polygon1"); Assert.AreEqual(p2.GetArea(),XYGeometryTools.CalculateSharedArea(p2,p2),1e-12,"Test2 - Polygon1 in Polygon1"); Assert.AreEqual(p4.GetArea(),XYGeometryTools.CalculateSharedArea(p4,p4),1e-12,"Test3 - Polygon1 in Polygon1"); Assert.AreEqual(p2.GetArea(),XYGeometryTools.CalculateSharedArea(p1,p2),1e-12,"Test4 - Polygon2 in Polygon1"); Assert.AreEqual(p1.GetArea(),XYGeometryTools.CalculateSharedArea(p1,p3),1e-12,"Test5 - Polygon1 in Polygon2"); Assert.AreEqual(4,XYGeometryTools.CalculateSharedArea(p1,p4),1e-12,"Test6 - Polygon1 in Polygon3"); }
/// <summary> /// The method calculates the intersection points of triangle a and b both /// of type XYPolygon. /// </summary> /// <param name="triangleA">triangle. The search is started along triangleA.</param> /// <param name="triangleB">triangle. Intersection with this triangle are sought.</param> /// <param name="p">Starting point for the search. p must be part of triangleA.</param> /// <param name="i">on input: End index for the first line segment of triangleA in the search. /// on output: End index for the last intersected line segment in triangleA.</param> /// <param name="j">on input: -1 if vertices before intersection is not to be added to list. /// on output: End index for last intersected line segment of triangleB.</param> /// <param name="intersectionPolygon">polygon eventuallu describing the /// intersection area between triangleA and triangleB</param> /// <returns> /// The p, i, j and intersectionPolygon are called by reference and modified in the method. /// </returns> private static void Intersect(XYPolygon triangleA, XYPolygon triangleB, ref XYPoint p, ref int i, ref int j, ref XYPolygon intersectionPolygon) { XYLine lineA; XYLine lineB; int im1 = Decrease(i, 2); // "i-1" int count1 = 0; bool found = false; while ((count1 < 3) && (!found)) { lineA = triangleA.GetLine(im1); if (count1 == 0) { lineA = new XYLine(lineA); lineA.P1.X = p.X; lineA.P1.Y = p.Y; } double MinDist = -1; // Distance used when a line is crossed more than once int jm1 = 0; // "j-1" int jm1Store = -1; while (jm1 < 3) { lineB = triangleB.GetLine(jm1); found = IntersectionPoint(lineA, lineB, ref p); double Dist = CalculatePointToPointDistance(lineA.P1, p); if (Dist < EPSILON) { found = false; } if (found) { if ((MinDist < 0) || (Dist < MinDist)) { MinDist = Dist; jm1Store = jm1; } } jm1++; } if (jm1Store > -1) { lineB = triangleB.GetLine(jm1Store); found = IntersectionPoint(lineA, lineB, ref p); XYPoint HelpCoordinate = new XYPoint(p.X, p.Y); XYPoint HelpNode = new XYPoint(HelpCoordinate); intersectionPolygon.Points.Add(HelpNode); j = Increase(jm1Store, 2); } if (!found) { count1++; im1 = Increase(im1, 2); i = Increase(i, 2); if (j != -1) { XYPoint HelpCoordinate = new XYPoint(lineA.P2.X, lineA.P2.Y); XYPoint HelpNode = new XYPoint(HelpCoordinate); intersectionPolygon.Points.Add(HelpNode); } } } lineA = triangleA.GetLine(Decrease(i, 2)); if (CalculatePointToPointDistance(p, lineA.P2) < EPSILON) { i = Increase(i, 2); } lineB = triangleB.GetLine(Decrease(j, 2)); if (CalculatePointToPointDistance(p, lineB.P2) < EPSILON) { j = Increase(j, 2); } }
/// <summary> /// Calculates length of line inside polygon. Parts of the line that is on the edge of /// the polygon only counts with half their length. /// </summary> /// <param name="line">Line</param> /// <param name="polygon">Polygon</param> /// <returns> /// Length of line inside polygon. /// </returns> protected static double CalculateLengthOfLineInsidePolygon(XYLine line, XYPolygon polygon) { var lineList = new List <XYLine> { new XYLine(line) }; for (int i = 0; i < polygon.Points.Count; i++) // For all lines in the polygon { for (int n = 0; n < lineList.Count; n++) { if (lineList.Count > 1000) { throw new Exception("Problems in ElementMapper, line has been cut in more than 1000 pieces !!!"); } if (DoLineSegmentsIntersect((XYLine)lineList[n], polygon.GetLine(i))) { // Split the intersecting line into two lines XYPoint IntersectionPoint = new XYPoint(CalculateIntersectionPoint((XYLine)lineList[n], polygon.GetLine(i))); lineList.Add(new XYLine(IntersectionPoint, lineList[n].P2)); lineList[n].P2.X = IntersectionPoint.X; lineList[n].P2.Y = IntersectionPoint.Y; break; } } } for (int i = 0; i < lineList.Count; i++) { if (lineList.Count > 1000) { throw new Exception("Problems in ElementMapper, line has been cuttes in more than 100 pieces !!!"); } for (int j = 0; j < polygon.Points.Count; j++) { if (IsPointInLineInterior(polygon.GetLine(j).P1, ((XYLine)lineList[i]))) { lineList.Add(new XYLine(polygon.GetLine(j).P1, ((XYLine)lineList[i]).P2)); lineList[i].P2.X = polygon.GetLine(j).P1.X; lineList[i].P2.Y = polygon.GetLine(j).P1.Y; } } } double lengthInside = 0; for (int i = 0; i < lineList.Count; i++) { double sharedLength = 0; for (int j = 0; j < polygon.Points.Count; j++) { sharedLength += CalculateSharedLength(((XYLine)lineList[i]), polygon.GetLine(j)); } if (sharedLength > EPSILON) { lengthInside += sharedLength / 2; } else if (IsPointInPolygon(((XYLine)lineList[i]).GetMidpoint(), polygon)) { lengthInside += ((XYLine)lineList[i]).GetLength(); } } return(lengthInside); }
/// <summary> /// The method calculates the intersection area of triangle a and b both /// of type XYPolygon. /// </summary> /// <param name="triangleA">Triangle of type XYPolygon</param> /// <param name="triangleB">Triangle of type XYPolygon</param> /// <returns> /// Intersection area between the triangles triangleA and triAngleB. /// </returns> protected static double TriangleIntersectionArea(XYPolygon triangleA, XYPolygon triangleB) { // TODO: Implement new algorithm - it is not very robust. // Consider an approach similar to the one used by DotSpatial and Java Topology Suite try { if (triangleA.Points.Count != 3 || triangleB.Points.Count != 3) { throw new System.Exception("Argument must be a polygon with 3 points"); } // TODO: implement an epsilon depending on the two triangles at hand. //XYExtent extentA = XYExtentUtil.GetExtent(triangleA); //XYExtent extentB = XYExtentUtil.GetExtent(triangleB); //double scalingLength // = Math.Max(extentA.XMax - extentA.XMin, // Math.Max(extentA.YMax - extentA.YMin, // Math.Max(extentB.XMax - extentB.XMin, extentB.YMax - extentB.YMin))); //double epsilon = EPSILON * scalingLength; int i = 1; // Index for "next" node in polygon a. int j = -1; // Index for "next" node in polygon b. // -1 indicates that the first has not yet been found. double area = 0; // Intersection area. Returned. XYPolygon intersectionPolygon = new XYPolygon(); // Intersection polygon. XYPoint pFirst = new XYPoint(); // First intersection point between triangles XYPoint pIntersect = new XYPoint(); // Latest intersection node found pIntersect.X = triangleA.Points[0].X; pIntersect.Y = triangleA.Points[0].Y; Intersect(triangleA, triangleB, ref pIntersect, ref i, ref j, ref intersectionPolygon); pFirst = pIntersect; if (j != -1) { int jStop = IncrementModula(j, 3); bool complete = false; int count = 0; while (!complete) { // coordinates for vectors pointing to next triangleA and triangleB point respectively double vax = triangleA.Points[i].X - pIntersect.X; double vay = triangleA.Points[i].Y - pIntersect.Y; double vbx = triangleB.Points[j].X - pIntersect.X; double vby = triangleB.Points[j].Y - pIntersect.Y; // The sideOf tells if the vb vector or the va vector is the one pointing "left" // If sideOf is positive, vb is pointing left, otherwise va is pointing left // The "left" vector is the one that is inside the polygon. double sideOf = vax * vby - vay * vbx; // Make sure to get out of EPSILON reach from the original point, hence 2*EPSILON if (sideOf < 0 && IsPointInPolygon(pIntersect.X + 2 * EPSILON * vax, pIntersect.Y + 2 * EPSILON * vay, triangleB)) { Intersect(triangleA, triangleB, ref pIntersect, ref i, ref j, ref intersectionPolygon); } else if (sideOf > 0 && IsPointInPolygon(pIntersect.X + 2 * EPSILON * vbx, pIntersect.Y + 2 * EPSILON * vby, triangleA)) { Intersect(triangleB, triangleA, ref pIntersect, ref j, ref i, ref intersectionPolygon); } // can be true if the point is on the edge of the triangleB // TODO: Replace with IsPointOnEdge of triangleB else if (IsPointInPolygonOrOnEdge(pIntersect.X + 2 * EPSILON * vax, pIntersect.Y + 2 * EPSILON * vay, triangleB)) { Intersect(triangleA, triangleB, ref pIntersect, ref i, ref j, ref intersectionPolygon); } // can be true if the point is on the edge of the triangleA // Should never happen, since above test basically does the same // TODO: Replace with IsPointOnEdge of triangleA else if (IsPointInPolygonOrOnEdge(pIntersect.X + 2 * EPSILON * vbx, pIntersect.Y + 2 * EPSILON * vby, triangleA)) { Intersect(triangleB, triangleA, ref pIntersect, ref j, ref i, ref intersectionPolygon); } else // triangleA and triangleB only touches one another but do not intersect { area = 0; return(area); } if (intersectionPolygon.Points.Count > 1) { complete = (CalculatePointToPointDistance(pIntersect, pFirst) < EPSILON); } count++; if (count > 20) { throw new System.Exception("Failed to find intersection polygon"); } } area = intersectionPolygon.GetArea(); } else { XYPoint pa = new XYPoint(); // internal point in triangle a XYPoint pb = new XYPoint(); // internal point in triangle b pa.X = (triangleA.GetX(0) + triangleA.GetX(1) + triangleA.GetX(2)) / 3; pa.Y = (triangleA.GetY(0) + triangleA.GetY(1) + triangleA.GetY(2)) / 3; pb.X = (triangleB.GetX(0) + triangleB.GetX(1) + triangleB.GetX(2)) / 3; pb.Y = (triangleB.GetY(0) + triangleB.GetY(1) + triangleB.GetY(2)) / 3; if (IsPointInPolygon(pa, triangleB) || IsPointInPolygon(pb, triangleA)) // triangleA is completely inside triangleB { area = Math.Min(triangleA.GetArea(), triangleB.GetArea()); } else // triangleA and triangleB do dot intersect { area = 0; } } return(area); } catch (System.Exception e) { throw new System.Exception("TriangleIntersectionArea failed", e); } }
/// <summary> /// Returns an ArrayList of triangles of type XYPolygon describing the /// triangalation of the polygon. /// </summary> /// <param></param> /// <returns> /// A triangulation of the polygon. /// </returns> public ArrayList GetTriangulation() { int i = 0; int im1 = 0; int ip1 = 0; int n = 0; XYPolygon LocalPolygon = new XYPolygon(this); ArrayList TriangleList = new ArrayList(); while (LocalPolygon.Points.Count > 3) { i = LocalPolygon.FindEar(); n = LocalPolygon.Points.Count; im1 = i-1; ip1 = i+1; if (i == 0) { im1 = n-1; } else if (i == n-1) { ip1 = 0; } XYPoint Nodeim1 = new XYPoint((XYPoint)LocalPolygon.Points[im1]); XYPoint Nodei = new XYPoint((XYPoint)LocalPolygon.Points[i]); XYPoint Nodeip1 = new XYPoint((XYPoint)LocalPolygon.Points[ip1]); XYPolygon Triangle = new XYPolygon(); Triangle.Points.Add(Nodeim1); Triangle.Points.Add(Nodei); Triangle.Points.Add(Nodeip1); TriangleList.Add(Triangle); LocalPolygon.Points.RemoveAt(i); } TriangleList.Add(LocalPolygon); return TriangleList; }
/// <summary> /// The method decides if the triangle formed by P(i-1), P(i) and /// P(i+1) from Polygon are intersected by any of the other points /// of the polygon. /// </summary> /// <param name="i">Middle index for the three points that forms the triangle</param> /// <returns> /// <p>true: If the triangle P(i-1), P(i), P(i+1) is intersected by other parts of Polygon</p> /// <p>false: otherwise</p> /// </returns> protected bool IsIntersected(int i) { double x = 0; double y = 0; int n = Points.Count; int im1 = i-1; int ip1 = i+1; if (i == 0) { im1 = n-1; } else if (i == n-1) { ip1 = 0; } XYPoint nodeim1 = new XYPoint((XYPoint) Points[im1]); XYPoint nodei = new XYPoint((XYPoint) Points[i]); XYPoint nodeip1 = new XYPoint((XYPoint) Points[ip1]); XYPolygon localPolygon = new XYPolygon(); localPolygon.Points.Add(nodeim1); localPolygon.Points.Add(nodei); localPolygon.Points.Add(nodeip1); int j = 0; bool intersected = false; while (((j < n-1) && (!intersected))) { x = ((XYPoint) Points[j]).X; y = ((XYPoint) Points[j]).Y; if (((((j!=im1) && (j!=i)) && (j!=ip1)) && XYGeometryTools.IsPointInPolygon(x,y,localPolygon))) { return true; } else { j++; } } return false; }
public static double ACalculateLengthOfLineInsidePolygon(XYLine line, XYPolygon polygon) { return CalculateLengthOfLineInsidePolygon(line, polygon); }
public void Protected_TriangleIntersectionArea() { XYPolygon t1 = new XYPolygon(); t1.Points.Add(new XYPoint(0.0, 0.5)); t1.Points.Add(new XYPoint(6.0, 0.5)); t1.Points.Add(new XYPoint(1.0, 7.0)); XYPolygon t2 = new XYPolygon(); t2.Points.Add(new XYPoint(1,1)); t2.Points.Add(new XYPoint(5,1)); t2.Points.Add(new XYPoint(1,5)); XYPolygon t3 = new XYPolygon(); t3.Points.Add(new XYPoint(1,1)); t3.Points.Add(new XYPoint(3,1)); t3.Points.Add(new XYPoint(1,3)); XYPolygon t4 = new XYPolygon(); t4.Points.Add(new XYPoint(1,2)); t4.Points.Add(new XYPoint(3,2)); t4.Points.Add(new XYPoint(3,4)); XYPolygon t5 = new XYPolygon(); t5.Points.Add(new XYPoint(6.5,3.5)); t5.Points.Add(new XYPoint(9.5,3.4)); t5.Points.Add(new XYPoint(7,5)); XYPolygon t6 = new XYPolygon(); t6.Points.Add(new XYPoint(-2,0)); t6.Points.Add(new XYPoint(3,0)); t6.Points.Add(new XYPoint(3,2)); //t2 is fully inside t1 Assert.AreEqual(8,AXYGeometryTools.ATriangleIntersectionArea(t2,t1),"t2, t1"); Assert.AreEqual(8,AXYGeometryTools.ATriangleIntersectionArea(t1,t2),"t1, t2"); // t4 is partly inside t2 Assert.AreEqual((double)7/ (double) 4, AXYGeometryTools.ATriangleIntersectionArea(t2,t4),"t2, t4"); Assert.AreEqual((double)7/ (double) 4, AXYGeometryTools.ATriangleIntersectionArea(t4,t2),"t4, t2"); // t3 is inside t2 but is sharing two edges Assert.AreEqual(2, AXYGeometryTools.ATriangleIntersectionArea(t2,t3),"t2, t3"); Assert.AreEqual(2, AXYGeometryTools.ATriangleIntersectionArea(t3,t2),"t3, t2"); // t1 and t5 has no overlap Assert.AreEqual(0, AXYGeometryTools.ATriangleIntersectionArea(t1,t5),"t1, t5"); Assert.AreEqual(0, AXYGeometryTools.ATriangleIntersectionArea(t5,t1),"t5, t1"); // two times t6 Assert.AreEqual(t6.GetArea(), AXYGeometryTools.ATriangleIntersectionArea(t6,t6),"t6, t6"); }
public static bool AIsPointInPolygonOrOnEdge(double x, double y, XYPolygon polygon) { return IsPointInPolygonOrOnEdge(x, y, polygon); }
/// <summary> /// Determines if a point in inside or outside a polygon. Inside /// includes on the edge for this method. /// Works for both convex and concave polygons (Winding number test) /// </summary> /// <param name="x">x-coordinate for the point</param> /// <param name="y">y-coordiante for the point</param> /// <param name="polygon">Polygon</param> /// <returns> /// <p>true: If the point is inside the polygon</p> /// <p>false: If the point is outside the polygon.</p> /// </returns> protected static bool IsPointInPolygonOrOnEdge(double x, double y, XYPolygon polygon) { bool result = IsPointInPolygon(x, y, polygon); if( result ) { return result; } else { int iLine = 0; while( (!result) && (iLine < polygon.Points.Count) ) { XYLine line = new XYLine(); line = polygon.GetLine(iLine); result = IsPointInLine(x, y, line); iLine++; } } return result; }
public void GetTriangulation() { XYPolygon p1 = new XYPolygon(); p1.Points.Add(new XYPoint(0, 3)); p1.Points.Add(new XYPoint(3, 0)); p1.Points.Add(new XYPoint(8, 0)); p1.Points.Add(new XYPoint(8, 2)); p1.Points.Add(new XYPoint(3, 1)); p1.Points.Add(new XYPoint(3, 3)); p1.Points.Add(new XYPoint(8, 3)); p1.Points.Add(new XYPoint(4, 7)); ArrayList triangleList = p1.GetTriangulation(); XYPolygon refTriangle1 = new XYPolygon(); refTriangle1.Points.Add(new XYPoint(3,0)); refTriangle1.Points.Add(new XYPoint(8,0)); refTriangle1.Points.Add(new XYPoint(8,2)); XYPolygon refTriangle2 = new XYPolygon(); refTriangle2.Points.Add(new XYPoint(3,0)); refTriangle2.Points.Add(new XYPoint(8,2)); refTriangle2.Points.Add(new XYPoint(3,1)); XYPolygon refTriangle3 = new XYPolygon(); refTriangle3.Points.Add(new XYPoint(0,3)); refTriangle3.Points.Add(new XYPoint(3,0)); refTriangle3.Points.Add(new XYPoint(3,1)); XYPolygon refTriangle4 = new XYPolygon(); refTriangle4.Points.Add(new XYPoint(0,3)); refTriangle4.Points.Add(new XYPoint(3,1)); refTriangle4.Points.Add(new XYPoint(3,3)); XYPolygon refTriangle5 = new XYPolygon(); refTriangle5.Points.Add(new XYPoint(4,7)); refTriangle5.Points.Add(new XYPoint(0,3)); refTriangle5.Points.Add(new XYPoint(3,3)); XYPolygon refTriangle6 = new XYPolygon(); refTriangle6.Points.Add(new XYPoint(3,3)); refTriangle6.Points.Add(new XYPoint(8,3)); refTriangle6.Points.Add(new XYPoint(4,7)); Assert.AreEqual(refTriangle1 ,(XYPolygon) triangleList[0]); Assert.AreEqual(refTriangle2 ,(XYPolygon) triangleList[1]); Assert.AreEqual(refTriangle3 ,(XYPolygon) triangleList[2]); Assert.AreEqual(refTriangle4 ,(XYPolygon) triangleList[3]); Assert.AreEqual(refTriangle5 ,(XYPolygon) triangleList[4]); Assert.AreEqual(refTriangle6 ,(XYPolygon) triangleList[5]); }
/// <summary> /// The methods calculates the shared area of two arbitrarily shaped /// polygons. /// </summary> /// <param name="polygonA">Polygon</param> /// <param name="polygonB">Polygon</param> /// <returns> /// <p>The shared area.</p> /// </returns> public static double CalculateSharedArea (XYPolygon polygonA, XYPolygon polygonB) { ArrayList triangleListA = polygonA.GetTriangulation(); ArrayList triangleListB = polygonB.GetTriangulation(); double area = 0; for (int ia = 0; ia < triangleListA.Count; ia++) { XYPolygon triangleA = new XYPolygon((XYPolygon)triangleListA[ia]); for (int ib = 0; ib < triangleListB.Count; ib++) { XYPolygon triangleB = new XYPolygon((XYPolygon)triangleListB[ib]); area = area + TriangleIntersectionArea(triangleA, triangleB); } } return area; }
public void Protected_IsPointInPolygonOrOnEdge() { XYPolygon p1 = new XYPolygon(); p1.Points.Add(new XYPoint(0, 3)); p1.Points.Add(new XYPoint(3, 0)); p1.Points.Add(new XYPoint(8, 0)); p1.Points.Add(new XYPoint(8, 2)); p1.Points.Add(new XYPoint(3, 1)); p1.Points.Add(new XYPoint(3, 3)); p1.Points.Add(new XYPoint(8, 3)); p1.Points.Add(new XYPoint(4, 7)); Assert.AreEqual(true, AXYGeometryTools.AIsPointInPolygonOrOnEdge(0,3,p1),"Test1"); Assert.AreEqual(true, AXYGeometryTools.AIsPointInPolygonOrOnEdge(1,3,p1),"Test2"); Assert.AreEqual(false, AXYGeometryTools.AIsPointInPolygonOrOnEdge(1,5,p1),"Test3"); Assert.AreEqual(true, AXYGeometryTools.AIsPointInPolygonOrOnEdge(3,2,p1),"Test4"); Assert.AreEqual(true, AXYGeometryTools.AIsPointInPolygonOrOnEdge(3,3,p1),"Test5"); Assert.AreEqual(true, AXYGeometryTools.AIsPointInPolygonOrOnEdge(6,1,p1),"Test6"); Assert.AreEqual(false, AXYGeometryTools.AIsPointInPolygonOrOnEdge(6,2,p1),"Test7"); Assert.AreEqual(false, AXYGeometryTools.AIsPointInPolygonOrOnEdge(6,7,p1),"Test8"); }
/// <summary> /// Calculates the length of polyline inside polygon. Lines segments on the edges of /// polygons are included with half their length. /// </summary> /// <param name="polyline">Polyline</param> /// <param name="polygon">Polygon</param> /// <returns> /// Length of polyline inside polygon. /// </returns> public static double CalculateLengthOfPolylineInsidePolygon(XYPolyline polyline, XYPolygon polygon) { double lengthInside = 0; int numberOfLineSegments = polyline.Points.Count - 1; for (int i = 0; i < numberOfLineSegments; i++) { var line = polyline.GetLine(i); lengthInside += CalculateLengthOfLineInsidePolygon(line, polygon); } return(lengthInside); }
public void IsPointInPolygon() { XYPolygon xypolygon = new XYPolygon(); xypolygon.Points.Add(new XYPoint(1,1)); xypolygon.Points.Add(new XYPoint(9,1)); xypolygon.Points.Add(new XYPoint(5,5)); xypolygon.Points.Add(new XYPoint(5,3)); xypolygon.Points.Add(new XYPoint(3,3)); xypolygon.Points.Add(new XYPoint(3,8)); xypolygon.Points.Add(new XYPoint(9,8)); xypolygon.Points.Add(new XYPoint(9,11)); xypolygon.Points.Add(new XYPoint(1,11)); Assert.AreEqual(true, XYGeometryTools.IsPointInPolygon(2,2,xypolygon)); Assert.AreEqual(true, XYGeometryTools.IsPointInPolygon(2,4,xypolygon)); Assert.AreEqual(true, XYGeometryTools.IsPointInPolygon(2,10,xypolygon)); Assert.AreEqual(true, XYGeometryTools.IsPointInPolygon(7,10,xypolygon)); Assert.AreEqual(true, XYGeometryTools.IsPointInPolygon(4,2,xypolygon)); Assert.AreEqual(true, XYGeometryTools.IsPointInPolygon(7,2,xypolygon)); Assert.AreEqual(true, XYGeometryTools.IsPointInPolygon(6,3.5,xypolygon)); Assert.AreEqual(true, XYGeometryTools.IsPointInPolygon(7.5,2,xypolygon)); Assert.AreEqual(false, XYGeometryTools.IsPointInPolygon(0,0,xypolygon)); Assert.AreEqual(false, XYGeometryTools.IsPointInPolygon(4,4,xypolygon)); Assert.AreEqual(false, XYGeometryTools.IsPointInPolygon(4,5,xypolygon)); Assert.AreEqual(false, XYGeometryTools.IsPointInPolygon(10,8,xypolygon)); Assert.AreEqual(false, XYGeometryTools.IsPointInPolygon(9,12,xypolygon)); Assert.AreEqual(true, XYGeometryTools.IsPointInPolygon(new XYPoint(7.5,2),xypolygon)); Assert.AreEqual(false, XYGeometryTools.IsPointInPolygon(new XYPoint(0,0),xypolygon)); }
/// <summary> /// The method calculates the intersection area of triangle a and b both /// of type XYPolygon. /// </summary> /// <param name="triangleA">Triangle of type XYPolygon</param> /// <param name="triangleB">Triangle of type XYPolygon</param> /// <returns> /// Intersection area between the triangles triangleA and triAngleB. /// </returns> protected static double TriangleIntersectionArea(XYPolygon triangleA, XYPolygon triangleB) { try { if (triangleA.Points.Count != 3 || triangleB.Points.Count != 3) { throw new System.Exception("Argument must be a polygon with 3 points"); } int i = 1; // Index for "next" node in polygon a. int j = -1; // Index for "next" node in polygon b. // -1 indicates that the first has not yet been found. double area = 0; // Intersection area. Returned. XYPolygon intersectionPolygon = new XYPolygon(); // Intersection polygon. XYPoint p = new XYPoint(); // Latest intersection node found p.X = ((XYPoint)triangleA.Points[0]).X; p.Y = ((XYPoint)triangleA.Points[0]).Y; Intersect(triangleA, triangleB, ref p, ref i, ref j, ref intersectionPolygon); if (j != -1) { // ERB 8/30/2012: For efficiency, allocate and initialize pFirst inside if block XYPoint pFirst = new XYPoint(); // First intersection point between triangles pFirst = p; int jStop = Increase(j, 2); bool complete = false; int count = 0; while (!complete) { // coordinates for vectors pointing to next triangleA and triangleB point respectively double vax = ((XYPoint)triangleA.Points[i]).X - p.X; double vay = ((XYPoint)triangleA.Points[i]).Y - p.Y; double vbx = ((XYPoint)triangleB.Points[j]).X - p.X; double vby = ((XYPoint)triangleB.Points[j]).Y - p.Y; if (IsPointInPolygonOrOnEdge(p.X + EPSILON * vax, p.Y + EPSILON * vay, triangleB)) { Intersect(triangleA, triangleB, ref p, ref i, ref j, ref intersectionPolygon); } else if (IsPointInPolygonOrOnEdge(p.X + EPSILON * vbx, p.Y + EPSILON * vby, triangleA)) { Intersect(triangleB, triangleA, ref p, ref j, ref i, ref intersectionPolygon); } else // triangleA and triangleB only touches one another but do not intersect { area = 0; return(area); } if (intersectionPolygon.Points.Count > 1) { complete = (CalculatePointToPointDistance(p, pFirst) < EPSILON); } count++; if (count > 20) { throw new System.Exception("Failed to find intersection polygon"); } } area = intersectionPolygon.GetArea(); } else { XYPoint pa = new XYPoint(); // internal point in triangle a XYPoint pb = new XYPoint(); // internal point in triangle b pa.X = (triangleA.GetX(0) + triangleA.GetX(1) + triangleA.GetX(2)) / 3; pa.Y = (triangleA.GetY(0) + triangleA.GetY(1) + triangleA.GetY(2)) / 3; pb.X = (triangleB.GetX(0) + triangleB.GetX(1) + triangleB.GetX(2)) / 3; pb.Y = (triangleB.GetY(0) + triangleB.GetY(1) + triangleB.GetY(2)) / 3; if (IsPointInPolygon(pa, triangleB) || IsPointInPolygon(pb, triangleA)) // triangleA is completely inside triangleB { area = Math.Min(triangleA.GetArea(), triangleB.GetArea()); } else // triangleA and triangleB do dot intersect { area = 0; } } return(area); } catch (System.Exception e) { throw new System.Exception("TriangleIntersectionArea failed", e); } }
private XYPolygon CreateXYPolygon(IElementSet elementSet, int index) { if (elementSet.ElementType != ElementType.XYPolygon) { throw new System.Exception("Cannot create XYPolyline"); } XYPolygon xyPolygon = new XYPolygon(); for (int i = 0; i < elementSet.GetVertexCount(index); i++) { xyPolygon.Points.Add(new XYPoint(elementSet.GetXCoordinate(index,i), elementSet.GetYCoordinate(index,i))); } return xyPolygon; }
/// <summary> /// Determines if a point in inside or outside a polygon. /// Works for both convex and concave polygons (Winding number test) /// </summary> /// <param name="point">Point</param> /// <param name="polygon">Polygon</param> /// <returns> /// <p>true: If the point is inside the polygon</p> /// <p>false: Otherwise.</p> /// </returns> public static bool IsPointInPolygon(XYPoint point, XYPolygon polygon) { return(IsPointInPolygon(point.X, point.Y, polygon)); }
/// <summary> /// The method calculates the intersection points of triangle a and b both /// of type XYPolygon. /// </summary> /// <param name="triangleA">triangle. The search is started along triangleA.</param> /// <param name="triangleB">triangle. Intersection with this triangle are sought.</param> /// <param name="p">Starting point for the search. p must be part of triangleA.</param> /// <param name="i">on input: End index for the first line segment of triangleA in the search. /// on output: End index for the last intersected line segment in triangleA.</param> /// <param name="j">on input: -1 if vertices before intersection is not to be added to list. /// on output: End index for last intersected line segment of triangleB.</param> /// <param name="intersectionPolygon">polygon eventuallu describing the /// intersection area between triangleA and triangleB</param> /// <returns> /// The p, i, j and intersectionPolygon are called by reference and modified in the method. /// </returns> private static void Intersect (XYPolygon triangleA, XYPolygon triangleB, ref XYPoint p, ref int i, ref int j, ref XYPolygon intersectionPolygon) { XYLine lineA; XYLine lineB; int im1 = Decrease(i, 2); // "i-1" int count1 = 0; bool found = false; while ((count1 < 3) && (!found)) { lineA = triangleA.GetLine(im1); if (count1 == 0) { lineA.P1.X = p.X; lineA.P1.Y = p.Y; } double MinDist = -1; // Distance used when a line is crossed more than once int jm1 = 0; // "j-1" int jm1Store = -1; while (jm1 < 3) { lineB = triangleB.GetLine(jm1); found = IntersectionPoint(lineA, lineB, ref p); double Dist = CalculatePointToPointDistance(lineA.P1,p); if (Dist < EPSILON) { found = false; } if (found) { if ((MinDist < 0) || (Dist < MinDist)) { MinDist = Dist; jm1Store = jm1; } } jm1++; } if ( jm1Store > -1 ) { lineB = triangleB.GetLine(jm1Store); found = IntersectionPoint(lineA, lineB, ref p); XYPoint HelpCoordinate = new XYPoint(p.X, p.Y); XYPoint HelpNode = new XYPoint(HelpCoordinate); intersectionPolygon.Points.Add(HelpNode); j = Increase(jm1Store,2); } if (!found) { count1++; im1 = Increase(im1,2); i = Increase(i,2); if (j!=-1) { XYPoint HelpCoordinate = new XYPoint(lineA.P2.X, lineA.P2.Y); XYPoint HelpNode = new XYPoint(HelpCoordinate); intersectionPolygon.Points.Add(HelpNode); } } } lineA = triangleA.GetLine(Decrease(i, 2)); if ( CalculatePointToPointDistance(p, lineA.P2)<EPSILON ) { i = Increase(i, 2); } lineB = triangleB.GetLine(Decrease(j, 2)); if ( CalculatePointToPointDistance(p, lineB.P2)<EPSILON ) { j = Increase(j, 2); } }
public void CalculateLengthOfPolylineInsidePolygon() { XYPolygon xypolygon = new XYPolygon(); xypolygon.Points.Add(new XYPoint(1,1)); xypolygon.Points.Add(new XYPoint(9,1)); xypolygon.Points.Add(new XYPoint(5,5)); xypolygon.Points.Add(new XYPoint(5,3)); xypolygon.Points.Add(new XYPoint(3,3)); xypolygon.Points.Add(new XYPoint(3,8)); xypolygon.Points.Add(new XYPoint(9,8)); xypolygon.Points.Add(new XYPoint(9,11)); xypolygon.Points.Add(new XYPoint(1,11)); XYPolyline xypolyline = new XYPolyline(); xypolyline.Points.Add(new XYPoint(9,13)); xypolyline.Points.Add(new XYPoint(7,12)); xypolyline.Points.Add(new XYPoint(7,10)); xypolyline.Points.Add(new XYPoint(2,10)); xypolyline.Points.Add(new XYPoint(2,3)); Assert.AreEqual(13,XYGeometryTools.CalculateLengthOfPolylineInsidePolygon(xypolyline, xypolygon)); XYPolygon rectangle = new XYPolygon(); rectangle.Points.Add(new XYPoint(10,10)); rectangle.Points.Add(new XYPoint(20,10)); rectangle.Points.Add(new XYPoint(20,40)); rectangle.Points.Add(new XYPoint(10,40)); XYPolyline line1 = new XYPolyline(); line1.Points.Add(new XYPoint(0,20)); line1.Points.Add(new XYPoint(30,20)); Assert.AreEqual(10, XYGeometryTools.CalculateLengthOfPolylineInsidePolygon(line1, rectangle)); // horizontal line crossing XYPolyline line2 = new XYPolyline(); line2.Points.Add(new XYPoint(10,20)); line2.Points.Add(new XYPoint(20,20)); Assert.AreEqual(10, XYGeometryTools.CalculateLengthOfPolylineInsidePolygon(line2, rectangle)); // fits inside XYPolyline line3 = new XYPolyline(); line3.Points.Add(new XYPoint(0,40)); line3.Points.Add(new XYPoint(30,40)); Assert.AreEqual(5, XYGeometryTools.CalculateLengthOfPolylineInsidePolygon(line3, rectangle)); XYPolyline line4 = new XYPolyline(); line4.Points.Add(new XYPoint(20,40)); line4.Points.Add(new XYPoint(20,0)); Assert.AreEqual(15, XYGeometryTools.CalculateLengthOfPolylineInsidePolygon(line4, rectangle)); XYPolyline line5 = new XYPolyline(); line5.Points.Add(new XYPoint(20,40)); line5.Points.Add(new XYPoint(20,10)); Assert.AreEqual(15, XYGeometryTools.CalculateLengthOfPolylineInsidePolygon(line5, rectangle)); XYPolyline line6 = new XYPolyline(); line6.Points.Add(new XYPoint(10,40)); line6.Points.Add(new XYPoint(30,40)); Assert.AreEqual(5, XYGeometryTools.CalculateLengthOfPolylineInsidePolygon(line6, rectangle)); XYPolyline line7 = new XYPolyline(); line7.Points.Add(new XYPoint(10,20)); line7.Points.Add(new XYPoint(30,20)); Assert.AreEqual(10, XYGeometryTools.CalculateLengthOfPolylineInsidePolygon(line7, rectangle)); }
/// <summary> /// Determines if a point in inside or outside a polygon. /// Works for both convex and concave polygons (Winding number test) /// </summary> /// <param name="point">Point</param> /// <param name="polygon">Polygon</param> /// <returns> /// <p>true: If the point is inside the polygon</p> /// <p>false: Otherwise.</p> /// </returns> public static bool IsPointInPolygon(XYPoint point, XYPolygon polygon) { return IsPointInPolygon(point.X, point.Y, polygon); }
[Test] public void GetLine() { // -- Triangle -- XYPolygon xypolygon = new XYPolygon(); xypolygon.Points.Add(new XYPoint(1,2)); xypolygon.Points.Add(new XYPoint(4,3)); xypolygon.Points.Add(new XYPoint(2,5)); Assert.AreEqual(new XYLine(1,2,4,3),xypolygon.GetLine(0)); Assert.AreEqual(new XYLine(4,3,2,5),xypolygon.GetLine(1)); Assert.AreEqual(new XYLine(2,5,1,2),xypolygon.GetLine(2)); // -- concave polygon -- XYPolygon xypolygon4 = new XYPolygon(); xypolygon4.Points.Add(new XYPoint(1,1)); xypolygon4.Points.Add(new XYPoint(9,1)); xypolygon4.Points.Add(new XYPoint(5,5)); xypolygon4.Points.Add(new XYPoint(5,3)); xypolygon4.Points.Add(new XYPoint(3,3)); xypolygon4.Points.Add(new XYPoint(3,8)); xypolygon4.Points.Add(new XYPoint(9,8)); xypolygon4.Points.Add(new XYPoint(9,11)); xypolygon4.Points.Add(new XYPoint(1,11)); Assert.AreEqual(new XYLine(1, 1, 9, 1),xypolygon4.GetLine(0)); Assert.AreEqual(new XYLine(9, 1, 5, 5),xypolygon4.GetLine(1)); Assert.AreEqual(new XYLine(5, 5, 5, 3),xypolygon4.GetLine(2)); Assert.AreEqual(new XYLine(5, 3, 3, 3),xypolygon4.GetLine(3)); Assert.AreEqual(new XYLine(3, 3, 3, 8),xypolygon4.GetLine(4)); Assert.AreEqual(new XYLine(3, 8, 9, 8),xypolygon4.GetLine(5)); Assert.AreEqual(new XYLine(9, 8, 9, 11),xypolygon4.GetLine(6)); Assert.AreEqual(new XYLine(9,11, 1 ,11),xypolygon4.GetLine(7)); Assert.AreEqual(new XYLine(1,11, 1 , 1),xypolygon4.GetLine(8)); }
public static double ATriangleIntersectionArea(XYPolygon triangleA, XYPolygon triangleB) { return TriangleIntersectionArea(triangleA, triangleB); }
/// <summary> /// Calculates the length of polyline inside polygon. Lines segments on the edges of /// polygons are included with half their length. /// </summary> /// <param name="polyline">Polyline</param> /// <param name="polygon">Polygon</param> /// <returns> /// Length of polyline inside polygon. /// </returns> public static double CalculateLengthOfPolylineInsidePolygon(XYPolyline polyline, XYPolygon polygon) { double lengthInside = 0; int numberOfLineSegments = polyline.Points.Count - 1; for (int i = 0; i < numberOfLineSegments; i++) { XYLine line = new XYLine(polyline.GetLine(i)); lengthInside += CalculateLengthOfLineInsidePolygon(line,polygon); } return lengthInside; }
/// <summary> /// Calculates length of line inside polygon. Parts of the line that is on the edge of /// the polygon only counts with half their length. /// </summary> /// <param name="line">Line</param> /// <param name="polygon">Polygon</param> /// <returns> /// Length of line inside polygon. /// </returns> protected static double CalculateLengthOfLineInsidePolygon(XYLine line, XYPolygon polygon) { ArrayList lineList = new ArrayList(); lineList.Add(new XYLine(line)); for (int i = 0; i < polygon.Points.Count; i++) // For all lines in the polygon { for (int n = 0; n < lineList.Count; n++) { if (lineList.Count > 1000) { throw new Exception("Problems in ElementMapper, line has been cut in more than 1000 pieces !!!"); } if (DoLineSegmentsIntersect((XYLine)lineList[n], polygon.GetLine(i))) { // Split the intersecting line into two lines XYPoint IntersectionPoint = new XYPoint(CalculateIntersectionPoint((XYLine)lineList[n], polygon.GetLine(i))); lineList.Add(new XYLine(IntersectionPoint, ((XYLine) lineList[n]).P2)); ((XYLine) lineList[n]).P2.X = IntersectionPoint.X; ((XYLine) lineList[n]).P2.Y = IntersectionPoint.Y; break; } } } for (int i = 0; i < lineList.Count; i++) { if (lineList.Count > 1000) { throw new Exception("Problems in ElementMapper, line has been cuttes in more than 100 pieces !!!"); } for (int j = 0; j < polygon.Points.Count; j++) { if (IsPointInLineInterior( polygon.GetLine(j).P1, ((XYLine) lineList[i]))) { lineList.Add(new XYLine(polygon.GetLine(j).P1, ((XYLine) lineList[i]).P2)); ((XYLine) lineList[i]).P2.X = polygon.GetLine(j).P1.X; ((XYLine) lineList[i]).P2.Y = polygon.GetLine(j).P1.Y; } } } double lengthInside = 0; for (int i = 0; i < lineList.Count; i++) { double sharedLength = 0; for (int j = 0; j < polygon.Points.Count; j++) { sharedLength += CalculateSharedLength(((XYLine) lineList[i]), polygon.GetLine(j)); } if (sharedLength > EPSILON) { lengthInside += sharedLength/2; } else if (IsPointInPolygon(((XYLine) lineList[i]).GetMidpoint(), polygon)) { lengthInside += ((XYLine) lineList[i]).GetLength(); } } return lengthInside; }
/// <summary> /// Calculates the mapping matrix between fromElements and toElements. The mapping method /// is decided from the combination of methodDescription, fromElements.ElementType and /// toElements.ElementType. /// The valid values for methodDescription is obtained through use of the /// GetAvailableMethods method. /// </summary> /// /// <remarks> /// UpdateMappingMatrix is called during initialisation. UpdateMappingMatrix must be called prior /// to Mapvalues. /// </remarks> /// /// <param name="methodIdentifier">String identification of mapping method</param> /// <param name="fromElements">The IElementset to map from.</param> /// <param name="toElements">The IElementset to map to</param> /// /// <returns> /// The method has no return value. /// </returns> private void UpdateMappingMatrix(ref IIdentifiable methodIdentifier, ref IElementSet fromElements, ref IElementSet toElements) { try { ElementSetChecker.CheckElementSet(fromElements); ElementSetChecker.CheckElementSet(toElements); _method = SpatialAdaptedOutputFactory.GetMethod(methodIdentifier); _numberOfToRows = toElements.ElementCount; _numberOfFromColumns = fromElements.ElementCount; _mappingMatrix = new DoubleSparseMatrix(_numberOfToRows, _numberOfFromColumns); if (fromElements.ElementType == ElementType.Point && toElements.ElementType == ElementType.Point) { #region try { for (int i = 0; i < _numberOfToRows; i++) { XYPoint toPoint = CreateXYPoint(toElements, i); for (int j = 0; j < _numberOfFromColumns; j++) { XYPoint fromPoint = CreateXYPoint(fromElements, j); _mappingMatrix[i, j] = XYGeometryTools.CalculatePointToPointDistance(toPoint, fromPoint); } } if (_method == ElementMapperMethod.Nearest) { for (int i = 0; i < _numberOfToRows; i++) { double minDist = _mappingMatrix[i, 0]; for (int j = 1; j < _numberOfFromColumns; j++) { if (_mappingMatrix[i, j] < minDist) { minDist = _mappingMatrix[i, j]; } } int denominator = 0; for (int j = 0; j < _numberOfFromColumns; j++) { if (_mappingMatrix[i, j] == minDist) { _mappingMatrix[i, j] = 1; denominator++; } else { _mappingMatrix[i, j] = 0; } } for (int j = 0; j < _numberOfFromColumns; j++) { _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator; } } } else if (_method == ElementMapperMethod.Inverse) { for (int i = 0; i < _numberOfToRows; i++) { double minDist = _mappingMatrix[i, 0]; for (int j = 1; j < _numberOfFromColumns; j++) { if (_mappingMatrix[i, j] < minDist) { minDist = _mappingMatrix[i, j]; } } if (minDist == 0) { int denominator = 0; for (int j = 0; j < _numberOfFromColumns; j++) { if (_mappingMatrix[i, j] == minDist) { _mappingMatrix[i, j] = 1; denominator++; } else { _mappingMatrix[i, j] = 0; } } for (int j = 0; j < _numberOfFromColumns; j++) { _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator; } } else { double denominator = 0; for (int j = 0; j < _numberOfFromColumns; j++) { _mappingMatrix[i, j] = 1 / _mappingMatrix[i, j]; denominator = denominator + _mappingMatrix[i, j]; } for (int j = 0; j < _numberOfFromColumns; j++) { _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator; } } } } else { throw new Exception("methodDescription unknown for point point mapping"); } } catch (Exception e) { throw new Exception("Point to point mapping failed", e); } #endregion } else if (fromElements.ElementType == ElementType.Point && toElements.ElementType == ElementType.PolyLine) { #region try { for (int i = 0; i < _numberOfToRows; i++) { XYPolyline toPolyLine = CreateXYPolyline(toElements, i); for (int j = 0; j < _numberOfFromColumns; j++) { XYPoint fromPoint = CreateXYPoint(fromElements, j); _mappingMatrix[i, j] = XYGeometryTools.CalculatePolylineToPointDistance(toPolyLine, fromPoint); } } if (_method == ElementMapperMethod.Nearest) { for (int i = 0; i < _numberOfToRows; i++) { double minDist = _mappingMatrix[i, 0]; for (int j = 1; j < _numberOfFromColumns; j++) { if (_mappingMatrix[i, j] < minDist) { minDist = _mappingMatrix[i, j]; } } int denominator = 0; for (int j = 0; j < _numberOfFromColumns; j++) { if (_mappingMatrix[i, j] == minDist) { _mappingMatrix[i, j] = 1; denominator++; } else { _mappingMatrix[i, j] = 0; } } for (int j = 0; j < _numberOfFromColumns; j++) { _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator; } } } else if (_method == ElementMapperMethod.Inverse) { for (int i = 0; i < _numberOfToRows; i++) { double minDist = _mappingMatrix[i, 0]; for (int j = 1; j < _numberOfFromColumns; j++) { if (_mappingMatrix[i, j] < minDist) { minDist = _mappingMatrix[i, j]; } } if (minDist == 0) { int denominator = 0; for (int j = 0; j < _numberOfFromColumns; j++) { if (_mappingMatrix[i, j] == minDist) { _mappingMatrix[i, j] = 1; denominator++; } else { _mappingMatrix[i, j] = 0; } } for (int j = 0; j < _numberOfFromColumns; j++) { _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator; } } else { double denominator = 0; for (int j = 0; j < _numberOfFromColumns; j++) { _mappingMatrix[i, j] = 1 / _mappingMatrix[i, j]; denominator = denominator + _mappingMatrix[i, j]; } for (int j = 0; j < _numberOfFromColumns; j++) { _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator; } } } } else { throw new Exception("methodDescription unknown for point to polyline mapping"); } } catch (Exception e) { throw new Exception("Point to polyline mapping failed", e); } #endregion } else if (fromElements.ElementType == ElementType.Point && toElements.ElementType == ElementType.Polygon) { #region try { for (int i = 0; i < _numberOfToRows; i++) { XYPolygon polygon = CreateXYPolygon(toElements, i); int count = 0; XYPoint point; for (int n = 0; n < _numberOfFromColumns; n++) { point = CreateXYPoint(fromElements, n); if (XYGeometryTools.IsPointInPolygon(point, polygon)) { if (_method == ElementMapperMethod.Mean) { count = count + 1; } else if (_method == ElementMapperMethod.Sum) { count = 1; } else { throw new Exception( "methodDescription unknown for point to polygon mapping"); } } } for (int n = 0; n < _numberOfFromColumns; n++) { point = CreateXYPoint(fromElements, n); if (XYGeometryTools.IsPointInPolygon(point, polygon)) { _mappingMatrix[i, n] = 1.0 / count; } } } } catch (Exception e) { throw new Exception("Point to polygon mapping failed", e); } #endregion } else if (fromElements.ElementType == ElementType.PolyLine && toElements.ElementType == ElementType.Point) { #region try { for (int i = 0; i < _numberOfToRows; i++) { XYPoint toPoint = CreateXYPoint(toElements, i); for (int j = 0; j < _numberOfFromColumns; j++) { XYPolyline fromPolyLine = CreateXYPolyline(fromElements, j); _mappingMatrix[i, j] = XYGeometryTools.CalculatePolylineToPointDistance(fromPolyLine, toPoint); } } if (_method == ElementMapperMethod.Nearest) { for (int i = 0; i < _numberOfToRows; i++) { double minDist = _mappingMatrix[i, 0]; for (int j = 1; j < _numberOfFromColumns; j++) { if (_mappingMatrix[i, j] < minDist) { minDist = _mappingMatrix[i, j]; } } int denominator = 0; for (int j = 0; j < _numberOfFromColumns; j++) { if (_mappingMatrix[i, j] == minDist) { _mappingMatrix[i, j] = 1; denominator++; } else { _mappingMatrix[i, j] = 0; } } for (int j = 0; j < _numberOfFromColumns; j++) { _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator; } } } else if (_method == ElementMapperMethod.Inverse) { for (int i = 0; i < _numberOfToRows; i++) { double minDist = _mappingMatrix[i, 0]; for (int j = 1; j < _numberOfFromColumns; j++) { if (_mappingMatrix[i, j] < minDist) { minDist = _mappingMatrix[i, j]; } } if (minDist == 0) { int denominator = 0; for (int j = 0; j < _numberOfFromColumns; j++) { if (_mappingMatrix[i, j] == minDist) { _mappingMatrix[i, j] = 1; denominator++; } else { _mappingMatrix[i, j] = 0; } } for (int j = 0; j < _numberOfFromColumns; j++) { _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator; } } else { double denominator = 0; for (int j = 0; j < _numberOfFromColumns; j++) { _mappingMatrix[i, j] = 1 / _mappingMatrix[i, j]; denominator = denominator + _mappingMatrix[i, j]; } for (int j = 0; j < _numberOfFromColumns; j++) { _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator; } } } } else { throw new Exception("methodDescription unknown for polyline to point mapping"); } } catch (Exception e) // Catch for all of the Point to Polyline part { throw new Exception("Polyline to point mapping failed", e); } #endregion } else if (fromElements.ElementType == ElementType.PolyLine && toElements.ElementType == ElementType.Polygon) { #region try { // For each polygon in target for (int i = 0; i < _numberOfToRows; i++) { XYPolygon polygon = CreateXYPolygon(toElements, i); if (_method == ElementMapperMethod.WeightedMean) { double totalLineLengthInPolygon = 0; for (int n = 0; n < _numberOfFromColumns; n++) { XYPolyline polyline = CreateXYPolyline(fromElements, n); _mappingMatrix[i, n] = XYGeometryTools.CalculateLengthOfPolylineInsidePolygon( polyline, polygon); totalLineLengthInPolygon += _mappingMatrix[i, n]; } if (totalLineLengthInPolygon > 0) { for (int n = 0; n < _numberOfFromColumns; n++) { _mappingMatrix[i, n] = _mappingMatrix[i, n] / totalLineLengthInPolygon; } } } else if (_method == ElementMapperMethod.WeightedSum) { // For each line segment in PolyLine for (int n = 0; n < _numberOfFromColumns; n++) { XYPolyline polyline = CreateXYPolyline(fromElements, n); _mappingMatrix[i, n] = XYGeometryTools.CalculateLengthOfPolylineInsidePolygon( polyline, polygon) / polyline.GetLength(); } } else { throw new Exception( "methodDescription unknown for polyline to polygon mapping"); } } } catch (Exception e) { throw new Exception("Polyline to polygon mapping failed", e); } #endregion } else if (fromElements.ElementType == ElementType.Polygon && toElements.ElementType == ElementType.Point) { #region try { if (_method != ElementMapperMethod.Value) { throw new Exception("methodDescription unknown for polygon to point mapping"); } // Only create search tree if number of cols/rows is larger than say 10/10. bool useSearchTree = _numberOfFromColumns > 10 && _numberOfToRows > 10; XYElementSearchTree <int> fromSearchTree = null; ICollection <int> fromCandidateElmts = null; if (useSearchTree) { fromSearchTree = XYElementSearchTree <int> .BuildSearchTree(fromElements); } else { fromCandidateElmts = new IntSequence(0, _numberOfFromColumns - 1); } for (int n = 0; n < _numberOfToRows; n++) { XYPoint point = CreateXYPoint(toElements, n); if (useSearchTree) { XYExtent toExtent = XYExtentUtil.GetExtent(point, XYGeometryTools.EPSILON); fromCandidateElmts = fromSearchTree.FindElements(toExtent); } int count = 0; // Check first for strict inclusion foreach (int i in fromCandidateElmts) { XYPolygon polygon = CreateXYPolygon(fromElements, i); if (XYGeometryTools.IsPointInPolygon(point, polygon)) { _mappingMatrix[n, i] = 1.0; count++; } } if (count == 0) { // Not strictly inside any polygon, check also edges foreach (int i in fromCandidateElmts) { XYPolygon polygon = CreateXYPolygon(fromElements, i); if (XYGeometryTools.IsPointInPolygonOrOnEdge(point, polygon)) { _mappingMatrix[n, i] = 1.0; count++; } } } if (count > 1) { // In case of more than one hit, use average foreach (int i in fromCandidateElmts) { if (_mappingMatrix[n, i] != 0.0) { _mappingMatrix[n, i] = 1.0 / count; } } } } } catch (Exception e) { throw new Exception("Polygon to point mapping failed", e); } #endregion } else if (fromElements.ElementType == ElementType.Polygon && toElements.ElementType == ElementType.PolyLine) // Polygon to PolyLine { #region try { for (int i = 0; i < _numberOfToRows; i++) { XYPolyline polyline = CreateXYPolyline(toElements, i); if (_method == ElementMapperMethod.WeightedMean) { for (int n = 0; n < _numberOfFromColumns; n++) { XYPolygon polygon = CreateXYPolygon(fromElements, n); _mappingMatrix[i, n] = XYGeometryTools.CalculateLengthOfPolylineInsidePolygon( polyline, polygon) / polyline.GetLength(); } double sum = 0; for (int n = 0; n < _numberOfFromColumns; n++) { sum += _mappingMatrix[i, n]; } for (int n = 0; n < _numberOfFromColumns; n++) { _mappingMatrix[i, n] = _mappingMatrix[i, n] / sum; } } else if (_method == ElementMapperMethod.WeightedSum) { for (int n = 0; n < _numberOfFromColumns; n++) { XYPolygon polygon = CreateXYPolygon(fromElements, n); _mappingMatrix[i, n] = XYGeometryTools.CalculateLengthOfPolylineInsidePolygon( polyline, polygon) / polyline.GetLength(); } } else { throw new Exception( "methodDescription unknown for polygon to polyline mapping"); } } } catch (Exception e) // catch for all of Polygon to PolyLine { throw new Exception("Polygon to polyline mapping failed", e); } #endregion } else if (fromElements.ElementType == ElementType.Polygon && toElements.ElementType == ElementType.Polygon) // Polygon to Polygon { #region try { // Only create search tree if number of cols/rows is larger than say 100/10. bool useSearchTree = _numberOfFromColumns > 10 && _numberOfToRows > 10; XYElementSearchTree <int> fromSearchTree = null; ICollection <int> fromCandidateElmts = null; if (useSearchTree) { fromSearchTree = XYElementSearchTree <int> .BuildSearchTree(fromElements); } else { fromCandidateElmts = new IntSequence(0, _numberOfFromColumns - 1); } for (int i = 0; i < _numberOfToRows; i++) { XYPolygon toPolygon = CreateXYPolygon(toElements, i); if (useSearchTree) { XYExtent toExtent = XYExtentUtil.GetExtent(toPolygon); fromCandidateElmts = fromSearchTree.FindElements(toExtent); } foreach (int j in fromCandidateElmts) { XYPolygon fromPolygon = CreateXYPolygon(fromElements, j); _mappingMatrix[i, j] = XYGeometryTools.CalculateSharedArea( toPolygon, fromPolygon); if (_method == ElementMapperMethod.Distribute) { _mappingMatrix[i, j] /= fromPolygon.GetArea(); } } if (_method == ElementMapperMethod.WeightedMean) { double denominator = 0; foreach (int j in fromCandidateElmts) { denominator = denominator + _mappingMatrix[i, j]; } foreach (int j in fromCandidateElmts) { if (denominator != 0) { _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator; } } } else if (_method == ElementMapperMethod.WeightedSum) { foreach (int j in fromCandidateElmts) { _mappingMatrix[i, j] = _mappingMatrix[i, j] / toPolygon.GetArea(); } } else if (_method != ElementMapperMethod.Distribute) { throw new Exception( "methodDescription unknown for polygon to polygon mapping"); } } } catch (Exception e) // catch for all of Polygon to Polygon { throw new Exception("Polygon to polygon mapping failed", e); } #endregion } else // if the fromElementType, toElementType combination is no implemented { throw new Exception( "Mapping of specified ElementTypes not included in ElementMapper"); } } catch (Exception e) { throw new Exception("UpdateMappingMatrix failed to update mapping matrix", e); } }
/// <summary> /// The method calculates the intersection area of triangle a and b both /// of type XYPolygon. /// </summary> /// <param name="triangleA">Triangle of type XYPolygon</param> /// <param name="triangleB">Triangle of type XYPolygon</param> /// <returns> /// Intersection area between the triangles triangleA and triAngleB. /// </returns> protected static double TriangleIntersectionArea(XYPolygon triangleA, XYPolygon triangleB) { try { if (triangleA.Points.Count != 3 || triangleB.Points.Count != 3) { throw new System.Exception("Argument must be a polygon with 3 points"); } int i = 1; // Index for "next" node in polygon a. int j = -1; // Index for "next" node in polygon b. // -1 indicates that the first has not yet been found. double area = 0; // Intersection area. Returned. XYPolygon intersectionPolygon = new XYPolygon(); // Intersection polygon. XYPoint pFirst = new XYPoint(); // First intersection point between triangles XYPoint p = new XYPoint(); // Latest intersection node found p.X = ((XYPoint) triangleA.Points[0]).X; p.Y = ((XYPoint) triangleA.Points[0]).Y; Intersect(triangleA, triangleB, ref p, ref i, ref j, ref intersectionPolygon); pFirst = p; if (j != -1) { int jStop = Increase(j, 2); bool complete = false; int count = 0; while (!complete) { // coordinates for vectors pointing to next triangleA and triangleB point respectively double vax= ((XYPoint) triangleA.Points[i]).X - p.X; double vay= ((XYPoint) triangleA.Points[i]).Y - p.Y; double vbx= ((XYPoint) triangleB.Points[j]).X - p.X; double vby= ((XYPoint) triangleB.Points[j]).Y - p.Y; if(IsPointInPolygonOrOnEdge(p.X + EPSILON*vax, p.Y + EPSILON*vay, triangleB)) { Intersect(triangleA, triangleB, ref p, ref i, ref j, ref intersectionPolygon); } else if(IsPointInPolygonOrOnEdge(p.X + EPSILON*vbx, p.Y + EPSILON*vby, triangleA)) { Intersect(triangleB, triangleA, ref p, ref j, ref i, ref intersectionPolygon); } else // triangleA and triangleB only touches one another but do not intersect { area = 0; return area; } if (intersectionPolygon.Points.Count > 1) { complete = (CalculatePointToPointDistance(p, pFirst) < EPSILON); } count++; if ( count > 20 ) { throw new System.Exception("Failed to find intersection polygon"); } } area = intersectionPolygon.GetArea(); } else { XYPoint pa = new XYPoint(); // internal point in triangle a XYPoint pb = new XYPoint(); // internal point in triangle b pa.X = (triangleA.GetX(0)+triangleA.GetX(1)+triangleA.GetX(2))/3; pa.Y = (triangleA.GetY(0)+triangleA.GetY(1)+triangleA.GetY(2))/3; pb.X = (triangleB.GetX(0)+triangleB.GetX(1)+triangleB.GetX(2))/3; pb.Y = (triangleB.GetY(0)+triangleB.GetY(1)+triangleB.GetY(2))/3; if (IsPointInPolygon(pa,triangleB) || IsPointInPolygon(pb,triangleA)) // triangleA is completely inside triangleB { area = Math.Min(triangleA.GetArea(),triangleB.GetArea()); } else // triangleA and triangleB do dot intersect { area = 0; } } return area; } catch (System.Exception e) { throw new System.Exception("TriangleIntersectionArea failed",e); } }
/// <summary> /// Static method that validates an object with an IElementSet interface. The method /// raises an Exception in case IElementSet does not describe a valid ElementSet. /// The checks made are: /// <p>ElementType: Check</p> /// <p>XYPoint: Only one vertex in each element.</p> /// <p>XYPolyline: At least two vertices in each element.</p> /// <p> All line segments in each element has length > 0</p> /// <p>XYPolygon: At least three vertices in each element.</p> /// <p> Area of each element is larger than 0</p> /// <p> All line segments in each element has length > 0</p> /// <p> No line segments within an element crosses.</p> /// </summary> /// /// <param name="elementSet">Object that implement the IElementSet interface</param> /// /// <returns> /// The method has no return value. /// </returns> public static void CheckElementSet(IElementSet elementSet) { try { if (elementSet.ElementType == ElementType.XYPoint) { for (int i = 0; i < elementSet.ElementCount; i++) { try { if (elementSet.GetVertexCount(i) != 1) { throw new System.Exception("Number of vertices in point element is different from 1."); } } catch (System.Exception e) { throw new System.Exception("ElementID = " + elementSet.GetElementID(i), e); } } } else if (elementSet.ElementType == ElementType.XYPolyLine) { for (int i = 0; i < elementSet.ElementCount; i++) { try { XYPolyline xypolyline = new XYPolyline(); for (int j = 0; j < elementSet.GetVertexCount(i); j++) { XYPoint xypoint = new XYPoint(elementSet.GetXCoordinate(i, j), elementSet.GetYCoordinate(i, j)); xypolyline.Points.Add(xypoint); } xypolyline.Validate(); } catch (System.Exception e) { throw new System.Exception("ElementID = " + elementSet.GetElementID(i), e); } } } else if (elementSet.ElementType == ElementType.XYPolygon) { for (int i = 0; i < elementSet.ElementCount; i++) { try { XYPolygon xypolygon = new XYPolygon(); for (int j = 0; j < elementSet.GetVertexCount(i); j++) { XYPoint xypoint = new XYPoint(elementSet.GetXCoordinate(i, j), elementSet.GetYCoordinate(i, j)); xypolygon.Points.Add(xypoint); } xypolygon.Validate(); } catch (System.Exception e) { throw new System.Exception("ElementID = " + elementSet.GetElementID(i), e); } } } } catch (System.Exception e) { throw new System.Exception("ElementSet with ID = " + elementSet.ID + " is invalid", e); } }
private void panelViewer_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { // write x and y coordinates double x = ((e.X - _margin) / _scale) + _minX; double y = _minY - (e.Y + _margin - panelViewer.ClientSize.Height) / _scale; if( _scale != double.MaxValue ) this.label3.Text = "(" + x.ToString("F3") +", " + y.ToString("F3") + ")"; else this.label3.Text = ""; // write elementSet ID and element index this.label4.Text = " "; this.label7.Text = " "; this.label8.Text = " "; this.label9.Text = " "; this.label10.Text = " "; this.label11.Text = " "; for (int elementSetNumber = 0; elementSetNumber < this._elementSets.Count; elementSetNumber++) { string elementID = " "; int elementIndex = -9; double distance = 10e30; IElementSet elementSet = (IElementSet) _elementSets[elementSetNumber]; if (elementSetNumber == 0) { this.label7.Text = elementSet.ID.Substring(0, Math.Min(20, elementSet.ID.Length)); } if (elementSetNumber == 1) { this.label9.Text = elementSet.ID.Substring(0, Math.Min(20, elementSet.ID.Length)); } for (int index = 0; index < elementSet.ElementCount; index++) { if (((IElementSet) _elementSets[elementSetNumber]).ElementType == ElementType.XYPolygon) { XYPolygon xyPolygon = new XYPolygon(); for (int i = 0; i < elementSet.GetVertexCount(index); i++) { xyPolygon.Points.Add(new XYPoint(elementSet.GetXCoordinate(index,i), elementSet.GetYCoordinate(index,i))); } if (XYGeometryTools.IsPointInPolygon(x,y,xyPolygon)) { elementID = elementSet.GetElementID(index); elementIndex = index; } } if (((IElementSet) _elementSets[elementSetNumber]).ElementType == ElementType.XYPolyLine) { XYPolyline xyPolyline = new XYPolyline(); for (int i = 0; i < elementSet.GetVertexCount(index); i++) { xyPolyline.Points.Add(new XYPoint(elementSet.GetXCoordinate(index,i), elementSet.GetYCoordinate(index,i))); } double xx = XYGeometryTools.CalculatePolylineToPointDistance(xyPolyline, new XYPoint(x,y)); if (xx < distance) { distance = xx; if (xx < 0.3 * xyPolyline.GetLength()) { elementIndex = index; elementID = elementSet.GetElementID(index); } } } if (elementSetNumber == 0 && elementIndex >= 0) { this.label4.Text = "Index: " + elementIndex.ToString(); this.label8.Text = "ID: " + elementID.Substring(0, Math.Min(17, elementID.Length)); } if (elementSetNumber == 1 && elementIndex >= 0) { this.label10.Text = "Index: " + elementIndex.ToString(); this.label11.Text = "ID: " + elementID.Substring(0, Math.Min(17, elementID.Length)); } } } }