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)); }
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"); } }
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()); }
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); } }
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); } } }
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); }
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; }
/** 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; }
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; }
/** * 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); }
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); }
/** * 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; } } }
@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()); } } } } }