allConnectingEdges.clear();
for (Edge tedge : connectingEdgesMap.values())
allConnectingEdges.add(tedge);
}
StringWriter sw = new StringWriter();
GeometryJSON geometryJSON = new GeometryJSON();
//
// -- create the different outputs ---
//
try {
if (output.equals(SIsochrone.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);
geometryJSON.write(gf.createMultiPoint(coords), sw);
LOG.debug("done");
} else if (output.equals(SIsochrone.RESULT_TYPE_SHED)) {
Geometry geomsArray[] = null;
// in case there was no road we create a circle
if (noRoadNearBy) {
Geometry circleShape = createCirle(dropPoint, pathToStreet);
geometryJSON.write(circleShape, sw);
} 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");
geometryJSON.write(outputHull, sw);
LOG.debug("done");
}
} else if (output.equals(SIsochrone.RESULT_TYPE_EDGES)) {
// in case there was no road we return only the suggested path to the street
if (noRoadNearBy) {
geometryJSON.write(pathToStreet, sw);
} 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");
geometryJSON.write(mls, sw);
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");
geometryJSON.write(mls, sw);
LOG.debug("done");
}
} catch (Exception e) {
e.printStackTrace();
}