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