public static void assertEquals(MultiPolygon p1, MultiPolygon p2) {
    assert p1.getNumGeometries() == p2.getNumGeometries()
        : "expected " + p1.getNumGeometries() + " geometries but found " + p2.getNumGeometries();

    // TODO: This test do not check all permutations. So the Test fails
    // if the inner polygons are not ordered the same way in both Multipolygons
    for (int i = 0; i < p1.getNumGeometries(); i++) {
      Geometry a = p1.getGeometryN(i);
      Geometry b = p2.getGeometryN(i);
      assertEquals(a, b);
    }
  }
  /**
   * make sure outer ring is CCW and holes are CW for all the polygons in the Geometry
   *
   * @param mp set of polygons to check
   */
  MultiPolygon makeGoodSHAPEMultiPolygon(MultiPolygon mp) {
    MultiPolygon result;
    Polygon[] ps = new Polygon[mp.getNumGeometries()];

    // check each sub-polygon
    for (int t = 0; t < mp.getNumGeometries(); t++) {
      ps[t] = makeGoodSHAPEPolygon((Polygon) mp.getGeometryN(t));
    }

    result = new MultiPolygon(ps, new PrecisionModel(), 0);

    return result;
  }
 protected Geometry transformMultiPolygon(MultiPolygon geom, Geometry parent) {
   List transGeomList = new ArrayList();
   for (int i = 0; i < geom.getNumGeometries(); i++) {
     Geometry transformGeom = transformPolygon((Polygon) geom.getGeometryN(i), geom);
     if (transformGeom == null) continue;
     if (transformGeom.isEmpty()) continue;
     transGeomList.add(transformGeom);
   }
   return factory.buildGeometry(transGeomList);
 }
  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();
  }
 protected static Geometry transformMultiPolygon(
     CoordinateTransform ct, MultiPolygon multiPolygon) {
   Polygon[] polygon = new Polygon[multiPolygon.getNumGeometries()];
   for (int i = 0; i < polygon.length; ++i) {
     polygon[i] =
         multiPolygon
             .getFactory()
             .createPolygon(
                 transformCoordinates(ct, multiPolygon.getGeometryN(i).getCoordinates()));
   }
   return multiPolygon.getFactory().createMultiPolygon(polygon);
 }
 /**
  * Filling multipolygons might result in holes where two polygons overlap. In this method we work
  * around that by drawing each polygon as a separate shape
  *
  * @param g
  * @param shape
  */
 void fillLiteShape(Graphics2D g, LiteShape2 shape) {
   if (shape.getGeometry() instanceof MultiPolygon && shape.getGeometry().getNumGeometries() > 1) {
     MultiPolygon mp = (MultiPolygon) shape.getGeometry();
     for (int i = 0; i < mp.getNumGeometries(); i++) {
       Polygon p = (Polygon) mp.getGeometryN(i);
       try {
         g.fill(new LiteShape2(p, null, null, false, false));
       } catch (Exception e) {
         // should not really happen, but anyways
         throw new RuntimeException("Unexpected error occurred while rendering a multipolygon", e);
       }
     }
   } else {
     g.fill(shape);
   }
 }
  /**
   * Writes the body for a <code>MultiPolygon</code> object. MultiPolygons are encoded into SVG path
   * elements. This function writes the different polygons in one d-attribute of an SVG path
   * element, separated by an 'M' character. (in other words, it calls the super.writeBody for each
   * polygon).
   *
   * @param o The <code>MultiPolygon</code> to be encoded.
   */
  public void writeObject(Object o, GraphicsDocument document, boolean asChild)
      throws RenderException {
    document.writeElement("path", asChild);
    document.writeAttribute("fill-rule", "evenodd");
    document.writeAttributeStart("d");
    MultiPolygon mpoly = (MultiPolygon) o;
    for (int i = 0; i < mpoly.getNumGeometries(); i++) {
      Polygon poly = (Polygon) mpoly.getGeometryN(i);
      LineString shell = poly.getExteriorRing();
      int nHoles = poly.getNumInteriorRing();
      document.writeClosedPathContent(shell.getCoordinates());

      for (int j = 0; j < nHoles; j++) {
        document.writeClosedPathContent(poly.getInteriorRingN(j).getCoordinates());
      }
    }
    document.writeAttributeEnd();
  }
  private String transformMultiPolygonToJsonPolygonArray(MultiPolygon multipolygon) {

    LOGGER.info("Transforming multipolygon to JSON polygon array");

    /*
     * For a multi polygon, we make several simple polygons and put them into an array
     */

    String polygonArray = "[";
    boolean firstElement = true;
    for (int i = 0; i < multipolygon.getNumGeometries(); i++) {
      Polygon polygon = (Polygon) multipolygon.getGeometryN(i);
      String aPolygon = transformPolygonToJsonPolygon(polygon);
      if (firstElement) {
        polygonArray = polygonArray.concat(aPolygon);
        firstElement = false;
      } else {
        polygonArray = polygonArray.concat(", " + aPolygon);
      }
    }

    return polygonArray;
  }
  // Multipolygon
  private String transformMultiPolygonToJsonPolygon(MultiPolygon multipolygon) {

    LOGGER.info("Transforming multipolygon to JSON polygon with several rings in it.");

    /* Lines are like this: {"paths":[[[-122.68,45.53], [-122.58,45.55],[-122.57,45.58],[-122.53,45.6]]],
    "spatialReference":{"wkid":4326}}
    * For a multi polygon, we put several paths.
    * We will assemble it in several parts:
    * 		(a)  {"paths":[
    * 		(b)  several paths, comma separated, each has square brackets:
    * 		(b)  		[  [coords],[coords],[coords]  ]   <== this is one path, with square brackets!
    * 		(b)  		[  [coords],[coords],[coords]  ],  <== this is one path, with square brackets!
    * 		(b)  		[  [coords],[coords],[coords]  ],  <== this is one path, with square brackets!
    *       (c)  ],
    *       (d)  "spatialReference":{"wkid":4326}
    *       (e)  }
    */

    // (1) make paths, and concatenate them, comma separated
    String allRings = "";
    boolean firstElement = true;
    for (int i = 0; i < multipolygon.getNumGeometries(); i++) {
      Polygon polygon = (Polygon) multipolygon.getGeometryN(i);
      String aRing = getPathFromPolygon(polygon);
      if (firstElement) {
        allRings = allRings.concat(aRing);
        firstElement = false;
      } else {
        allRings = allRings.concat(", " + aRing);
      }
    }

    // (2) assemble polygon
    String jsonString = assemblePolygon(allRings, multipolygon);
    return jsonString;
  }
  /**
   * Transform a feature to a JSON string
   *
   * <p>The feature that is passed to this method is transformed to a JSON string according to this
   * site (http://help.arcgis.com/en/webapi/javascript/arcgis/help/jsapi_start.htm).
   *
   * @param geom
   * @return
   * @throws IOException
   */
  private String transformOneFeature(Geometry geom) throws IOException {

    // Depending on geometry's type, transform to json geometry
    String jsonString = "";

    // simple geometries:
    if (geom instanceof Point) {
      jsonString = transformPointToJsonPoint((Point) geom);
    } else if (geom instanceof LineString) {
      jsonString = transformLineStringToJsonLineString((LineString) geom);
    } else if (geom instanceof Polygon) {
      jsonString = transformPolygonToJsonPolygon((Polygon) geom);
    }

    // multipoint
    else if (geom instanceof MultiPoint) {
      MultiPoint multipoint = (MultiPoint) geom;

      // if only one point inside, make normal point out of it
      if (multipoint.getNumGeometries() == 1) {
        Point point = (Point) multipoint.getGeometryN(0);
        jsonString = transformPointToJsonPoint(point);
      } else {
        jsonString = transformMultiPointToJsonMultiPoint(multipoint);
      }

      // multilinestring
    } else if (geom instanceof MultiLineString) {
      MultiLineString multiline = (MultiLineString) geom;

      // if only one linestring inside, make normal linestring out of it
      if (multiline.getNumGeometries() == 1) {
        LineString line = (LineString) multiline.getGeometryN(0);
        jsonString = transformLineStringToJsonLineString(line);
      }
      // real multilinestring
      else {
        if (multiGeometriesToArray) {
          jsonString = transformMultiLineStringToJsonLineStringArray(multiline);
        } else {
          jsonString = transformMultiLineStringToJsonLineString(multiline);
        }
      }

      // multipolygon
    } else if (geom instanceof MultiPolygon) {
      MultiPolygon multipoly = (MultiPolygon) geom;

      // if only one polygon inside, make normal polygon out of it
      if (multipoly.getNumGeometries() == 1) {
        Polygon poly = (Polygon) multipoly.getGeometryN(0);
        jsonString = transformPolygonToJsonPolygon(poly);
      }

      // real multi polygon
      else {
        if (multiGeometriesToArray) {
          jsonString = transformMultiPolygonToJsonPolygonArray(multipoly);
        } else {
          jsonString = transformMultiPolygonToJsonPolygon(multipoly);
        }
      }
    } else {
      LOGGER.error("Feature has no recognized geometry type");
    }

    return jsonString;
  }
Exemple #11
0
  @Override
  public void decodeData(boolean autoClosed)
      throws DecodeException, IOException, TransformException {
    super.decodeData(autoClosed);

    polyMultimap = ArrayListMultimap.create();

    radialDataBlock = new RadialDataBlock();
    radialDataBlock.builder(this.decodeCinradXHeader.getRandomAccessFile(), -1);

    if (autoClosed) {
      this.decodeCinradXHeader.getRandomAccessFile().close();
    }

    SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
    builder.setCRS(crs);
    builder.setName("Cinrad-X Radial Data");
    builder.add("geom", Geometry.class);
    builder.add("colorIndex", Float.class);
    builder.add("value", Float.class);
    schema = builder.buildFeatureType();

    // Reset index counter
    geoIndex = 0;

    if (getPlaneFeatures() == null) {
      planeFeatures = new DefaultFeatureCollection();
    }
    planeFeatures.clear();

    double minA = filter.getMinAzimuth();
    double maxA = filter.getMaxAzimuth();

    if (maxA - minA < 360.0) {
      while (minA >= 360.0) {
        minA -= 360.0;
        maxA -= 360.0;
      }
    }

    for (RadialData data : radialDataBlock.getRadialDatas()) {

      if (testInAzimuthRange(data, minA, maxA)) {
        double startAngle = data.getStartAngle();
        double endAngle = startAngle + data.getAngleWidth();

        // double angle1 = 90.0 - startAngle;
        // double angle2 = 90.0 - endAngle;

        if (startAngle < 0) {
          startAngle += 360;
        }
        if (endAngle < 0) {
          endAngle += 360;
        }

        // Add .00000001 to any 0, 90, 180, 270, 360 values to prevent
        // sin
        // or cos error
        if (startAngle == 0.0
            || startAngle == 90.0
            || startAngle == 180.0
            || startAngle == 270.0
            || startAngle == 360.0) {
          startAngle += 0.00001;
        }
        if (endAngle == 0.0
            || endAngle == 90.0
            || endAngle == 180.0
            || endAngle == 270.0
            || endAngle == 360.0) {
          endAngle += 0.00001;
        }

        startAngle = Math.toRadians(startAngle);
        endAngle = Math.toRadians(endAngle);

        int startRange = data.getRadialHeader().getStartRange();

        int key;
        float value;

        for (Map.Entry<Integer, Float> entry : data.getDataValueArray().entrySet()) {

          value = entry.getValue();
          if (testValueRange(value)) {
            key = entry.getKey();

            // double[] geoXY;
            double[] albX = new double[4];

            double[] albY = new double[4];

            int length1 = startRange + key * data.getRadialHeader().getResolution();
            albX[0] = length1 * Math.sin(startAngle);
            albY[0] = length1 * Math.cos(startAngle);
            albX[1] = length1 * Math.sin(endAngle);
            albY[1] = length1 * Math.cos(endAngle);

            int length2 = length1 + data.getRadialHeader().getResolution();
            albX[2] = length2 * Math.sin(endAngle);
            albY[2] = length2 * Math.cos(endAngle);
            albX[3] = length2 * Math.sin(startAngle);
            albY[3] = length2 * Math.cos(startAngle);

            Coordinate[] cArray = new Coordinate[5];
            // Add the first point
            double[] srcPts0 = {albX[0], albY[0]};
            double[] dstPts0 = new double[2];

            cinradTransform.transform(srcPts0, 0, dstPts0, 0, 1);
            cArray[0] = new Coordinate(dstPts0[0], dstPts0[1]);
            for (int nr = 1; nr < albX.length; nr++) {
              double[] srcPts = {albX[nr], albY[nr]};
              double[] dstPts = new double[2];

              cinradTransform.transform(srcPts, 0, dstPts, 0, 1);

              cArray[nr] = new Coordinate(dstPts[0], dstPts[1]);
            }

            // Add the first point again to close polygon
            cArray[4] = new Coordinate(dstPts0[0], dstPts0[1]);

            LinearRing lr = geoFactory.createLinearRing(cArray);
            Polygon poly = JTSUtilities.makeGoodShapePolygon(geoFactory.createPolygon(lr, null));

            // System.out.println("value:" + entry.getValue());

            if (configuration.getBoolean(COLOR_MODE, true)) {

              polyMultimap.put(CinradXUtils.getRadialColorIndex(entry.getValue()) * 1.0f, poly);
            } else {
              polyMultimap.put(entry.getValue(), poly);
            }
          }
        }
      }
    }

    Set<Float> valueSet = polyMultimap.keySet();
    // System.out.println(valueSet.size());
    if (valueSet.size() > 0) {
      for (Float v : valueSet) {

        Float color = new Float(v);

        Float value = color;
        if (configuration.getBoolean(COLOR_MODE, true)) {
          value = color * 5;
        }

        if (configuration.getBoolean(REDUCE_POLYGONS, true)) {
          logger.debug("REDUCING POLYGONS!");

          if (polyMultimap.get(v).size() > 0) {
            Polygon[] polyArray = new Polygon[polyMultimap.get(v).size()];

            GeometryCollection polyCollection =
                geoFactory.createGeometryCollection(polyMultimap.get(v).toArray(polyArray));

            Geometry union = polyCollection.buffer(geometryBuffer);

            union = TopologyPreservingSimplifier.simplify(union, geometrySimplify);

            logger.debug("Geometry Type:" + union.getGeometryType());

            // polyMultimap.get(v).clear();

            if (union.getGeometryType().equalsIgnoreCase("MultiPolygon")) {

              // logger.debug(union.toString());
              if (configuration.getBoolean(MULTIPOLYGON_MODE, true)) {
                SimpleFeature feature =
                    SimpleFeatureBuilder.build(
                        schema,
                        new Object[] {union, color, value},
                        new Integer(geoIndex++).toString());

                planeFeatures.add(feature);
              } else {

                MultiPolygon multiPolygon = (MultiPolygon) union;
                for (int j = 0; j < multiPolygon.getNumGeometries(); j++) {

                  // create the feature
                  SimpleFeature feature =
                      SimpleFeatureBuilder.build(
                          schema,
                          new Object[] {(Geometry) multiPolygon.getGeometryN(j), color, value},
                          new Integer(geoIndex++).toString());

                  planeFeatures.add(feature);

                  // logger.debug(feature.toString());

                }
              }

            } else if (union.getGeometryType().equalsIgnoreCase("Polygon")) {
              if (configuration.getBoolean(MULTIPOLYGON_MODE, true)) {
                // create the feature
                Polygon[] pa = {(Polygon) union};
                SimpleFeature feature =
                    SimpleFeatureBuilder.build(
                        schema,
                        new Object[] {(Geometry) new MultiPolygon(pa, geoFactory), color, value},
                        new Integer(geoIndex++).toString());

                planeFeatures.add(feature);

              } else {

                // create the feature
                SimpleFeature feature =
                    SimpleFeatureBuilder.build(
                        schema,
                        new Object[] {(Geometry) union, color, value},
                        new Integer(geoIndex++).toString());

                planeFeatures.add(feature);
              }

              // logger.debug(feature.toString());
            }
          }

        } else {

          for (Polygon poly : polyMultimap.get(v)) {

            SimpleFeature feature =
                SimpleFeatureBuilder.build(
                    schema, new Object[] {poly, color, value}, new Integer(geoIndex++).toString());

            planeFeatures.add(feature);

            // logger.debug(feature.toString());
          }
        }
      }
    }
  }
  public static IGlobeFeatureCollection<
          IVector2, ? extends IBoundedGeometry2D<? extends IFinite2DBounds<?>>>
      readFeatures(final DataStore dataStore, final String layerName, final GProjection projection)
          throws Exception {

    final SimpleFeatureSource featureSource = dataStore.getFeatureSource(layerName);

    final SimpleFeatureCollection featuresCollection = featureSource.getFeatures();

    final GIntHolder validCounter = new GIntHolder(0);
    // final GIntHolder polygonsWithHolesCounter = new GIntHolder(0);
    final GIntHolder invalidCounter = new GIntHolder(0);
    //      final GIntHolder validVerticesCounter = new GIntHolder(0);
    final GIntHolder polygonsCounter = new GIntHolder(0);
    final GIntHolder linesCounter = new GIntHolder(0);
    final GIntHolder pointsCounter = new GIntHolder(0);

    final int featuresCount = featuresCollection.size();
    final ArrayList<IGlobeFeature<IVector2, IBoundedGeometry2D<? extends IFinite2DBounds<?>>>>
        euclidFeatures =
            new ArrayList<
                IGlobeFeature<IVector2, IBoundedGeometry2D<? extends IFinite2DBounds<?>>>>(
                featuresCount);

    final GProgress progress =
        new GProgress(featuresCount) {
          @Override
          public void informProgress(
              final double percent, final long elapsed, final long estimatedMsToFinish) {
            //            System.out.println("Loading \"" + fileName.buildPath() + "\" "
            //                               + progressString(percent, elapsed,
            // estimatedMsToFinish));
            System.out.println(
                "Loading data from data storage: "
                    + layerName
                    + " "
                    + progressString(percent, elapsed, estimatedMsToFinish));
          }
        };

    final FeatureIterator<SimpleFeature> iterator = featuresCollection.features();

    while (iterator.hasNext()) {
      final SimpleFeature feature = iterator.next();

      final GeometryAttribute geometryAttribute = feature.getDefaultGeometryProperty();

      final GeometryType type = geometryAttribute.getType();

      if (type.getBinding() == com.vividsolutions.jts.geom.MultiPolygon.class) {

        polygonsCounter.increment();

        final com.vividsolutions.jts.geom.MultiPolygon multipolygon =
            (com.vividsolutions.jts.geom.MultiPolygon) geometryAttribute.getValue();
        final int geometriesCount = multipolygon.getNumGeometries();

        final List<IPolygon2D> polygons = new ArrayList<IPolygon2D>(geometriesCount);
        for (int i = 0; i < geometriesCount; i++) {
          final com.vividsolutions.jts.geom.Polygon jtsPolygon =
              (com.vividsolutions.jts.geom.Polygon) multipolygon.getGeometryN(i);

          try {
            final IPolygon2D euclidPolygon = createEuclidPolygon(projection, jtsPolygon);

            if (euclidPolygon != null) {
              //                     euclidFeatures.add(createFeature(euclidPolygon, feature));
              polygons.add(euclidPolygon);
              validCounter.increment();
            }
          } catch (final IllegalArgumentException e) {
            //                     System.err.println(e.getMessage());
          }
        }

        if (!polygons.isEmpty()) {
          if (polygons.size() == 1) {
            euclidFeatures.add(createFeature(polygons.get(0), feature));
          } else {
            euclidFeatures.add(createFeature(new GMultiGeometry2D<IPolygon2D>(polygons), feature));
          }
        }

      } else if (type.getBinding() == com.vividsolutions.jts.geom.MultiLineString.class) {

        linesCounter.increment();

        final com.vividsolutions.jts.geom.MultiLineString multiline =
            (com.vividsolutions.jts.geom.MultiLineString) geometryAttribute.getValue();
        final int geometriesCount = multiline.getNumGeometries();

        final List<IPolygonalChain2D> lines = new ArrayList<IPolygonalChain2D>(geometriesCount);
        for (int i = 0; i < geometriesCount; i++) {
          final com.vividsolutions.jts.geom.LineString jtsLine =
              (com.vividsolutions.jts.geom.LineString) multiline.getGeometryN(i);

          try {
            final IPolygonalChain2D euclidLine = createLine(jtsLine.getCoordinates(), projection);

            // euclidFeatures.add(createFeature(euclidLines, feature));
            lines.add(euclidLine);
          } catch (final IllegalArgumentException e) {
            //                     System.err.println(e.getMessage());
          }
        }

        if (!lines.isEmpty()) {
          if (lines.size() == 1) {
            euclidFeatures.add(createFeature(lines.get(0), feature));
          } else {
            euclidFeatures.add(
                createFeature(new GMultiGeometry2D<IPolygonalChain2D>(lines), feature));
          }
        }

        validCounter.increment();
      } else if (type.getBinding() == com.vividsolutions.jts.geom.Point.class) {

        pointsCounter.increment();

        final IVector2 euclidPoint =
            createPoint(
                ((com.vividsolutions.jts.geom.Point) geometryAttribute.getValue()).getCoordinate(),
                projection);
        euclidFeatures.add(createFeature(euclidPoint, feature));

        validCounter.increment();
      } else if (type.getBinding() == com.vividsolutions.jts.geom.MultiPoint.class) {
        final IBoundedGeometry2D<? extends IFinite2DBounds<?>> euclidMultipoint =
            createEuclidMultiPoint(geometryAttribute, projection);
        euclidFeatures.add(createFeature(euclidMultipoint, feature));

        validCounter.increment();
      } else {
        invalidCounter.increment();
        System.out.println("invalid type: " + type);
      }

      progress.stepDone();
    }

    dataStore.dispose();

    euclidFeatures.trimToSize();

    System.out.println();
    System.out.println("Features: " + featuresCount);

    System.out.println();
    System.out.println("Read " + validCounter.get() + " valid geometries");

    System.out.println("  => " + polygonsCounter.get() + " valid polygons");
    System.out.println("  => " + linesCounter.get() + " valid lines");
    System.out.println("  => " + pointsCounter.get() + " valid points");
    System.out.println();

    if (invalidCounter.get() > 0) {
      System.out.println("Ignored " + invalidCounter.get() + " invalid geometries");
    }

    System.out.println();

    final SimpleFeatureType schema = featureSource.getSchema();
    final int fieldsCount = schema.getAttributeCount();
    final List<GField> fields = new ArrayList<GField>(fieldsCount);
    System.out.println("Fields count: " + fieldsCount);
    for (int i = 0; i < fieldsCount; i++) {
      final String fieldName = schema.getType(i).getName().getLocalPart();
      System.out.println("Fieldname: " + fieldName);
      final Class<?> fieldType = schema.getType(i).getBinding();

      fields.add(new GField(fieldName, fieldType));
    }

    return new GListFeatureCollection<IVector2, IBoundedGeometry2D<? extends IFinite2DBounds<?>>>(
        GProjection.EPSG_4326, fields, euclidFeatures, "uniqueId_000");
  }