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.LatLon;
|
||||||
import net.osmand.data.QuadRect;
|
import net.osmand.data.QuadRect;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
|
import net.osmand.util.Algorithms.Point2D;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
@ -187,37 +188,27 @@ public class WorldRegion implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsRegion(WorldRegion region) {
|
public boolean containsRegion(WorldRegion region) {
|
||||||
boolean isBoundingAvailable = this.boundingBox != null && region.boundingBox != null;
|
if (containsBoundingBox(region.boundingBox)) {
|
||||||
boolean isPolygonsAvailable = this.polygon != null && region.polygon != null;
|
// check polygon only if bounding box match
|
||||||
|
return containsPolygon(region.polygon);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPointInsideThePolygon(LatLon test) {
|
private boolean containsBoundingBox(QuadRect rectangle) {
|
||||||
boolean result = false;
|
if (boundingBox != null && rectangle != null) {
|
||||||
for (int i = 0, j = polygon.size() - 1; i < polygon.size(); j = i++) {
|
return boundingBox.contains(rectangle);
|
||||||
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;
|
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() {
|
public boolean isContinent() {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.osmand.util;
|
||||||
|
|
||||||
import net.osmand.IProgress;
|
import net.osmand.IProgress;
|
||||||
import net.osmand.PlatformUtil;
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.data.LatLon;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
@ -117,6 +118,46 @@ public class Algorithms {
|
||||||
}
|
}
|
||||||
return def;
|
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) {
|
public static int parseIntSilently(String input, int def) {
|
||||||
if (input != null && input.length() > 0) {
|
if (input != null && input.length() > 0) {
|
||||||
|
|
Loading…
Reference in a new issue