diff --git a/OsmAnd-java/src/main/java/net/osmand/map/OsmandRegions.java b/OsmAnd-java/src/main/java/net/osmand/map/OsmandRegions.java index 882231d8a6..388572bd58 100644 --- a/OsmAnd-java/src/main/java/net/osmand/map/OsmandRegions.java +++ b/OsmAnd-java/src/main/java/net/osmand/map/OsmandRegions.java @@ -436,7 +436,7 @@ public class OsmandRegions { cx /= object.getPointsLength(); cy /= object.getPointsLength(); rd.regionCenter = new LatLon(MapUtils.get31LatitudeY((int) cy), MapUtils.get31LongitudeX((int) cx)); - rd.boundingBox = findBoundingBox(object); + findBoundaries(rd, object); } rd.regionParentFullName = mapIndexFields.get(mapIndexFields.parentFullName, object); @@ -462,13 +462,15 @@ public class OsmandRegions { return rd; } - private QuadRect findBoundingBox(BinaryMapDataObject object) { + private void findBoundaries(WorldRegion rd, BinaryMapDataObject object) { if (object.getPointsLength() == 0) { - return new QuadRect(0, 0, 0, 0); + return; } + List polygon = new ArrayList<>(); double currentX = object.getPoint31XTile(0); double currentY = object.getPoint31YTile(0); + polygon.add(new LatLon(currentX, currentY)); double minX = currentX; double maxX = currentX; double minY = currentY; @@ -476,8 +478,10 @@ public class OsmandRegions { if (object.getPointsLength() > 1) { for (int i = 1; i < object.getPointsLength(); i++) { - currentX = object.getPoint31XTile(i); - currentY = object.getPoint31YTile(i); + int tileX = object.getPoint31XTile(i); + int tileY = object.getPoint31YTile(i); + currentX = tileX; + currentY = tileY; if (currentX > maxX) { maxX = currentX; } else if (currentX < minX) { @@ -488,6 +492,7 @@ public class OsmandRegions { } else if (currentY < minY) { minY = currentY; } + polygon.add(new LatLon(currentX, currentY)); } } @@ -496,7 +501,8 @@ public class OsmandRegions { double revertedMinY = MapUtils.get31LatitudeY((int) maxY); double revertedMaxY = MapUtils.get31LatitudeY((int) minY); - return new QuadRect(minX, revertedMinY, maxX, revertedMaxY); + rd.boundingBox = new QuadRect(minX, revertedMinY, maxX, revertedMaxY); + rd.polygon = polygon; } private String getSearchIndex(BinaryMapDataObject object) { diff --git a/OsmAnd-java/src/main/java/net/osmand/map/WorldRegion.java b/OsmAnd-java/src/main/java/net/osmand/map/WorldRegion.java index b6fdb4f7d4..45bd14f600 100644 --- a/OsmAnd-java/src/main/java/net/osmand/map/WorldRegion.java +++ b/OsmAnd-java/src/main/java/net/osmand/map/WorldRegion.java @@ -42,6 +42,7 @@ public class WorldRegion implements Serializable { protected boolean regionMapDownload; protected LatLon regionCenter; protected QuadRect boundingBox; + protected List polygon; public static class RegionParams { protected String regionLeftHandDriving; @@ -186,12 +187,39 @@ public class WorldRegion implements Serializable { } public boolean containsRegion(WorldRegion region) { - if (this.boundingBox != null && region.boundingBox != null) { - return this.boundingBox.contains(region.boundingBox); + boolean isBoundingAvailable = this.boundingBox != null && region.boundingBox != null; + boolean isPolygonsAvailable = this.polygon != null && region.polygon != null; + + boolean containsBox = false; + if (isBoundingAvailable) { + containsBox = this.boundingBox.contains(region.boundingBox); + } + if (containsBox && isPolygonsAvailable) { + boolean allPointsInsideThePolygon = true; + List regionPolygon = region.polygon; + for (int i = 0; i < regionPolygon.size(); i++) { + allPointsInsideThePolygon = isPointInsideThePolygon(regionPolygon.get(i)); + if (!allPointsInsideThePolygon) { + return false; + } + } + return true; } return false; } + private boolean isPointInsideThePolygon(LatLon test) { + boolean result = false; + for (int i = 0, j = polygon.size() - 1; i < polygon.size(); j = i++) { + if ((polygon.get(i).getLongitude() > test.getLongitude()) != (polygon.get(j).getLongitude() > test.getLongitude()) && + (test.getLatitude() < (polygon.get(j).getLatitude() - polygon.get(i).getLatitude()) * (test.getLongitude() - polygon.get(i).getLongitude()) + / (polygon.get(j).getLongitude()-polygon.get(i).getLongitude()) + polygon.get(i).getLatitude())) { + result = !result; + } + } + return result; + } + public boolean isContinent() { if (superregion != null) { String superRegionId = superregion.getRegionId();