static void bufferPolygons(GeoShape shape, double b, out GeoPartList output) { foreach (GeoPointList i in shape.getParts()) { GeoPointList part = i; if (part.Count < 3) { continue; } GeoPointList new_part; // first build the buffered line segments: SegmentList segments; foreach (GeoPoint j in part) { Vector3D p0 = j; Vector3D p1 = (j + 1) != part.end() ? *(j + 1) : *part.begin(); Vector3D d = p1 - p0; d.Normalize(); Vector3D b0 = new Vector3D(p0.X + b * d.Y, p0.Y - b * d.X, p1.z()); Vector3D b1 = new Vector3D(p1.X + b * d.Y, p1.Y - b * d.X, p1.z()); segments.Add(new Segment(b0, b1)); } // then intersect each pair of segments to find the new verts: foreach (Segment k in segments) { Segment s0 = k; Segment s1 = (k + 1) != segments.end() ? *(k + 1) : *segments.begin(); Vector3D isect; if (getLineIntersection(s0, s1, isect)) { GeoPoint r = new GeoPoint(isect, part[0].getSRS()); r.setDim(part[0].getDim()); new_part.Add(r); } } if (new_part.Count > 2) { output.Add(new_part); } } }
// ensures that all single-part shapes have their verts wound CCW. static Feature wind(Feature input) { #if TODO if (input.getShapeType() == GeoShape.ShapeType.TYPE_POLYGON) { foreach (GeoShape i in input.getShapes()) { GeoShape shape = i; if (shape.getPartCount() == 1) { GeoPointList part = shape.getPart(0); GeomUtils.openPolygon(part); if (!GeomUtils.isPolygonCCW(part)) { std.reverse(part.begin(), part.end()); } } } } return(input); #endif throw new NotImplementedException(); }
static void bufferLinesToPolygons(GeoShape input, double b, GeoShape output) { // buffering lines turns them into polygons foreach (GeoPointList i in input.getParts()) { GeoPointList part = i; if (part.Count < 2) { continue; } GeoPointList new_part; // collect segments in one direction and then the other. SegmentList segments; foreach (GeoPoint j in part) { Vector3D p0 = j; Vector3D p1 = *(j + 1); Vector3D d = p1 - p0; d.Normalize(); Vector3D b0 = new Vector3D(p0.X + b * d.Y, p0.Y - b * d.X, p1.Z); Vector3D b1 = new Vector3D(p1.X + b * d.Y, p1.Y - b * d.X, p1.Z); segments.Add(new Segment(b0, b1)); // after the last seg, add an end-cap: if (j == part.end() - 2) { Vector3D b2 = new Vector3D(p1.X - b * d.Y, p1.Y + b * d.X, p1.Z); segments.Add(new Segment(b1, b2)); } } // now back the other way: foreach (GeoPoint j in part) //TODO IS IN REVERSE !! { Vector3D p0 = j; Vector3D p1 = *(j + 1); Vector3D d = p1 - p0; d.Normalize(); Vector3D b0 = new Vector3D(p0.X + b * d.Y, p0.Y - b * d.X, p1.Z); Vector3D b1 = new Vector3D(p1.X + b * d.Y, p1.Y - b * d.X, p1.Z); segments.Add(new Segment(b0, b1)); // after the last seg, add an end-cap: if (j == part.rend() - 2) { Vector3D b2 = new Vector3D(p1.X - b * d.Y, p1.Y + b * d.X, p1.z()); segments.Add(new Segment(b1, b2)); } } // then intersect each pair of segments to find the new verts: foreach (Segment k in segments) { Segment s0 = k; Segment s1 = (k + 1) != segments.end() ? *(k + 1) : *segments.begin(); Vector3D isect; if (getLineIntersection(s0, s1, out isect)) { GeoPoint r = new GeoPoint(isect, part[0].getSRS()); r.setDim(part[0].getDim()); new_part.Add(r); } } if (new_part.Count > 2) { output.getParts().Add(new_part); } } }