List<Integer> commands(Geometry geometry) {

    x = 0;
    y = 0;

    if (geometry instanceof Polygon) {
      Polygon polygon = (Polygon) geometry;
      if (polygon.getNumInteriorRing() > 0) {
        List<Integer> commands = new ArrayList<Integer>();
        commands.addAll(commands(polygon.getExteriorRing().getCoordinates(), true));
        for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
          commands.addAll(commands(polygon.getInteriorRingN(i).getCoordinates(), true));
        }
        return commands;
      }
    }

    if (geometry instanceof MultiLineString || geometry instanceof MultiPoint) {
      List<Integer> commands = new ArrayList<Integer>();
      GeometryCollection gc = (GeometryCollection) geometry;
      for (int i = 0; i < gc.getNumGeometries(); i++) {
        commands.addAll(commands(gc.getGeometryN(i).getCoordinates(), false));
      }
      return commands;
    }

    return commands(geometry.getCoordinates(), shouldClosePath(geometry));
  }
Beispiel #2
0
  private static void transformGeometry(Geometry geometry) {
    if (geometry == null) {
      return;
    }

    if (geometry instanceof GeometryCollection) {
      GeometryCollection collection = (GeometryCollection) geometry;
      for (int i = 0; i < collection.getNumGeometries(); i++) {
        transformGeometry(collection.getGeometryN(i));
      }
    } else if (geometry instanceof Polygon) {
      Polygon polygon = (Polygon) geometry;
      transformGeometry(polygon.getExteriorRing());
      for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
        transformGeometry(polygon.getInteriorRingN(i));
      }
    } else if (geometry instanceof LineString) {
      LiteCoordinateSequence seq =
          (LiteCoordinateSequence) ((LineString) geometry).getCoordinateSequence();
      double[] coords = seq.getArray();
      for (int i = 0; i < coords.length; i++) {
        coords[i] = (int) (coords[i] + 0.5d);
      }
      seq.setArray(coords);
    }
  }
  private FeatureCollection convexHhull(TaskMonitor monitor, FeatureCollection fc) {
    monitor.allowCancellationRequests();
    monitor.report(I18N.get("ui.plugin.analysis.ConvexHullPlugIn.Computing-Convex-Hull") + "...");

    int size = fc.size();
    GeometryFactory geomFact = null;

    if (size == 0) {
      return null;
    }
    int count = 0;
    Geometry[] geoms = new Geometry[size];

    for (Iterator i = fc.iterator(); i.hasNext(); ) {
      Feature f = (Feature) i.next();
      Geometry geom = f.getGeometry();
      if (geom == null) {
        continue;
      }
      if (geomFact == null) {
        geomFact = geom.getFactory();
      }

      geoms[count++] = geom;
    }
    GeometryCollection gc = geomFact.createGeometryCollection(geoms);
    Geometry hull = gc.convexHull();
    List hullList = new ArrayList();
    hullList.add(hull);

    return FeatureDatasetFactory.createFromGeometry(hullList);
  }
  public void testHomogeneous() throws Exception {
    Node node =
        createNode(
            gcol,
            new ElementInstance[] {point1, point2},
            new Object[] {
              gf.createPoint(new Coordinate(0, 0)), gf.createPoint(new Coordinate(1, 1))
            },
            null,
            null);

    GMLGeometryCollectionTypeBinding s =
        (GMLGeometryCollectionTypeBinding)
            container.getComponentInstanceOfType(GMLGeometryCollectionTypeBinding.class);

    GeometryCollection gc = (GeometryCollection) s.parse(gcol, node, null);
    assertNotNull(gc);
    assertEquals(gc.getNumGeometries(), 2);
    assertTrue(gc.getGeometryN(0) instanceof Point);
    assertTrue(gc.getGeometryN(1) instanceof Point);
    assertEquals(((Point) gc.getGeometryN(0)).getX(), 0d, 0d);
    assertEquals(((Point) gc.getGeometryN(0)).getY(), 0d, 0d);
    assertEquals(((Point) gc.getGeometryN(1)).getX(), 1d, 0d);
    assertEquals(((Point) gc.getGeometryN(1)).getY(), 1d, 0d);
  }
  public void testBounds() throws Exception {
    PrecisionModel pm = new PrecisionModel();
    Geometry[] g = new Geometry[4];
    GeometryFactory gf = new GeometryFactory(pm);

    g[0] = gf.createPoint(new Coordinate(0, 0));
    g[1] = gf.createPoint(new Coordinate(0, 10));
    g[2] = gf.createPoint(new Coordinate(10, 0));
    g[3] = gf.createPoint(new Coordinate(10, 10));

    GeometryCollection gc = gf.createGeometryCollection(g);

    SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
    tb.setName("bounds");
    tb.setCRS(null);
    tb.add("p1", Point.class);

    SimpleFeatureType t = tb.buildFeatureType();

    TreeSetFeatureCollection fc = new TreeSetFeatureCollection(null, t);
    SimpleFeatureBuilder b = new SimpleFeatureBuilder(t);
    for (int i = 0; i < g.length; i++) {
      b.add(g[i]);
      fc.add(b.buildFeature(null));
    }
    assertEquals(gc.getEnvelopeInternal(), fc.getBounds());
  }
  /**
   * Extract the coordinate arrays for a geometry into a List.
   *
   * @param g the Geometry to extract from
   * @param coordArrayList the List to add the coordinate arrays to
   * @param orientPolygons whether or not the arrays in the List should be oriented (clockwise for
   *     the shell, counterclockwise for the holes)
   */
  public static void addCoordinateArrays(Geometry g, boolean orientPolygons, List coordArrayList) {
    if (g.getDimension() <= 0) {
      return;
    } else if (g instanceof LineString) {
      LineString l = (LineString) g;
      coordArrayList.add(l.getCoordinates());
    } else if (g instanceof Polygon) {
      Polygon poly = (Polygon) g;
      Coordinate[] shell = poly.getExteriorRing().getCoordinates();

      if (orientPolygons) {
        shell = ensureOrientation(shell, CGAlgorithms.CLOCKWISE);
      }

      coordArrayList.add(shell);

      for (int i = 0; i < poly.getNumInteriorRing(); i++) {
        Coordinate[] hole = poly.getInteriorRingN(i).getCoordinates();

        if (orientPolygons) {
          hole = ensureOrientation(hole, CGAlgorithms.COUNTERCLOCKWISE);
        }

        coordArrayList.add(hole);
      }
    } else if (g instanceof GeometryCollection) {
      GeometryCollection gc = (GeometryCollection) g;

      for (int i = 0; i < gc.getNumGeometries(); i++) {
        addCoordinateArrays(gc.getGeometryN(i), orientPolygons, coordArrayList);
      }
    } else {
      Assert.shouldNeverReachHere("Geometry of type " + g.getClass().getName() + " not handled");
    }
  }
Beispiel #7
0
 public final void decimateTransformGeneralize(Geometry geometry, MathTransform transform)
     throws TransformException {
   if (geometry instanceof GeometryCollection) {
     GeometryCollection collection = (GeometryCollection) geometry;
     final int length = collection.getNumGeometries();
     for (int i = 0; i < length; i++) {
       decimateTransformGeneralize(collection.getGeometryN(i), transform);
     }
   } else if (geometry instanceof Point) {
     LiteCoordinateSequence seq =
         (LiteCoordinateSequence) ((Point) geometry).getCoordinateSequence();
     decimateTransformGeneralize(seq, transform);
   } else if (geometry instanceof Polygon) {
     Polygon polygon = (Polygon) geometry;
     decimateTransformGeneralize(polygon.getExteriorRing(), transform);
     final int length = polygon.getNumInteriorRing();
     for (int i = 0; i < length; i++) {
       decimateTransformGeneralize(polygon.getInteriorRingN(i), transform);
     }
   } else if (geometry instanceof LineString) {
     LiteCoordinateSequence seq =
         (LiteCoordinateSequence) ((LineString) geometry).getCoordinateSequence();
     decimateTransformGeneralize(seq, transform);
   }
 }
 private void splitAndAddFeatures(
     String layerName, Map<String, ?> attributes, GeometryCollection geometry) {
   for (int i = 0; i < geometry.getNumGeometries(); i++) {
     Geometry subGeometry = geometry.getGeometryN(i);
     addFeature(layerName, attributes, subGeometry);
   }
 }
 protected static Geometry transformGeometryCollection(
     CoordinateTransform ct, GeometryCollection geometryCollection) throws Exception {
   Geometry[] geometry = new Geometry[geometryCollection.getNumGeometries()];
   for (int i = 0; i < geometry.length; ++i) {
     geometry[i] = transformGeometry(ct, geometryCollection.getGeometryN(i));
   }
   return geometryCollection.getFactory().createGeometryCollection(geometry);
 }
  public void testParse() throws Exception {
    GML3MockData.multiGeometry(document, document);

    GeometryCollection multiGeom = (GeometryCollection) parse();
    assertNotNull(multiGeom);

    assertEquals(3, multiGeom.getNumGeometries());
  }
Beispiel #11
0
  private void validate(final Geometry geom, final List<ValidationResult> validationErrors) {

    if (geom.isEmpty()) {
      return;
    }

    if (geom instanceof GeometryCollection) {
      final GeometryCollection gc = (GeometryCollection) geom;
      for (int numGeom = 0; numGeom < gc.getNumGeometries(); numGeom++) {
        validate(gc.getGeometryN(numGeom), validationErrors);
      }
    }

    final ValidationResult result = new ValidationResult();
    result.setWkt(geom.toText());
    final List<String> messages = new ArrayList<String>();

    if (!geom.isValid()) {
      messages.add("Error en topología básica");
    }

    if (!geom.isSimple()) {
      messages.add("No es una geometría simple");
    }

    if (repeatedPointTester.hasRepeatedPoint(geom)) {
      messages.add("Se encuentran vértices repetidos");
    }

    if (geom instanceof Polygon) {
      final Polygon polygon = (Polygon) geom;
      if (CGAlgorithms.isCCW(polygon.getExteriorRing().getCoordinates())) {
        messages.add("Error en orientación del polígono");
      } else {

        for (int numRing = 0; numRing < polygon.getNumInteriorRing(); numRing++) {
          if (!CGAlgorithms.isCCW(polygon.getInteriorRingN(numRing).getCoordinates())) {
            messages.add("Error en orientación del polígono en anillos interiores");
            break;
          }
        }
      }

      if (!validateMinPolygonArea(geom)) {
        messages.add("Error en validación mínima de area de un polígono");
      }
    }

    if (!validateMinSegmentLength(geom)) {
      messages.add("Error en validación mínima de longitud de segmento");
    }

    if (!messages.isEmpty()) {
      result.setMessages(messages);
      validationErrors.add(result);
    }
  }
Beispiel #12
0
  private JSONBuilder writeGeomCollection(GeometryCollection collection) {
    this.key("geometries");
    this.array();

    for (int i = 0, n = collection.getNumGeometries(); i < n; i++) {
      writeGeom(collection.getGeometryN(i));
    }

    return this.endArray();
  }
 protected <T> void accumulateGeometries(
     List<T> collection, Geometry g, Class<? extends T> target) {
   if (target.isInstance(g)) {
     collection.add((T) g);
   } else if (g instanceof GeometryCollection) {
     GeometryCollection coll = (GeometryCollection) g;
     for (int i = 0; i < coll.getNumGeometries(); i++) {
       accumulateGeometries(collection, coll.getGeometryN(i), target);
     }
   }
 }
Beispiel #14
0
 protected Geometry transformGeometryCollection(GeometryCollection geom, Geometry parent) {
   List transGeomList = new ArrayList();
   for (int i = 0; i < geom.getNumGeometries(); i++) {
     Geometry transformGeom = transform(geom.getGeometryN(i));
     if (transformGeom == null) continue;
     if (pruneEmptyGeometry && transformGeom.isEmpty()) continue;
     transGeomList.add(transformGeom);
   }
   if (preserveGeometryCollectionType)
     return factory.createGeometryCollection(GeometryFactory.toGeometryArray(transGeomList));
   return factory.buildGeometry(transGeomList);
 }
Beispiel #15
0
  Map<String, Object> createGeometryCollection(GeometryCollection gcol) {
    LinkedHashMap obj = new LinkedHashMap();

    ArrayList geoms = new ArrayList(gcol.getNumGeometries());
    for (int i = 0; i < gcol.getNumGeometries(); i++) {
      geoms.add(create(gcol.getGeometryN(i)));
    }

    obj.put("type", "GeometryCollection");
    obj.put("geometries", geoms);
    return obj;
  }
Beispiel #16
0
  /** decimates JTS geometries. */
  public final Geometry decimate(Geometry geom) {
    GeometryFactory gFac = new GeometryFactory(geom.getPrecisionModel(), geom.getSRID());
    if (spanx == -1) return geom;
    if (geom instanceof MultiPoint) {
      // TODO check geometry and if its bbox is too small turn it into a 1
      // point geom
      return geom;
    }
    if (geom instanceof GeometryCollection) {
      // TODO check geometry and if its bbox is too small turn it into a
      // 1-2 point geom
      // takes a bit of work because the geometry will need to be
      // recreated.
      GeometryCollection collection = (GeometryCollection) geom;
      Geometry[] result = new Geometry[collection.getDimension()];
      final int numGeometries = collection.getNumGeometries();
      for (int i = 0; i < numGeometries; i++) {
        result[i] = decimate(collection.getGeometryN(i));
      }
      return gFac.createGeometryCollection(result);

    } else if (geom instanceof LineString) {
      LineString line = (LineString) geom;
      CoordinateSequence seq = (CoordinateSequence) line.getCoordinateSequence();
      LiteCoordinateSequence lseq = new LiteCoordinateSequence(seq.toCoordinateArray());

      if (decimateOnEnvelope(line, lseq)) {
        if (lseq.size() >= 2) return gFac.createLineString(lseq);
      }
      if (lseq.size() >= 2) return gFac.createLineString(decimate(lseq));
      return null;
    } else if (geom instanceof Polygon) {
      Polygon line = (Polygon) geom;
      Coordinate[] exterior = decimate(line.getExteriorRing()).getCoordinates();
      forceClosed(exterior);
      if (exterior.length > 3) {
        LinearRing ring = gFac.createLinearRing(exterior);

        final int numRings = line.getNumInteriorRing();
        List<LinearRing> rings = new ArrayList<LinearRing>();

        for (int i = 0; i < numRings; i++) {
          Coordinate[] interior = decimate(line.getInteriorRingN(i)).getCoordinates();
          forceClosed(interior);
          if (interior.length > 3) rings.add(gFac.createLinearRing(interior));
        }
        return gFac.createPolygon(ring, rings.toArray(new LinearRing[] {}));
      }
      return null;
    }
    return geom;
  }
 /**
  * The method explodes a geometry, if it is a multi-geometry (Geometry Collection), into their
  * parts.
  *
  * @param geom
  * @return a list of geometries
  */
 public static ArrayList<Geometry> explodeGeomsIfMultiG(Geometry geom) {
   ArrayList<Geometry> geoms = new ArrayList<Geometry>();
   if (geom instanceof GeometryCollection) {
     // System.out.println("explode multigeoms");
     GeometryCollection multig = (GeometryCollection) geom;
     for (int i = 0; i < multig.getNumGeometries(); i++) {
       Geometry g = (Geometry) multig.getGeometryN(i);
       geoms.add(g);
     }
   } else {
     geoms.add(geom);
   }
   return geoms;
 }
Beispiel #18
0
 List toList(GeometryCollection mgeom) {
   ArrayList list = new ArrayList(mgeom.getNumGeometries());
   for (int i = 0; i < mgeom.getNumGeometries(); i++) {
     Geometry g = mgeom.getGeometryN(i);
     if (g instanceof Polygon) {
       list.add(toList((Polygon) g));
     } else if (g instanceof LineString) {
       list.add(new CoordinateSequenceEncoder(((LineString) g).getCoordinateSequence(), scale));
     } else if (g instanceof Point) {
       list.add(new CoordinateSequenceEncoder(((Point) g).getCoordinateSequence(), scale));
     }
   }
   return list;
 }
Beispiel #19
0
  /**
   * Bulk write method for writing a collection of (hopefully) like geometries of the given
   * ShapeType.
   */
  public void write(final GeometryCollection geometries, final ShapeType type)
      throws IOException, DataStoreException {
    handler = type.getShapeHandler(true);

    writeHeaders(geometries, type);

    lp = shapeBuffer.position();
    for (int i = 0, ii = geometries.getNumGeometries(); i < ii; i++) {
      Geometry g = geometries.getGeometryN(i);

      writeGeometry(g);
    }

    close();
  }
 /**
  * @param geometry
  * @return
  * @throws Exception
  */
 @Override
 public org.geojson.GeometryCollection buildGeoJsonGeometry(GeometryCollection geometry)
     throws Exception {
   logger.trace(
       ":::::::::::::::::::Called {}#buildGeoJsonGeometry for JTS_GEOMETRY : {}\n",
       super.toString(),
       geometry);
   org.geojson.GeometryCollection geometryCollection = new org.geojson.GeometryCollection();
   for (int i = 0; i < geometry.getNumGeometries(); i++) {
     Geometry theGeom = geometry.getGeometryN(i);
     GeometryWriterImplementor implementor =
         GEOMETRY_WRITER_IMPLEMENTOR_STORE.getImplementorByKey(theGeom.getClass());
     geometryCollection.add(implementor.buildGeoJsonGeometry(theGeom));
   }
   return geometryCollection;
 }
  public void testHeterogeneous() throws Exception {
    Node node =
        createNode(
            gcol,
            new ElementInstance[] {point1, point2, line1, ring1, poly1},
            new Object[] {
              gf.createPoint(new Coordinate(0, 0)),
              gf.createPoint(new Coordinate(1, 1)),
              gf.createLineString(new Coordinate[] {new Coordinate(0, 0), new Coordinate(1, 1)}),
              gf.createLinearRing(
                  new Coordinate[] {
                    new Coordinate(0, 0),
                    new Coordinate(1, 1),
                    new Coordinate(2, 2),
                    new Coordinate(0, 0)
                  }),
              gf.createPolygon(
                  gf.createLinearRing(
                      new Coordinate[] {
                        new Coordinate(0, 0),
                        new Coordinate(1, 1),
                        new Coordinate(2, 2),
                        new Coordinate(0, 0)
                      }),
                  null)
            },
            null,
            null);

    GMLGeometryCollectionTypeBinding s =
        (GMLGeometryCollectionTypeBinding)
            container.getComponentInstanceOfType(GMLGeometryCollectionTypeBinding.class);

    GeometryCollection gc = (GeometryCollection) s.parse(gcol, node, null);
    assertNotNull(gc);
    assertEquals(gc.getNumGeometries(), 5);
    assertTrue(gc.getGeometryN(0) instanceof Point);
    assertTrue(gc.getGeometryN(1) instanceof Point);
    assertTrue(gc.getGeometryN(2) instanceof LineString);
    assertTrue(gc.getGeometryN(3) instanceof LinearRing);
    assertTrue(gc.getGeometryN(4) instanceof Polygon);
  }
Beispiel #22
0
 private void writeHeaders(final GeometryCollection geometries, final ShapeType type)
     throws IOException {
   // ShapefileHeader header = new ShapefileHeader();
   // Envelope bounds = geometries.getEnvelopeInternal();
   // header.write(shapeBuffer, type, geometries.getNumGeometries(),
   // fileLength / 2,
   // bounds.getMinX(),bounds.getMinY(), bounds.getMaxX(),bounds.getMaxY()
   // );
   // header.write(indexBuffer, type, geometries.getNumGeometries(), 50 + 4
   // * geometries.getNumGeometries(),
   // bounds.getMinX(),bounds.getMinY(), bounds.getMaxX(),bounds.getMaxY()
   // );
   int fileLength = 100;
   // int largestShapeSize = 0;
   for (int i = geometries.getNumGeometries() - 1; i >= 0; i--) {
     // shape length + record (2 ints)
     int size = handler.getLength(geometries.getGeometryN(i)) + 8;
     fileLength += size;
     // if (size > largestShapeSize)
     // largestShapeSize = size;
   }
   writeHeaders(geometries.getEnvelopeInternal(), type, geometries.getNumGeometries(), fileLength);
 }
Beispiel #23
0
  /**
   * Main method - write the featurecollection to a shapefile (2d, 3d or 4d).
   *
   * @param featureCollection collection to write
   * @param dp 'OutputFile' or 'DefaultValue' to specify where to write, and 'ShapeType' to specify
   *     dimentionality.
   */
  public void write(FeatureCollection featureCollection, DriverProperties dp)
      throws IllegalParametersException, Exception {
    String shpfileName;
    String dbffname;
    String shxfname;

    String path;
    String fname;
    String fname_withoutextention;
    int shapeType;
    int loc;

    GeometryCollection gc;

    shpfileName = dp.getProperty(FILE_PROPERTY_KEY);

    if (shpfileName == null) {
      shpfileName = dp.getProperty(DEFAULT_VALUE_PROPERTY_KEY);
    }

    if (shpfileName == null) {
      throw new IllegalParametersException("no output filename specified");
    }

    loc = shpfileName.lastIndexOf(File.separatorChar);

    if (loc == -1) {
      // loc = 0; // no path - ie. "hills.shp"
      // path = "";
      // fname = shpfileName;
      // probably using the wrong path separator character.
      throw new Exception(
          "couldn't find the path separator character '"
              + File.separatorChar
              + "' in your shape file name. This you're probably using the unix (or dos) one.");
    } else {
      path = shpfileName.substring(0, loc + 1); // ie. "/data1/hills.shp" -> "/data1/"
      fname = shpfileName.substring(loc + 1); // ie. "/data1/hills.shp" -> "hills.shp"
    }

    loc = fname.lastIndexOf(".");

    if (loc == -1) {
      throw new IllegalParametersException("Filename must end in '.shp'");
    }

    fname_withoutextention = fname.substring(0, loc); // ie. "hills.shp" -> "hills."
    dbffname = path + fname_withoutextention + ".dbf";

    writeDbf(featureCollection, dbffname);

    // this gc will be a collection of either multi-points, multi-polygons, or multi-linestrings
    // polygons will have the rings in the correct order
    gc = makeSHAPEGeometryCollection(featureCollection);

    shapeType = 2; // x,y

    if (dp.getProperty(SHAPE_TYPE_PROPERTY_KEY) != null) {
      String st = dp.getProperty(SHAPE_TYPE_PROPERTY_KEY);

      if (st.equalsIgnoreCase("xy")) {
        shapeType = 2;
      } else if (st.equalsIgnoreCase("xym")) {
        shapeType = 3;
      } else if (st.equalsIgnoreCase("xymz")) {
        shapeType = 4;
      } else if (st.equalsIgnoreCase("xyzm")) {
        shapeType = 4;
      } else if (st.equalsIgnoreCase("xyz")) {
        shapeType = 4;
      } else {
        throw new IllegalParametersException(
            "ShapefileWriter.write() - dataproperties has a 'ShapeType' that isnt 'xy', 'xym', or 'xymz'");
      }
    } else {
      if (gc.getNumGeometries() > 0) {
        shapeType = guessCoorinateDims(gc.getGeometryN(0));
      }
    }

    URL url = new URL("file", "localhost", shpfileName);
    Shapefile myshape = new Shapefile(url);
    myshape.write(gc, shapeType);

    shxfname = path + fname_withoutextention + ".shx";

    BufferedOutputStream in = new BufferedOutputStream(new FileOutputStream(shxfname));
    EndianDataOutputStream sfile = new EndianDataOutputStream(in);

    myshape.writeIndex(gc, sfile, shapeType);
  }
  /**
   * Calculates walksheds for a given location, based on time given to walk and the walk speed.
   *
   * <p>Depending on the value for the "output" parameter (i.e. "POINTS", "SHED" or "EDGES"), a
   * different type of GeoJSON geometry is returned. If a SHED is requested, then a ConcaveHull of
   * the EDGES/roads is returned. If that fails, a ConvexHull will be returned.
   *
   * <p>The ConcaveHull parameter is set to 0.005 degrees. The offroad walkspeed is assumed to be
   * 0.83333 m/sec (= 3km/h) until a road is hit.
   *
   * <p>Note that the set of EDGES/roads returned as well as POINTS returned may contain duplicates.
   * If POINTS are requested, then not the end-points are returned at which the max time is reached,
   * but instead all the graph nodes/crossings that are within the time limits.
   *
   * <p>In case there is no road near by within the given time, then a circle for the walktime limit
   * is created and returned for the SHED parameter. Otherwise the edge with the direction towards
   * the closest road. Note that the circle is calculated in Euclidian 2D coordinates, and
   * distortions towards an ellipse will appear if it is transformed/projected to the user location.
   *
   * <p>An example request may look like this:
   * localhost:8080/otp-rest-servlet/ws/iso?layers=traveltime&styles=mask&batch=true&fromPlace=51.040193121307176
   * %2C-114.04471635818481&toPlace
   * =51.09098935%2C-113.95179705&time=2012-06-06T08%3A00%3A00&mode=WALK&maxWalkDistance=10000&walkSpeed=1.38&walkTime=10.7&output=EDGES
   * Though the first parameters (i) layer, (ii) styles and (iii) batch could be discarded.
   *
   * @param walkmins Maximum number of minutes to walk.
   * @param output Can be set to "POINTS", "SHED" or "EDGES" to return different types of GeoJSON
   *     geometry. SHED returns a ConcaveHull or ConvexHull of the edges/roads. POINTS returns all
   *     graph nodes that are within the time limit.
   * @return a JSON document containing geometries (either points, lineStrings or a polygon).
   * @throws Exception
   * @author sstein---geo.uzh.ch
   */
  @GET
  @Produces({MediaType.APPLICATION_JSON})
  public String getIsochrone(
      @QueryParam("walkTime") @DefaultValue("15") double walkmins,
      @QueryParam("output") @DefaultValue("POINTS") String output)
      throws Exception {

    this.debugGeoms = new ArrayList();
    this.tooFastTraversedEdgeGeoms = new ArrayList();

    RoutingRequest sptRequestA = buildRequest(0);
    String from = sptRequestA.getFrom().toString();
    int pos = 1;
    float lat = 0;
    float lon = 0;
    for (String s : from.split(",")) {
      if (s.isEmpty()) {
        // no location
        Response.status(Status.BAD_REQUEST).entity("no position").build();
        return null;
      }
      try {
        float num = Float.parseFloat(s);
        if (pos == 1) {
          lat = num;
        }
        if (pos == 2) {
          lon = num;
        }
      } catch (Exception e) {
        throw new WebApplicationException(
            Response.status(Status.BAD_REQUEST)
                .entity(
                    "Could not parse position string to number. Require numerical lat & long coords.")
                .build());
      }
      pos++;
    }

    GeometryFactory gf = new GeometryFactory();

    Coordinate dropPoint = new Coordinate(lon, lat);

    int walkInMin = (int) Math.floor(walkmins);
    double walkInSec = walkmins * 60;
    LOG.debug(
        "given travel time: " + walkInMin + " mins + " + (walkInSec - (60 * walkInMin)) + " sec");
    // restrict the evaluated SPT size to 30mins for requests with walking < 30min
    // if larger walking times are requested we adjust the evaluated
    // graph dynamically by 1.3 * min -> this should save processing time
    if (walkInMin < 30) {
      sptRequestA.worstTime = sptRequestA.dateTime + (30 * 60);
    } else {
      sptRequestA.worstTime = sptRequestA.dateTime + Math.round(walkInMin * 1.3 * 60);
    }
    // set the switch-time for shed/area calculation, i.e. to decide if the hull is calculated based
    // on points or on edges
    TraverseModeSet modes = sptRequestA.modes;
    LOG.debug("mode(s): " + modes);
    if ((modes.contains(TraverseMode.TRANSIT))
        || (modes.contains(TraverseMode.BUSISH))
        || (modes.contains(TraverseMode.TRAINISH))) {
      shedCalcMethodSwitchTimeInSec =
          60 * 20; // 20min (use 20min for transit, since buses may not come all the time)
    } else if (modes.contains(TraverseMode.CAR)) {
      shedCalcMethodSwitchTimeInSec = 60 * 10; // 10min
    } else if (modes.contains(TraverseMode.BICYCLE)) {
      shedCalcMethodSwitchTimeInSec = 60 * 10; // 10min
    } else {
      shedCalcMethodSwitchTimeInSec = 60 * 20; // 20min
    }
    // set the maxUserSpeed, which is used later to check for u-type streets/crescents when
    // calculating sub-edges;
    // Note, that the car speed depends on the edge itself, so this value may be replaced later
    this.usesCar = false;
    int numberOfModes = modes.getModes().size();
    if (numberOfModes == 1) {
      if (modes.getWalk()) {
        this.maxUserSpeed = sptRequestA.getWalkSpeed();
      } else if (modes.getBicycle()) {
        this.maxUserSpeed = sptRequestA.getBikeSpeed();
      } else if (modes.getDriving()) {
        this.maxUserSpeed = sptRequestA.getCarSpeed();
        this.usesCar = true;
      }
    } else { // for all other cases (multiple-modes)
      // sstein: I thought I may set it to 36.111 m/sec = 130 km/h,
      // but maybe it is better to assume walk speed for transit, i.e. treat it like if the
      // person gets off the bus on the last crossing and walks the "last mile".
      this.maxUserSpeed = sptRequestA.getWalkSpeed();
    }

    if (doSpeedTest) {
      LOG.debug("performing angle and speed based test to detect u-shapes");
    } else {
      LOG.debug("performing only angle based test to detect u-shapes");
    }

    // TODO: OTP prefers to snap to car-roads/ways, which is not so nice, when walking,
    // and a footpath is closer by. So far there is no option to switch that off

    // create the ShortestPathTree
    try {
      sptRequestA.setRoutingContext(graphService.getGraph());
    } catch (Exception e) {
      // if we get an exception here, and in particular a VertexNotFoundException,
      // then it is likely that we chose a (transit) mode without having that (transit) modes data
      LOG.debug("cannot set RoutingContext: " + e.toString());
      LOG.debug("cannot set RoutingContext: setting mode=WALK");
      sptRequestA.setMode(TraverseMode.WALK); // fall back to walk mode
      sptRequestA.setRoutingContext(graphService.getGraph());
    }
    ShortestPathTree sptA = sptService.getShortestPathTree(sptRequestA);
    StreetLocation origin = (StreetLocation) sptRequestA.rctx.fromVertex;
    sptRequestA.cleanup(); // remove inserted points

    // create a LineString for display
    Coordinate pathToStreetCoords[] = new Coordinate[2];
    pathToStreetCoords[0] = dropPoint;
    pathToStreetCoords[1] = origin.getCoordinate();
    LineString pathToStreet = gf.createLineString(pathToStreetCoords);

    // get distance between origin and drop point for time correction
    double distanceToRoad =
        this.distanceLibrary.distance(origin.getY(), origin.getX(), dropPoint.y, dropPoint.x);
    long offRoadTimeCorrection = (long) (distanceToRoad / this.offRoadWalkspeed);

    //
    // --- filter the states ---
    //
    Set<Coordinate> visitedCoords = new HashSet<Coordinate>();
    ArrayList<Edge> allConnectingEdges = new ArrayList<Edge>();
    Coordinate coords[] = null;
    long maxTime = (long) walkInSec - offRoadTimeCorrection;
    // System.out.println("Reducing walktime from: " + (int)(walkmins * 60) + "sec to " + maxTime +
    // "sec due to initial walk of " + distanceToRoad
    // + "m");

    // if the initial walk is already to long, there is no need to parse...
    if (maxTime <= 0) {
      noRoadNearBy = true;
      long timeToWalk = (long) walkInSec;
      long timeBetweenStates = offRoadTimeCorrection;
      long timeMissing = timeToWalk;
      double fraction = (double) timeMissing / (double) timeBetweenStates;
      pathToStreet = getSubLineString(pathToStreet, fraction);
      LOG.debug(
          "no street found within giving travel time (for off-road walkspeed: {} m/sec)",
          this.offRoadWalkspeed);
    } else {
      noRoadNearBy = false;
      Map<ReversibleLineStringWrapper, Edge> connectingEdgesMap = Maps.newHashMap();
      for (State state : sptA.getAllStates()) {
        long et = state.getElapsedTimeSeconds();
        if (et <= maxTime) {
          // -- filter points, as the same coordinate may be passed several times due to the graph
          // structure
          // in a Calgary suburb family homes neighborhood with a 15min walkshed it filtered about
          // 250 points away (while 145 were finally displayed)
          if (visitedCoords.contains(state.getVertex().getCoordinate())) {
            continue;
          } else {
            visitedCoords.add(state.getVertex().getCoordinate());
          }
          // -- get all Edges needed later for the edge representation
          // and to calculate an edge-based walkshed
          // Note, it can happen that we get a null geometry here, e.g. for hop-edges!
          Collection<Edge> vertexEdgesIn = state.getVertex().getIncoming();
          for (Iterator<Edge> iterator = vertexEdgesIn.iterator(); iterator.hasNext(); ) {
            Edge edge = (Edge) iterator.next();
            Geometry edgeGeom = edge.getGeometry();
            if (edgeGeom != null) { // make sure we get only real edges
              if (edgeGeom instanceof LineString) {
                // allConnectingEdges.add(edge); // instead of this, use a map now, so we don't have
                // similar edge many times
                connectingEdgesMap.put(
                    new ReversibleLineStringWrapper((LineString) edgeGeom), edge);
              }
            }
          }
          Collection<Edge> vertexEdgesOut = state.getVertex().getOutgoing();
          for (Iterator<Edge> iterator = vertexEdgesOut.iterator(); iterator.hasNext(); ) {
            Edge edge = (Edge) iterator.next();
            Geometry edgeGeom = edge.getGeometry();
            if (edgeGeom != null) {
              if (edgeGeom instanceof LineString) {
                // allConnectingEdges.add(edge); // instead of this, use a map now, so we don't
                // similar edge many times
                connectingEdgesMap.put(
                    new ReversibleLineStringWrapper((LineString) edgeGeom), edge);
              }
            }
          }
        } // end : if(et < maxTime)
      }
      // --
      // points from list to array, for later
      coords = new Coordinate[visitedCoords.size()];
      int i = 0;
      for (Coordinate c : visitedCoords) coords[i++] = c;

      // connection edges from Map to List
      allConnectingEdges.clear();
      for (Edge tedge : connectingEdgesMap.values()) allConnectingEdges.add(tedge);
    }
    StringWriter sw = new StringWriter();
    GeoJSONBuilder json = new GeoJSONBuilder(sw);
    //
    // -- create the different outputs ---
    //
    try {
      if (output.equals(IsoChrone.RESULT_TYPE_POINTS)) {
        // in case there was no road we create a circle and
        // and return those points
        if (noRoadNearBy) {
          Geometry circleShape = createCirle(dropPoint, pathToStreet);
          coords = circleShape.getCoordinates();
        }
        // -- the states/nodes with time elapsed <= X min.
        LOG.debug("write multipoint geom with {} points", coords.length);
        json.writeGeom(gf.createMultiPoint(coords));
        LOG.debug("done");
      } else if (output.equals(IsoChrone.RESULT_TYPE_SHED)) {

        Geometry geomsArray[] = null;
        // in case there was no road we create a circle
        if (noRoadNearBy) {
          Geometry circleShape = createCirle(dropPoint, pathToStreet);
          json.writeGeom(circleShape);
        } else {
          if (maxTime > shedCalcMethodSwitchTimeInSec) { // eg., walkshed > 20 min
            // -- create a point-based walkshed
            // less exact and should be used for large walksheds with many edges
            LOG.debug("create point-based shed (not from edges)");
            geomsArray = new Geometry[coords.length];
            for (int j = 0; j < geomsArray.length; j++) {
              geomsArray[j] = gf.createPoint(coords[j]);
            }
          } else {
            // -- create an edge-based walkshed
            // it is more exact and should be used for short walks
            LOG.debug("create edge-based shed (not from points)");
            Map<ReversibleLineStringWrapper, LineString> walkShedEdges = Maps.newHashMap();
            // add the walk from the pushpin to closest street point
            walkShedEdges.put(new ReversibleLineStringWrapper(pathToStreet), pathToStreet);
            // get the edges and edge parts within time limits
            ArrayList<LineString> withinTimeEdges =
                this.getLinesAndSubEdgesWithinMaxTime(
                    maxTime,
                    allConnectingEdges,
                    sptA,
                    angleLimitForUShapeDetection,
                    distanceToleranceForUShapeDetection,
                    maxUserSpeed,
                    usesCar,
                    doSpeedTest);
            for (LineString ls : withinTimeEdges) {
              walkShedEdges.put(new ReversibleLineStringWrapper(ls), ls);
            }
            geomsArray = new Geometry[walkShedEdges.size()];
            int k = 0;
            for (LineString ls : walkShedEdges.values()) geomsArray[k++] = ls;
          } // end if-else: maxTime condition
          GeometryCollection gc = gf.createGeometryCollection(geomsArray);
          // create the concave hull, but in case it fails we just return the convex hull
          Geometry outputHull = null;
          LOG.debug(
              "create concave hull from {} geoms with edge length limit of about {} m (distance on meridian)",
              geomsArray.length,
              concaveHullAlpha * 111132);
          // 1deg at Latitude phi = 45deg is about 111.132km
          // (see wikipedia:
          // http://en.wikipedia.org/wiki/Latitude#The_length_of_a_degree_of_latitude)
          try {
            ConcaveHull hull = new ConcaveHull(gc, concaveHullAlpha);
            outputHull = hull.getConcaveHull();
          } catch (Exception e) {
            outputHull = gc.convexHull();
            LOG.debug("Could not generate ConcaveHull for WalkShed, using ConvexHull instead.");
          }
          LOG.debug("write shed geom");
          json.writeGeom(outputHull);
          LOG.debug("done");
        }
      } else if (output.equals(IsoChrone.RESULT_TYPE_EDGES)) {
        // in case there was no road we return only the suggested path to the street
        if (noRoadNearBy) {
          json.writeGeom(pathToStreet);
        } else {
          // -- if we would use only the edges from the paths to the origin we will miss
          // some edges that will be never on the shortest path (e.g. loops/crescents).
          // However, we can retrieve all edges by checking the times for each
          // edge end-point
          Map<ReversibleLineStringWrapper, LineString> walkShedEdges = Maps.newHashMap();
          // add the walk from the pushpin to closest street point
          walkShedEdges.put(new ReversibleLineStringWrapper(pathToStreet), pathToStreet);
          // get the edges and edge parts within time limits
          ArrayList<LineString> withinTimeEdges =
              this.getLinesAndSubEdgesWithinMaxTime(
                  maxTime,
                  allConnectingEdges,
                  sptA,
                  angleLimitForUShapeDetection,
                  distanceToleranceForUShapeDetection,
                  maxUserSpeed,
                  usesCar,
                  doSpeedTest);
          for (LineString ls : withinTimeEdges) {
            walkShedEdges.put(new ReversibleLineStringWrapper(ls), ls);
          }
          Geometry mls = null;
          LineString edges[] = new LineString[walkShedEdges.size()];
          int k = 0;
          for (LineString ls : walkShedEdges.values()) edges[k++] = ls;
          LOG.debug("create multilinestring from {} geoms", edges.length);
          mls = gf.createMultiLineString(edges);
          LOG.debug("write geom");
          json.writeGeom(mls);
          LOG.debug("done");
        }
      } else if (output.equals("DEBUGEDGES")) {
        // -- for debugging, i.e. display of detected u-shapes/crescents
        ArrayList<LineString> withinTimeEdges =
            this.getLinesAndSubEdgesWithinMaxTime(
                maxTime,
                allConnectingEdges,
                sptA,
                angleLimitForUShapeDetection,
                distanceToleranceForUShapeDetection,
                maxUserSpeed,
                usesCar,
                doSpeedTest);
        if (this.showTooFastEdgesAsDebugGeomsANDnotUShapes) {
          LOG.debug("displaying edges that are traversed too fast");
          this.debugGeoms = this.tooFastTraversedEdgeGeoms;
        } else {
          LOG.debug("displaying detected u-shaped roads/crescents");
        }
        LineString edges[] = new LineString[this.debugGeoms.size()];
        int k = 0;
        for (Iterator iterator = debugGeoms.iterator(); iterator.hasNext(); ) {
          LineString ls = (LineString) iterator.next();
          edges[k] = ls;
          k++;
        }
        Geometry mls = gf.createMultiLineString(edges);
        LOG.debug("write debug geom");
        json.writeGeom(mls);
        LOG.debug("done");
      }
    } catch (org.codehaus.jettison.json.JSONException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return sw.toString();
  }
    /**
     * SAX handler - handle state information and transitions based on ending elements.
     *
     * @param uri Description of the Parameter
     * @param name Description of the Parameter
     * @param qName Description of the Parameter
     * @exception SAXException Description of the Exception
     */
    @SuppressWarnings({"unused", "unchecked"})
    public void endElement(String uri, String name, String qName) throws SAXException {
      // System.out.println("/" + name);
      // System.out.println("the ena name="+name);
      if (placemarkactive
          && !CollectionUtils.intersection(visits, LEGALNAMES).isEmpty()
          && currGeomHandler == null
          && !lastEltData.isEmpty()) {
        // System.out.println(lastEltName + " " + lastEltData);

        row.addPair(lastEltName, lastEltData);
      }
      lastEltData = "";
      if (name.equals("Placemark")) {
        placemarkactive = false;
        try {
          row.addPair(GeoTiffReader2.this.primarykey, KeyGenerator.Generate());
        } catch (Exception e) {
          e.printStackTrace();
          System.exit(0);
        }
        GeoTiffReader2.this.results.add(row);
      }
      visits.remove(name);

      if (currGeomHandler != null) {
        currGeomHandler.endElement(uri, name, qName);

        if (currGeomHandler.isGeometryComplete()) {
          Geometry g = currGeomHandler.getGeometry();

          WKTWriter wkt_writer = new WKTWriter();
          GMLWriter gml_writer = new GMLWriter();
          if (g.getClass().equals(com.vividsolutions.jts.geom.Point.class)) {
            Point geometry = (com.vividsolutions.jts.geom.Point) g;
            row.addPair("isEmpty", geometry.isEmpty());
            row.addPair("isSimple", geometry.isSimple());
            row.addPair("dimension", geometry.getCoordinates().length);
            row.addPair("coordinateDimension", geometry.getCoordinates().length);
            row.addPair("spatialDimension", geometry.getDimension()); // spatialdimension
            // <=
            // dimension
            // System.out.println(geometry.getCoordinate().x + " "
            // +geometry.getCoordinate().z);
            // System.out.println(geometry.get .getSRID());
            // CRS.
            String crs = "2311";
            if (crs == null) {
              System.err.println("No SRID specified. Aborting...");
              System.exit(-1);
            }

            row.addPair(
                "asWKT",
                "<http://www.opengis.net/def/crs/EPSG/0/" + crs + ">" + wkt_writer.write(geometry));
            row.addPair(
                "hasSerialization",
                "<http://www.opengis.net/def/crs/EPSG/0/" + crs + ">" + wkt_writer.write(geometry));
            // newrow.addPair("hasSerialization",
            // wkt_writer.write(geometry));
            gml_writer.setSrsName(crs);
            row.addPair("asGML", gml_writer.write(geometry).replaceAll("\n", " "));
            row.addPair("is3D", geometry.getDimension() == 3);
          } else {
            GeometryCollection geometry = (GeometryCollection) g;
            row.addPair("isEmpty", geometry.isEmpty());
            row.addPair("isSimple", geometry.isSimple());
            row.addPair("dimension", geometry.getCoordinates().length);
            row.addPair("coordinateDimension", geometry.getCoordinates().length);
            row.addPair("spatialDimension", geometry.getDimension()); // spatialdimension
            // <=
            // dimension
            // System.out.println(geometry.getCoordinate().x + " "
            // +geometry.getCoordinate().z);
            // System.out.println(geometry.get .getSRID());
            // CRS.
            String crs = "2323";
            if (crs == null) {
              System.err.println("No SRID specified. Aborting...");
              System.exit(-1);
            }
            // geometry.getNumPoints();
            // TODO spatialDimension??????
            // TODO coordinateDimension??????
            // Geometry geometry1=
            // (Geometry)sourceGeometryAttribute.getValue();
            // geometry1.transform(arg0, arg1)

            // sourceGeometryAttribute.ge

            row.addPair(
                "asWKT",
                "<http://www.opengis.net/def/crs/EPSG/0/" + crs + ">" + wkt_writer.write(geometry));
            row.addPair(
                "hasSerialization",
                "<http://www.opengis.net/def/crs/EPSG/0/" + crs + ">" + wkt_writer.write(geometry));
            // newrow.addPair("hasSerialization",
            // wkt_writer.write(geometry));
            gml_writer.setSrsName("http://www.opengis.net/def/crs/EPSG/0/" + crs);
            row.addPair("asGML", gml_writer.write(geometry).replaceAll("\n", " "));
            row.addPair("is3D", geometry.getDimension() == 3);
          }

          // System.out.println(g);

          // System.out.println(ww.write(g));
          geoms.add(g);

          // reset to indicate no longer parsing geometry
          currGeomHandler = null;
        }
      }
    }
Beispiel #26
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());
          }
        }
      }
    }
  }