improve the readability of the algorithm for checking that one region is inside another

This commit is contained in:
nazar-kutz 2021-03-06 01:55:08 +02:00
parent 6affa0c432
commit 37d795cf7b
2 changed files with 58 additions and 26 deletions

View file

@ -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() {

View file

@ -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 {