-
Notifications
You must be signed in to change notification settings - Fork 13
Add polygon geometry #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
viktor76525
wants to merge
19
commits into
davidmoten:master
Choose a base branch
from
tracmap:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
f8fe672
Add maven-assembly-plugin to build JAR with all dependencies
a2695e0
Add Polygon geometry
51ed5f5
Update README.md
viktor76525 1f3e071
Polygon unit tests
5aca0e1
Polygon intersects with line when line fully inside
viktor76525 de26898
Polygon tidy
viktor76525 fbd5bd8
Polygon of arbitrary edges
viktor76525 51bb1b7
Polygon tidy2
viktor76525 d47961c
Revert "Update README.md"
viktor76525 0e04114
Revert "Add maven-assembly-plugin to build JAR with all dependencies"
viktor76525 126c05e
Polygon docstrings, comments, exceptions, renaming
viktor76525 235afef
Polygon defensive input handling
viktor76525 b87607c
Polygon tests for duplicates
viktor76525 fab816b
Polygon tests 100% coverage
viktor76525 704a177
Polygon self review rename var
viktor76525 1624581
Polygon throws if not convex
viktor76525 120b747
Polygon increase overall test coverage
viktor76525 2e65123
Polygon up and down functions
viktor76525 2061100
Polygon fix imports settings
viktor76525 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
src/main/java/com/github/davidmoten/rtree2/geometry/Polygon.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package com.github.davidmoten.rtree2.geometry; | ||
|
|
||
| public interface Polygon extends Geometry { | ||
|
|
||
| boolean intersects(Line b); | ||
|
|
||
| boolean intersects(Point point); | ||
|
|
||
| boolean intersects(Circle circle); | ||
|
|
||
| boolean intersects(Polygon polygon); | ||
|
|
||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
169 changes: 169 additions & 0 deletions
169
src/main/java/com/github/davidmoten/rtree2/geometry/internal/PolygonDouble.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,169 @@ | ||
| package com.github.davidmoten.rtree2.geometry.internal; | ||
|
|
||
| import com.github.davidmoten.rtree2.geometry.Circle; | ||
| import com.github.davidmoten.rtree2.geometry.Line; | ||
| import com.github.davidmoten.rtree2.geometry.Point; | ||
| import com.github.davidmoten.rtree2.geometry.Polygon; | ||
| import com.github.davidmoten.rtree2.geometry.Rectangle; | ||
| import com.github.davidmoten.rtree2.internal.util.ObjectsHelper; | ||
|
|
||
| import java.util.ArrayList; | ||
|
|
||
| /** | ||
| * A polygon shell. | ||
| */ | ||
| public final class PolygonDouble implements Polygon { | ||
|
|
||
| private final ArrayList<PointDouble> points; | ||
| private final Rectangle mbr; | ||
|
|
||
| private static final double PRECISION = 0.00000001; | ||
|
|
||
| private PolygonDouble(double[] coordinates) { | ||
|
viktor76525 marked this conversation as resolved.
|
||
| if (coordinates.length % 2 != 0 || coordinates.length < 6) | ||
| throw new IllegalArgumentException("expecting an even number of coordinate points of at least 6"); | ||
|
|
||
| points = new ArrayList<>(); | ||
| double minX = coordinates[0]; | ||
| double maxX = coordinates[0]; | ||
| double minY = coordinates[1]; | ||
| double maxY = coordinates[1]; | ||
| PointDouble lastPoint = PointDouble.create(coordinates[0], coordinates[1]); | ||
| points.add(lastPoint); | ||
| for (int i = 2; i < coordinates.length - 1; i += 2) { | ||
| // be nice to users and just ignore duplicate points | ||
| if (coordinates[i] == lastPoint.x() && coordinates[i + 1] == lastPoint.y()) continue; | ||
| minX = Math.min(minX, coordinates[i]); | ||
| maxX = Math.max(maxX, coordinates[i]); | ||
| minY = Math.min(minY, coordinates[i + 1]); | ||
| maxY = Math.max(maxY, coordinates[i + 1]); | ||
| lastPoint = PointDouble.create(coordinates[i], coordinates[i + 1]); | ||
| points.add(lastPoint); | ||
| } | ||
| // don't break if the polygon was closed | ||
| if (points.get(0).equals(lastPoint)) | ||
| points.remove(points.size() - 1); | ||
| // final check to make sure the polygon remains valid after removing duplicates | ||
| if (points.size() < 3) throw new IllegalArgumentException("fewer than 3 unique polygon points provided"); | ||
| // currently the implementation is only for convex polygons | ||
| if (!convexPoints()) throw new UnsupportedOperationException("only implemented for convex polygons"); | ||
| mbr = RectangleDouble.create(minX, minY, maxX, maxY); | ||
| } | ||
|
|
||
| /** | ||
| * Constructor for a polygon shell. | ||
| * @param coordinates An array of x1, y1, x2, y2, ... xn, yn that make the un-closed shell of a convex polygon. | ||
| * As it is a polygon, at least 3 pairs of points are required (6 values). | ||
| * @return convex polygon shell | ||
| * @throws IllegalArgumentException if there are not enough unique points or there is an odd amount of points | ||
| * @throws UnsupportedOperationException if the resulting polygon is not convex | ||
| */ | ||
| public static PolygonDouble create(double[] coordinates) { | ||
|
viktor76525 marked this conversation as resolved.
|
||
| return new PolygonDouble(coordinates); | ||
| } | ||
|
|
||
| @Override | ||
| public Rectangle mbr() { | ||
| return mbr; | ||
| } | ||
|
|
||
| @Override | ||
| public double distance(Rectangle r) { | ||
| throw new UnsupportedOperationException("not implemented"); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean intersects(Rectangle r) { | ||
| throw new UnsupportedOperationException("not implemented"); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean intersects(Circle c) { | ||
| throw new UnsupportedOperationException("not implemented"); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean intersects(Polygon p) { | ||
| throw new UnsupportedOperationException("not implemented"); | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return points.hashCode(); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object obj) { | ||
| PolygonDouble other = ObjectsHelper.asClass(obj, PolygonDouble.class); | ||
| if (other!=null) { | ||
| return points.equals(other.points); | ||
| } else | ||
| return false; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean intersects(Point point) { | ||
| int n = points.size(); | ||
|
davidmoten marked this conversation as resolved.
|
||
|
|
||
| int firstDirection = pointsDirection(points.get(n - 1), point, points.get(0)); | ||
| if (firstDirection == 0) | ||
| return true; | ||
|
|
||
| for (int i = 0; i < n - 1; i++) { | ||
| int direction = pointsDirection(points.get(i), point, points.get(i + 1)); | ||
| if (direction == 0) return true; | ||
| if (direction != firstDirection) return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| private boolean convexPoints() { | ||
| int n = points.size(); | ||
| int overallDirection = 0; | ||
|
|
||
| for (int i = 0; i < n - 1; i++) { | ||
| int direction = pointsDirection(points.get(i), points.get((i + 2) % n), points.get(i + 1)); | ||
| if (direction != 0) { | ||
| if (overallDirection == 0) overallDirection = direction; | ||
| else if (direction != overallDirection) return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean intersects(Line line) { | ||
| // handle the case when the line is fully inside the polygon | ||
| if (intersects(PointDouble.create(line.x1(), line.y1()))) | ||
|
viktor76525 marked this conversation as resolved.
|
||
| return true; | ||
| // check if the line intersects any of the edges of this polygon | ||
| int n = points.size(); | ||
| for (int i = 0; i < n; i++) { | ||
| PointDouble cur = points.get(i); | ||
| PointDouble next = points.get((i + 1) % n); | ||
| LineDouble edge = LineDouble.create(cur.x(), cur.y(), next.x(), next.y()); | ||
| if (line.intersects(edge)) | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isDoublePrecision() { | ||
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * Return the orientation of point b relative to the path a -> c. | ||
| * @param a origin point | ||
| * @param b point to determine if it is to the left, right or along the path | ||
| * @param c point we are facing from a | ||
| * @return 0 if b is on the line a->c, -1 if b is to the left of a facing c or 1 if to the right. | ||
| */ | ||
| private static int pointsDirection(Point a, Point b, Point c) { | ||
| double crossProduct = (b.x() - a.x()) * (c.y() - a.y()) - (b.y() - a.y()) * (c.x() - a.x()); | ||
| if (Math.abs(crossProduct) < PRECISION) return 0; | ||
| return crossProduct > 0.0 ? 1 : -1; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing check on geometry being instanceof Polygon. Also required on other geometryIntersects* methods
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this what you mean (latest commit)?