private Geometry readMultiplePolygon()

in baremaps-core/src/main/java/org/apache/baremaps/storage/shapefile/internal/ShapefileByteReader.java [332:380]


  private Geometry readMultiplePolygon(int numParts, int numPoints) {
    /**
     * From ESRI Specification : Parts : 0 5 (meaning : 0 designs the first v1, 5 designs the first
     * v5 on the points list below). Points : v1 v2 v3 v4 v1 v5 v8 v7 v6 v5
     *
     * <p>
     * POSITION FIELD VALUE TYPE NUMBER ORDER Byte 0 Shape Type 5 Integer 1 Little Byte 4 Box Box
     * Double 4 Little Byte 36 NumParts NumParts Integer 1 Little Byte 40 NumPoints NumPoints
     * Integer 1 Little Byte 44 Parts Parts Integer NumParts Little Byte X Points Points Point
     * NumPoints Little
     */

    // Read all the parts indexes (starting at byte 44).
    var partsIndexes = new int[numParts];
    for (int index = 0; index < numParts; index++) {
      partsIndexes[index] = getByteBuffer().getInt();
    }

    // Read all the coordinates.
    var coordinates = new Coordinate[numPoints];
    for (var i = 0; i < numPoints; i++) {
      var x = getByteBuffer().getDouble();
      var y = getByteBuffer().getDouble();
      var coordinate = new Coordinate(x, y);
      coordinates[i] = coordinate;
    }

    // Create the shells and holes.
    var shells = new ArrayList<Polygon>();
    var holes = new LinkedList<Polygon>();
    for (var i = 0; i < partsIndexes.length; i++) {
      var from = partsIndexes[i];
      var to = i < partsIndexes.length - 1 ? partsIndexes[i + 1] : coordinates.length;
      var array = Arrays.copyOfRange(coordinates, from, to);
      var linearRing = geometryFactory.createPolygon(array);
      if (!Orientation.isCCW(linearRing.getCoordinates())) {
        shells.add(linearRing);
      } else {
        holes.add(linearRing);
      }
    }

    // Compute the difference between shells and holes
    var shellsMultiPolygon =
        geometryFactory.createMultiPolygon(shells.toArray(size -> new Polygon[size]));
    var holesMultiPolygon =
        geometryFactory.createMultiPolygon(holes.toArray(size -> new Polygon[size]));
    return shellsMultiPolygon.difference(holesMultiPolygon);
  }