public Geobuf.Data.Geometry polyToGeobuf(Polygon poly) { Geobuf.Data.Geometry.Builder builder = Geobuf.Data.Geometry.newBuilder().setType(Geobuf.Data.Geometry.Type.POLYGON); Stream<LineString> interiorRings = IntStream.range(0, poly.getNumInteriorRing()).mapToObj(poly::getInteriorRingN); Stream.concat(Stream.of(poly.getExteriorRing()), interiorRings) .forEach(r -> addRing(r, builder)); return builder.build(); }
/** Add a ring to a builder */ private void addRing(LineString r, Geobuf.Data.Geometry.Builder builder) { // skip last point, same as first builder.addLengths(r.getNumPoints() - 1); long x, y, prevX = 0, prevY = 0; // last point is same as first, skip for (int i = 0; i < r.getNumPoints() - 1; i++) { // delta code Coordinate coord = r.getCoordinateN(i); // note that roundoff errors do not accumulate x = (long) (coord.x * precisionMultiplier); y = (long) (coord.y * precisionMultiplier); builder.addCoords(x - prevX); builder.addCoords(y - prevY); prevX = x; prevY = y; } }
public Geobuf.Data.Geometry multiPolyToGeobuf(MultiPolygon poly) { Geobuf.Data.Geometry.Builder builder = Geobuf.Data.Geometry.newBuilder().setType(Geobuf.Data.Geometry.Type.MULTIPOLYGON); // first we specify the number of polygons builder.addLengths(poly.getNumGeometries()); for (int i = 0; i < poly.getNumGeometries(); i++) { Polygon p = (Polygon) poly.getGeometryN(i); // how many rings there are builder.addLengths(p.getNumInteriorRing() + 1); Stream<LineString> interiorRings = IntStream.range(0, p.getNumInteriorRing()).<LineString>mapToObj(p::getInteriorRingN); Stream.concat(Stream.of(p.getExteriorRing()), interiorRings) .forEach(r -> addRing(r, builder)); } return builder.build(); }