public Polygon Clone() { Polygon g = new Polygon(); for (int k=0;k< contours.Count;k++) { g.AddContour(contours[k].Clone()); } return g; }
public Polygon ToPolygon() { // Check for empty result if ((closedPolygons.Count == 0 || (closedPolygons.Count == 1 && closedPolygons[0].pointList.Count == 0)) && (openPolygons.Count == 0 || (openPolygons.Count == 1 && openPolygons[0].pointList.Count == 0))) { return null; } Polygon polygon = new Polygon (); foreach (PointChain pointChain in closedPolygons) { Contour c = new Contour (); c.AddRange (pointChain.pointList); polygon.AddContour (c); } FixOrientation(polygon); return polygon; }
public void Compute(PolygonOp operation) { subject = ComputeInternal(operation); }
// public PolygonClipper(Region regionSubject, Region regionClipping) { // // Setup subject and clipping polygons // this.regionSubject = regionSubject; // subject = new Polygon(); // Contour scont = new Contour(); // scont.AddRange(regionSubject.points); // subject.AddContour(scont); // SetClippingRegion(regionClipping); // } // // public void SetClippingRegion(Region regionClipping) { // clipping = new Polygon(); // Contour ccont = new Contour(); // ccont.AddRange(regionClipping.points); // clipping.AddContour(ccont); // } public PolygonClipper(Polygon subject, Polygon clipping) { this.subject = subject; this.clipping = clipping; }
/// <summary> /// Since polygons from countries and cells are not perfectly aligned in all cases, this method will take the largest contour and assume this is the resulting polygon /// (even if it's not closed...) /// </summary> public Polygon ToPolygonFromLargestLineStrip() { // Check for empty result if ((closedPolygons.Count == 0 || (closedPolygons.Count == 1 && closedPolygons[0].pointList.Count == 0)) && (openPolygons.Count == 0 || (openPolygons.Count == 1 && openPolygons[0].pointList.Count == 0))) { return null; } // Get the largest contour (open or closed) int maxPoints=-1; PointChain largestPointChain = null; foreach (PointChain pointChain in closedPolygons) { if (pointChain.pointList.Count>maxPoints) { maxPoints = pointChain.pointList.Count; largestPointChain = pointChain; } } foreach (PointChain pointChain in openPolygons) { if (pointChain.pointList.Count>maxPoints) { maxPoints = pointChain.pointList.Count; largestPointChain = pointChain; } } // ... and create a new polygon of that if (maxPoints<0) return null; Polygon polygon = new Polygon (); Contour c = new Contour (); c.AddRange (largestPointChain.pointList); polygon.AddContour (c); FixOrientation(polygon); return polygon; }
// orientation2D_Polygon(): test the orientation of a simple 2D polygon // Input: Point* V = an array of n+1 vertex points with V[n]=V[0] // Return: >0 for counterclockwise // =0 for none (degenerate) // <0 for clockwise // Note: this algorithm is faster than computing the signed area. // From http://geomalgorithms.com/a01-_area.html#orientation2D_Polygon() double[] Orientation(Polygon V) { // first find rightmost lowest vertex of the polygon double[] ou = new double[V.contours.Count]; for(int j=0;j<V.contours.Count;j++) { Contour r = V.contours[j]; int rmin = 0; double xmin = r.points[0].x; double ymin = r.points[0].y; for(int i=0;i<r.points.Count;i++) { Point p = r.points[i]; if (p.y > ymin) { continue; } else if (p.y == ymin) { // just as low if (p.x < xmin) { // and to left continue; } } rmin = i; // a new rightmost lowest vertex xmin = p.x; ymin = p.y; } // test orientation at the rmin vertex // ccw <=> the edge leaving V[rmin] is left of the entering edge if (rmin == 0 || rmin == r.points.Count-1) { ou[j] = isLeft(r.points[r.points.Count-2], r.points[0], r.points[1]); } else { ou[j] = isLeft(r.points[rmin-1], r.points[rmin], r.points[rmin+1]); } } return ou; }
// Change the winding direction of the outer and inner // rings so the outer ring is counter-clockwise and // nesting rings alternate directions. void FixOrientation(Polygon g) { Polygon p = g; //.(geom.Polygon) double[] o = Orientation(p); for (int i=0;i<p.contours.Count;i++) { Contour inner = p.contours[i]; int numInside = 0; for (int j=0;j<p.contours.Count;j++) { Contour outer = p.contours[j]; if (i != j) { if (PolyInPoly(outer, inner)) { numInside++; } } } if (numInside % 2 == 1 && o[i] > 0) { ReversePolygon(inner.points); } else if (numInside % 2 == 0 && o[i] < 0) { ReversePolygon(inner.points); } } }