use of org.openstreetmap.atlas.geography.MultiPolygon in project atlas-generator by osmlab.
the class AtlasMissingShardVerifier method verifier.
public int verifier(final CountryBoundaryMap boundaries, final Set<CountryShard> missingCountryShardsUntrimmed, final File output, final String server, final HttpHost proxy, final ConfiguredTaggableFilter filter, final Integer numRetryQueries) {
int returnCode = 0;
final Set<CountryShard> missingCountryShards = removeShardsWithZeroIntersection(missingCountryShardsUntrimmed, boundaries);
final String masterQuery = createMasterQuery(boundaries, missingCountryShards);
final OverpassClient client = new OverpassClient(server, proxy);
try (SafeBufferedWriter writer = output.writer()) {
final List<OverpassOsmNode> nodes = client.nodesFromQuery(masterQuery);
final List<OverpassOsmWay> ways = client.waysFromQuery(masterQuery);
if (client.hasTooMuchResponseData()) {
logger.warn("The overpass query returned too much data. This means that there's potentially" + "large amounts of data missing! Rerunning with smaller queries.");
client.resetTooMuchDataError();
final StringList splitQueries = createQueryList(boundaries, missingCountryShards, numRetryQueries);
nodes.clear();
ways.clear();
for (final String query : splitQueries) {
nodes.addAll(client.nodesFromQuery(query));
ways.addAll(client.waysFromQuery(query));
}
}
if (client.hasTooMuchResponseData()) {
throw new CoreException("The overpass query had to much data, even when split " + numRetryQueries + " times. There is lots of data missing!");
}
if (client.hasUnknownError()) {
throw new CoreException("The overpass query encountered an error. Validation has failed.");
}
final STRtree nodeTree = initializeNodeTree(nodes);
final STRtree wayTree = initializeWayTree(nodes, ways);
for (final CountryShard countryShard : missingCountryShards) {
final Clip clip = intersectionClip(countryShard, boundaries);
final MultiPolygon clipMulti = clip.getClipMultiPolygon();
final Rectangle clipBounds = clipMulti.bounds();
@SuppressWarnings("unchecked") final List<OverpassOsmNode> nodeList = nodeTree.query(clipBounds.asEnvelope());
// Prune extra nodes returned by STRtree that might not actually be contained within
// clipBounds
nodeList.removeIf(node -> !clipBounds.fullyGeometricallyEncloses(Location.forString(node.getLatitude() + "," + node.getLongitude())));
@SuppressWarnings("unchecked") final List<OverpassOsmWay> wayList = wayTree.query(clipBounds.asEnvelope());
// Filter out ways that aren't ingested into atlas
wayList.stream().filter(way -> !filter.test(Taggable.with(way.getTags()))).forEach(way -> {
nodeList.removeIf(node -> way.getNodeIdentifiers().contains(node.getIdentifier()));
});
// bounds then the shard should have been built, so break and list the shard
for (final OverpassOsmNode node : nodeList) {
final Location nodeLocation = Location.forString(node.getLatitude() + "," + node.getLongitude());
if (clipMulti.fullyGeometricallyEncloses(nodeLocation)) {
returnCode = -1;
writer.writeLine(countryShard.toString());
writer.writeLine("Boundary/Shard intersection zone: " + clipMulti.toString());
writer.writeLine("Id of node that should have been imported: " + node.getIdentifier());
writer.writeLine("Node Location: " + nodeLocation.toString() + "\n");
logger.info("{} is missing!", countryShard);
break;
}
}
}
} catch (final Exception e) {
logger.error("Error!", e);
return -1;
}
if (returnCode == 0) {
logger.info("No shards are missing!");
}
return returnCode;
}
use of org.openstreetmap.atlas.geography.MultiPolygon in project atlas by osmlab.
the class AtlasDebugTool method onRun.
@Override
protected int onRun(final CommandMap command) {
final File pbf = (File) command.get(PBF);
final File atlasFile = (File) command.get(ATLAS);
final File geojson = (File) command.get(GEOJSON);
final File text = (File) command.get(TEXT);
final java.io.File boundaryFile = (java.io.File) command.get(BOUNDARY);
final String country = (String) command.get(COUNTRY);
final Rectangle bound = (Rectangle) command.get(BOUND);
final MultiPolygon inputMultipolygon = (MultiPolygon) command.get(MULTIPOLYGON);
@SuppressWarnings("unchecked") final List<Location> startEndRoute = (List<Location>) command.get(ROUTE);
Atlas atlas;
if (pbf != null && pbf.exists()) {
final AtlasLoadingOption option;
MultiPolygon multiPolygon = MultiPolygon.forPolygon(Rectangle.MAXIMUM);
if (boundaryFile != null) {
final CountryBoundaryMap boundaryMap = CountryBoundaryMap.fromShapeFile(boundaryFile);
option = AtlasLoadingOption.createOptionWithAllEnabled(boundaryMap);
if (country != null) {
if (new CountryListTwoWayStringConverter().convert(country).size() == 1) {
multiPolygon = boundaryMap.countryBoundary(country).get(0).getBoundary();
}
option.setCountryCode(country);
}
} else {
option = AtlasLoadingOption.createOptionWithNoSlicing();
}
if (bound != null) {
multiPolygon = MultiPolygon.forPolygon(bound);
}
if (inputMultipolygon != null) {
multiPolygon = inputMultipolygon;
}
atlas = new RawAtlasGenerator(pbf, option, multiPolygon).build();
if (option.isCountrySlicing()) {
atlas = new RawAtlasSlicer(option, atlas).slice();
}
atlas = new WaySectionProcessor(atlas, option).run();
atlas.save(atlasFile);
} else if (atlasFile != null && atlasFile.exists()) {
atlas = new AtlasResourceLoader().load(atlasFile);
} else {
logger.error("Must have at least one source, -pbf or -atlas");
atlas = null;
System.exit(1);
}
logger.info("Loaded {}", atlas.summary());
if (geojson != null) {
atlas.saveAsGeoJson(geojson);
}
if (text != null) {
atlas.saveAsText(text);
}
if (startEndRoute != null) {
logger.info("Route between {} and {} = {}", startEndRoute.get(0), startEndRoute.get(1), AStarRouter.dijkstra(atlas, Distance.TEN_MILES).route(startEndRoute.get(0), startEndRoute.get(1)));
}
return 0;
}
use of org.openstreetmap.atlas.geography.MultiPolygon in project atlas by osmlab.
the class RelationOrAreaToMultiPolygonConverter method convert.
@Override
public MultiPolygon convert(final AtlasEntity entity) {
if (entity instanceof Relation) {
final Relation relation = (Relation) entity;
if (relation.isMultiPolygon()) {
// Loop through the relation members, extract the inners and outers, and create the
// outline.
final MultiMap<Polygon, Polygon> outerToInners = new MultiMap<>();
for (final Polygon outer : OUTER_CONVERTER.convert(relation)) {
outerToInners.put(outer, new ArrayList<>());
}
if (outerToInners.isEmpty()) {
throw new CoreException("Unable to find outer polygon.");
}
for (final Polygon inner : INNER_CONVERTER.convert(relation)) {
boolean added = false;
for (final Polygon outer : outerToInners.keySet()) {
if (outer.overlaps(inner) && !inner.fullyGeometricallyEncloses(outer)) {
outerToInners.add(outer, inner);
added = true;
break;
}
}
if (!added) {
throw new CoreException("Malformed MultiPolygon: inner has no outer host: {}", inner);
}
}
return new MultiPolygon(outerToInners);
} else {
throw new CoreException("This is not a multipolygon relation");
}
} else if (entity instanceof Area) {
return MultiPolygon.forPolygon(((Area) entity).asPolygon());
} else {
throw new CoreException("The outline is not an area nor a relation: {}", entity);
}
}
use of org.openstreetmap.atlas.geography.MultiPolygon in project atlas by osmlab.
the class ComplexBoundary method removeOuter.
public void removeOuter(final Polygon outerToRemove) {
final MultiMap<Polygon, Polygon> outersToInners = new MultiMap<>();
this.outline.outers().forEach(outer -> {
final List<Polygon> innersForThisOuter = this.outline.innersOf(outer);
outersToInners.put(outer, innersForThisOuter);
});
outersToInners.remove(outerToRemove);
setOutline(new MultiPolygon(outersToInners));
}
use of org.openstreetmap.atlas.geography.MultiPolygon in project atlas by osmlab.
the class RawAtlasSlicer method slicePolygonGeometry.
/**
* Take a polygon and find its slices, while also checking for validity and geometric
* consistency (i.e. only Polygonal results)
*
* @param identifier
* the OSM identifier for the Line being sliced
* @param polygon
* The Polygon being sliced
* @param intersectingBoundaryPolygons
* All intersecting country boundary polygons
* @return A SortedMap of country codes to the portions of the Polygon inside those country
* boundary polygons
*/
private SortedMap<String, Set<org.locationtech.jts.geom.Polygon>> slicePolygonGeometry(final long identifier, final org.locationtech.jts.geom.Polygon polygon, final Set<org.locationtech.jts.geom.Polygon> intersectingBoundaryPolygon) {
final Map<String, Set<Geometry>> currentResults = sliceGeometry(polygon, intersectingBoundaryPolygon);
final SortedMap<String, Set<org.locationtech.jts.geom.Polygon>> results = new TreeMap<>();
for (final Map.Entry<String, Set<Geometry>> entry : currentResults.entrySet()) {
final String countryCode = entry.getKey();
final Set<org.locationtech.jts.geom.Polygon> slicedPolygons = new HashSet<>();
entry.getValue().forEach(geometry -> {
if (geometry instanceof org.locationtech.jts.geom.Polygon) {
// the log as an error so it should be easy to find
if (((org.locationtech.jts.geom.Polygon) geometry).getNumInteriorRing() > 0) {
throw new CoreException("Line {} for Atlas {} had multipolygon geometry {}!", identifier, this.shardOrAtlasName, geometry.toText());
} else {
slicedPolygons.add((org.locationtech.jts.geom.Polygon) geometry);
}
}
});
results.put(countryCode, slicedPolygons);
}
return results;
}
Aggregations