use of com.graphhopper.util.shapes.BBox in project graphhopper by graphhopper.
the class SpatialRuleLookupArrayTest method testSmallBoundsBigPolygon.
@Test
public void testSmallBoundsBigPolygon() {
List<SpatialRule> spatialRules = new ArrayList<>();
spatialRules.add(getSpatialRule(new Polygon(new double[] { -100, -100, 100, 100 }, new double[] { -100, 100, 100, -100 }), "big"));
SpatialRuleLookup spatialRuleLookup = new SpatialRuleLookupArray(spatialRules, 1, true, new BBox(1, 2, 1, 2));
assertEquals("big", spatialRuleLookup.lookupRule(1.5, 1.5).getId());
}
use of com.graphhopper.util.shapes.BBox in project graphhopper by graphhopper.
the class SpatialRuleLookupArrayTest method testExactCountry.
@Test
public void testExactCountry() {
List<SpatialRule> spatialRules = new ArrayList<>();
// Taken from here: https://github.com/johan/world.geo.json/blob/master/countries/DEU.geo.json
String germanPolygonJson = "[9.921906,54.983104],[9.93958,54.596642],[10.950112,54.363607],[10.939467,54.008693],[11.956252,54.196486],[12.51844,54.470371],[13.647467,54.075511],[14.119686,53.757029],[14.353315,53.248171],[14.074521,52.981263],[14.4376,52.62485],[14.685026,52.089947],[14.607098,51.745188],[15.016996,51.106674],[14.570718,51.002339],[14.307013,51.117268],[14.056228,50.926918],[13.338132,50.733234],[12.966837,50.484076],[12.240111,50.266338],[12.415191,49.969121],[12.521024,49.547415],[13.031329,49.307068],[13.595946,48.877172],[13.243357,48.416115],[12.884103,48.289146],[13.025851,47.637584],[12.932627,47.467646],[12.62076,47.672388],[12.141357,47.703083],[11.426414,47.523766],[10.544504,47.566399],[10.402084,47.302488],[9.896068,47.580197],[9.594226,47.525058],[8.522612,47.830828],[8.317301,47.61358],[7.466759,47.620582],[7.593676,48.333019],[8.099279,49.017784],[6.65823,49.201958],[6.18632,49.463803],[6.242751,49.902226],[6.043073,50.128052],[6.156658,50.803721],[5.988658,51.851616],[6.589397,51.852029],[6.84287,52.22844],[7.092053,53.144043],[6.90514,53.482162],[7.100425,53.693932],[7.936239,53.748296],[8.121706,53.527792],[8.800734,54.020786],[8.572118,54.395646],[8.526229,54.962744],[9.282049,54.830865],[9.921906,54.983104]";
Polygon germanPolygon = parsePolygonString(germanPolygonJson);
spatialRules.add(new DefaultSpatialRule() {
@Override
public String getId() {
return "DEU";
}
}.addBorder(germanPolygon));
SpatialRuleLookup spatialRuleLookup = new SpatialRuleLookupArray(spatialRules, .1, true, new BBox(-180, 180, -90, 90));
// Far from the border of Germany, in Germany
assertEquals("DEU", spatialRuleLookup.lookupRule(48.777106, 9.180769).getId());
assertEquals("DEU", spatialRuleLookup.lookupRule(51.806281, 7.269380).getId());
assertEquals("DEU", spatialRuleLookup.lookupRule(50.636710, 12.514561).getId());
// Far from the border of Germany, not in Germany
assertEquals("SpatialRule.EMPTY", spatialRuleLookup.lookupRule(48.029533, 7.250122).getId());
assertEquals("SpatialRule.EMPTY", spatialRuleLookup.lookupRule(51.694467, 15.209218).getId());
assertEquals("SpatialRule.EMPTY", spatialRuleLookup.lookupRule(47.283669, 11.167381).getId());
// Close to the border of Germany, in Germany - Whereas the borders are defined by the GeoJson above and do not strictly follow the acutal border
assertEquals("DEU", spatialRuleLookup.lookupRule(50.017714, 12.356129).getId());
assertEquals("DEU", spatialRuleLookup.lookupRule(49.949930, 6.225853).getId());
assertEquals("DEU", spatialRuleLookup.lookupRule(47.580866, 9.707582).getId());
assertEquals("DEU", spatialRuleLookup.lookupRule(47.565101, 9.724267).getId());
assertEquals("DEU", spatialRuleLookup.lookupRule(47.557166, 9.738343).getId());
// Close to the border of Germany, not in Germany
assertEquals("SpatialRule.EMPTY", spatialRuleLookup.lookupRule(50.025342, 12.386262).getId());
assertEquals("SpatialRule.EMPTY", spatialRuleLookup.lookupRule(49.932900, 6.174023).getId());
assertEquals("SpatialRule.EMPTY", spatialRuleLookup.lookupRule(47.547463, 9.741948).getId());
}
use of com.graphhopper.util.shapes.BBox in project graphhopper by graphhopper.
the class SpatialRuleLookupBuilder method buildIndex.
/**
* Builds a SpatialRuleLookup by passing the provided JSON features into the provided
* SpatialRuleFactory and collecting all the SpatialRule instances that it returns,
* ignoring when it returns SpatialRule.EMPTY.
* <p>
* See {@link SpatialRuleLookup} and {@link SpatialRule}.
*
* @param jsonFeatureCollection a feature collection
* @param jsonIdField the name of a property in that feature collection which serves as an id
* @param spatialRuleFactory a factory which is called with all the (id, geometry) pairs.
* It should provide a SpatialRule for each id it knows about,
* and SpatialRule.EMPTY otherwise.
* @param maxBBox limit the maximum BBox of the SpatialRuleLookup to the given BBox
* @return the fully constructed SpatialRuleLookup.
*/
public static SpatialRuleLookup buildIndex(JsonFeatureCollection jsonFeatureCollection, String jsonIdField, SpatialRuleFactory spatialRuleFactory, double resolution, BBox maxBBox) {
BBox polygonBounds = BBox.createInverse(false);
List<SpatialRule> spatialRules = new ArrayList<>();
for (int jsonFeatureIdx = 0; jsonFeatureIdx < jsonFeatureCollection.getFeatures().size(); jsonFeatureIdx++) {
JsonFeature jsonFeature = jsonFeatureCollection.getFeatures().get(jsonFeatureIdx);
String id = jsonIdField.isEmpty() || toLowerCase(jsonIdField).equals("id") ? jsonFeature.getId() : (String) jsonFeature.getProperty(jsonIdField);
if (id == null || id.isEmpty())
throw new IllegalArgumentException("ID cannot be empty but was for JsonFeature " + jsonFeatureIdx);
List<Polygon> borders = new ArrayList<>();
for (int i = 0; i < jsonFeature.getGeometry().getNumGeometries(); i++) {
Geometry poly = jsonFeature.getGeometry().getGeometryN(i);
if (poly instanceof com.vividsolutions.jts.geom.Polygon)
borders.add(Polygon.create((com.vividsolutions.jts.geom.Polygon) poly));
else
throw new IllegalArgumentException("Geometry for " + id + " (" + i + ") not supported " + poly.getClass().getSimpleName());
}
SpatialRule spatialRule = spatialRuleFactory.createSpatialRule(id, borders);
if (spatialRule != SpatialRule.EMPTY) {
spatialRules.add(spatialRule);
for (Polygon polygon : spatialRule.getBorders()) {
polygonBounds.update(polygon.getMinLat(), polygon.getMinLon());
polygonBounds.update(polygon.getMaxLat(), polygon.getMaxLon());
}
}
}
if (!polygonBounds.isValid()) {
return SpatialRuleLookup.EMPTY;
}
BBox calculatedBounds = polygonBounds.calculateIntersection(maxBBox);
if (calculatedBounds == null)
return SpatialRuleLookup.EMPTY;
SpatialRuleLookup spatialRuleLookup = new SpatialRuleLookupArray(spatialRules, resolution, true, calculatedBounds);
logger.info("Created the SpatialRuleLookup with the following rules: " + Arrays.toString(spatialRules.toArray()));
return spatialRuleLookup;
}
use of com.graphhopper.util.shapes.BBox in project graphhopper by graphhopper.
the class GraphEdgeIdFinder method parseBlockArea.
/**
* This method reads the blockAreaString and creates a Collection of Shapes or a set of found edges if area is small enough.
* @param useEdgeIdsUntilAreaSize until the specified area (specified in m²) use the findEdgesInShape method
*/
public BlockArea parseBlockArea(String blockAreaString, EdgeFilter filter, double useEdgeIdsUntilAreaSize) {
final String objectSeparator = ";";
final String innerObjSep = ",";
BlockArea blockArea = new BlockArea(graph);
// Add blocked circular areas or points
if (!blockAreaString.isEmpty()) {
String[] blockedCircularAreasArr = blockAreaString.split(objectSeparator);
for (int i = 0; i < blockedCircularAreasArr.length; i++) {
String objectAsString = blockedCircularAreasArr[i];
String[] splittedObject = objectAsString.split(innerObjSep);
if (splittedObject.length == 4) {
final BBox bbox = BBox.parseTwoPoints(objectAsString);
if (bbox.calculateArea() > useEdgeIdsUntilAreaSize)
blockArea.add(bbox);
else
findEdgesInShape(blockArea.blockedEdges, bbox, filter);
} else if (splittedObject.length == 3) {
double lat = Double.parseDouble(splittedObject[0]);
double lon = Double.parseDouble(splittedObject[1]);
int radius = Integer.parseInt(splittedObject[2]);
Circle circle = new Circle(lat, lon, radius);
if (circle.calculateArea() > useEdgeIdsUntilAreaSize) {
blockArea.add(circle);
} else {
findEdgesInShape(blockArea.blockedEdges, circle, filter);
}
} else if (splittedObject.length == 2) {
double lat = Double.parseDouble(splittedObject[0]);
double lon = Double.parseDouble(splittedObject[1]);
findClosestEdge(blockArea.blockedEdges, lat, lon, filter);
} else {
throw new IllegalArgumentException(objectAsString + " at index " + i + " need to be defined as lat,lon " + "or as a circle lat,lon,radius or rectangular lat1,lon1,lat2,lon2");
}
}
}
return blockArea;
}
use of com.graphhopper.util.shapes.BBox in project graphhopper by graphhopper.
the class LocationIndexTree method prepareAlgo.
void prepareAlgo() {
// 0.1 meter should count as 'equal'
equalNormedDelta = distCalc.calcNormalizedDist(0.1);
// now calculate the necessary maxDepth d for our current bounds
// if we assume a minimum resolution like 0.5km for a leaf-tile
// n^(depth/2) = toMeter(dLon) / minResolution
BBox bounds = graph.getBounds();
if (graph.getNodes() == 0)
throw new IllegalStateException("Cannot create location index of empty graph!");
if (!bounds.isValid())
throw new IllegalStateException("Cannot create location index when graph has invalid bounds: " + bounds);
double lat = Math.min(Math.abs(bounds.maxLat), Math.abs(bounds.minLat));
double maxDistInMeter = Math.max((bounds.maxLat - bounds.minLat) / 360 * DistanceCalcEarth.C, (bounds.maxLon - bounds.minLon) / 360 * preciseDistCalc.calcCircumference(lat));
double tmp = maxDistInMeter / minResolutionInMeter;
tmp = tmp * tmp;
IntArrayList tmpEntries = new IntArrayList();
// the last one is always 4 to reduce costs if only a single entry
tmp /= 4;
while (tmp > 1) {
int tmpNo;
if (tmp >= 64) {
tmpNo = 64;
} else if (tmp >= 16) {
tmpNo = 16;
} else if (tmp >= 4) {
tmpNo = 4;
} else {
break;
}
tmpEntries.add(tmpNo);
tmp /= tmpNo;
}
tmpEntries.add(4);
initEntries(tmpEntries.toArray());
int shiftSum = 0;
long parts = 1;
for (int i = 0; i < shifts.length; i++) {
shiftSum += shifts[i];
parts *= entries[i];
}
if (shiftSum > 64)
throw new IllegalStateException("sum of all shifts does not fit into a long variable");
keyAlgo = new SpatialKeyAlgo(shiftSum).bounds(bounds);
parts = Math.round(Math.sqrt(parts));
deltaLat = (bounds.maxLat - bounds.minLat) / parts;
deltaLon = (bounds.maxLon - bounds.minLon) / parts;
}
Aggregations