improve the readability of the algorithm for checking that one region is inside another
This commit is contained in:
parent
6affa0c432
commit
37d795cf7b
2 changed files with 58 additions and 26 deletions
|
@ -3,6 +3,7 @@ package net.osmand.map;
|
|||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.util.Algorithms.Point2D;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.LinkedList;
|
||||
|
@ -187,37 +188,27 @@ public class WorldRegion implements Serializable {
|
|||
}
|
||||
|
||||
public boolean containsRegion(WorldRegion region) {
|
||||
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<LatLon> regionPolygon = region.polygon;
|
||||
for (int i = 0; i < regionPolygon.size(); i++) {
|
||||
allPointsInsideThePolygon = isPointInsideThePolygon(regionPolygon.get(i));
|
||||
if (!allPointsInsideThePolygon) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if (containsBoundingBox(region.boundingBox)) {
|
||||
// check polygon only if bounding box match
|
||||
return containsPolygon(region.polygon);
|
||||
}
|
||||
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;
|
||||
}
|
||||
private boolean containsBoundingBox(QuadRect rectangle) {
|
||||
if (boundingBox != null && rectangle != null) {
|
||||
return boundingBox.contains(rectangle);
|
||||
}
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean containsPolygon(List<LatLon> another) {
|
||||
if (polygon != null && another != null) {
|
||||
Point2D[] inner = Algorithms.createPoint2DArrayFromLatLon(polygon);
|
||||
Point2D[] outer = Algorithms.createPoint2DArrayFromLatLon(another);
|
||||
return Algorithms.isFirstPolygonInsideTheSecond(outer, inner);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isContinent() {
|
||||
|
|
|
@ -2,6 +2,7 @@ package net.osmand.util;
|
|||
|
||||
import net.osmand.IProgress;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.data.LatLon;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
@ -118,6 +119,46 @@ public class Algorithms {
|
|||
return def;
|
||||
}
|
||||
|
||||
public static class Point2D {
|
||||
public double x;
|
||||
public double y;
|
||||
}
|
||||
|
||||
public static Point2D[] createPoint2DArrayFromLatLon(List<LatLon> latLons) {
|
||||
Point2D[] array = new Point2D[latLons.size()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
Point2D point = new Point2D();
|
||||
point.x = latLons.get(i).getLatitude();
|
||||
point.y = latLons.get(i).getLongitude();
|
||||
array[i] = point;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public static boolean isFirstPolygonInsideTheSecond(Point2D[] first,
|
||||
Point2D[] second) {
|
||||
for (Point2D point : first) {
|
||||
if (!isPointInsideTheBoundary(point, second)) {
|
||||
// if at least one point is not inside the boundary, return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isPointInsideTheBoundary(Point2D point,
|
||||
Point2D[] polygon) {
|
||||
boolean result = false;
|
||||
for (int i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||
if ((polygon[i].y > point.y) != (polygon[j].y > point.y)
|
||||
&& (point.x < (polygon[j].x - polygon[i].x) * (point.y - polygon[i].y) /
|
||||
(polygon[j].y-polygon[i].y) + polygon[i].x)) {
|
||||
result = !result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int parseIntSilently(String input, int def) {
|
||||
if (input != null && input.length() > 0) {
|
||||
try {
|
||||
|
|
Loading…
Reference in a new issue