I have a series of Polygons, created using the JTS Topology Suite. Each polygon is a set of points, longitudes and latitudes that form a shape, as shown below.
((lat1,lon1),(lat2,lon2),....(lat1,lon1))
I want to find each of these polygons neighbours, the other shapes that are physically next to them. I have thought of looking for matching points, but obviously that won't work in all cases. I was wondering if there is any package that will check to see if polygons share the same edge that I could use in this situation? Or if not then another way to do this in Java.
Thanks.
Since you are looking for shared edges, you can create a hash table uses the edge as the key and a list of polygons that have that edge as its item.
Then you go through each polygon and fill up the table. Which is linear in the number of edges.
Then you go through the table and look for edges that are tied to multiple polygons, which is what you are looking for. This is linear in the number of unique edges.
I'm not sure how Java implement hash tables, so it might be a bit of work to get this setup. Make sure the edges are sorted to prevent the edge (A,B) being different from the edge (B,A), which will mess up the algorithm.
As for libraries, seems like what you're trying to do might be a bit specialized, and thus not sure you'll find library implementations, hence why I outlined an algorithm.
There was in fact a very simple way to do this. I created an arraylist containing an array of objects. The object referenced the name/id of the polygon, the actual polygon coordinates and then a string that would contain ids of any neighbours.
In JTS Topology suite there is a method that you can call on polygons called touches that returns a boolean; so I had a double for loop, going through my arraylist twice and calling the method touches on polygon(i) so:
arraylist<object[]>..
//where in the array the objects are
object[0] = id
object[1] = polygon
object[2] = neighbours
for (int i=0;i<arraylist;i++)
for (int j=0;j<arraylist;j++)
if (i)[1].touches(j)[1]
update i[2]..
It's probably not the best method but it seems to work.
If you are using JTS geometries anyway you can use the spatial relations that can be used with any Geometry object.
Use touches if you can ensure that at least one point between neighbours is in common and their interiors do not intersect.
Use intersects if you cannot ensure that the interiors do not intersect. Depending on the datasource this is probably the better choice.
Given the polygons a method to get the neighbours can look like this:
public ArrayList<Polygon> getNeighbourList(Polygon center, ArrayList<Polygon> possibleNeighbourList){
// result list
ArrayList realNeighbourList = new ArrayList();
for(Polygon p : possibleNeighbourList){
// check if current polygon is a neighbour of the center polygon by using the spatial relation touches or intersects
if(center.intersects(p)){
realNeighbourList.add(p);
}
}
return realNeighbourList;
}
Related
I have a two polygon shape draw using HTML5 canvas(GWT). I have all the points for two polygon shape. Means I have the list of points for draw this type of polygon.
Below image showing two polygon intersect or overlapping each other. Now I am searching for a solution how to find two polygon "intersect or not" using java? I am using pure java programming without using any third library.
I have another issue. For explaining this issue I am attaching another image below.
This is the another case when one Polygon inside of another Polygon. In this scenario how to calculate minimum distance between two polygon in negative?
Using Postgis Api Using You get Information That Two Polygon intersect or not . Find Following Link As Reference
http://www.postgis.net/docs/ST_Intersection.html
You can use the sweepline paradigm.
Consider the horizontal lines passing through the vertexes of either polygons. Two consecutive lines cut out slabs (trapezoids).
As the slabs are simple, convex polygons, checking them for intersection is straightforward: it suffices to detect overlap of the bases (mind the case where they form an X cross).
Now the whole process can be decomposed as
sorting the vertices of both polygons by increasing ordinates; for every vertex, remember to what polygon it belongs and what are its neighbors with a higher ordinate (none, one or two);
scanning the vertices by increasing ordinate, while maintaining a list of the edges that are intersected (it is called the active list). Every time you move to another vertex, update the active list;
testing the slabs for intersection.
I'm making a program that needs to detect the collision between 2 non-axis aligned boxes. My program only needs an indication if 2 non-axis aligned boxes are colliding. I would like to have the most simple and efficient algorithm possible.
Here I visualized the problem.
So as you can see squares 1,2 and 3 would return true because they collided with the green squares.
4 would return false because it isn't colliding.
I do have all the boxes of both colors in separate array lists.
Does anybody know a library or algorithm for this problem? Thanks in advance.
Check out the Area class in the java.awt.geom package.
http://docs.oracle.com/javase/6/docs/api/java/awt/geom/Area.html
I don't know how "easy" your game really is, how many shapes you'd have to check for (I'm thinking efficiency here), but if you have your different color shapes in different lists, a kind of brute force iteration may work for you. Not a clue if it would be efficient enough for you. I use box2D to tell me the collisions, but sounds like that may be overkill for you.
The brute force method I'm thinking of would be to utilize libgdx's Intersector class (check out the API, it has lots of methods). Iterate through your rectangles comparing to the others. Something like IntersectRectangles() gives you a boolean if two rectangles overlap (ie: collide).
This may be too inefficient/hacky, and a physics library may be too much. So one of the other answers provided may be the sweet spot.
A commonly-used approach involves quadtrees. There's a good write-up and tutorial here, which explains how to use quadtrees to perform collision detection in 2D space.
The general idea is that your game area will keep being partitioned by four as your add objects. Each partition is called a node and each node will maintain a reference to objects that exist in the corresponding partition. Objects are placed into nodes based on where they are in the 2D space. If a node does not fit cleanly into a partition, it is inserted into the parent node. Using this method, you don't have to perform an expensive check against every other object in your 2D space, because you can be sure that objects in different nodes (at the same level; i.e., sibling nodes) will not collide. So you only have to perform your collision detection on a small subset of objects.
Note that this just tells you which objects are occupying a certain area; it's a more efficient way to hone in on objects that are likely to be colliding. After that you have to check if the objects are actually colliding. There is another write-up here that goes over various techniques to accomplish this.
There are two algorithms/data-structures you need to consider for this problem:
A spatial data-structure to store your rotated quads, to efficiently determine which pairs of quads need to be tested against each other. Other answers have already addressed this. If the number of quads is small enough then you can just test all the red quads against all the green quads, which is O(m * n).
An algorithm to perform the actual test of one rotated quad against another. One of the simplest is the Separating Axis Theorem.
The basic idea behind the SAT is that if you can find at least one line where all the points of one convex object are on one side of it, and all the points of the other are on the other side, then the two are not colliding. The potential lines that you need to test are just the edges of both of the objects.
To implement it you need to implement a point-line test to tell you which side of an edge a point is on. This is done by calculating the normal to the edge, and then calculating the dot product of the edge normal and a vector from a point on the edge to the point you are testing. The sign of the dot product tells you which side the point is on (positive means the outside the edge, for an outward pointing normal). Whether you count zero (on the line) as outside or inside depends on whether you want objects that are just touching but not penetrating to count as a collision, if you do then the dot product must be greater than zero to count as outside.
For example if the points on objects are in clockwise order, and edgeA and edgeB are the two points of an edge on one object, and pointC is a point on the other object, the test is done like this (not using function calls, to show the math):
boolean isOutsideEdge(PointF edgeA, PointF edgeB, PointF pointC)
{
float normalX = edgeA.Y - edgeB.y;
float normalY = edgeB.X - edgeA.x;
float vectorX = pointC.x - edgeA.x;
float vectorY = pointC.y - edgeA.y;
return (normalX * vectorX) + (normalY * vectorY) > 0.0f;
}
Then the algorithm is:
For each edge on quad A, if all the corner points on quad B are on the outward facing side of the edge, then A and B are not colliding, stop processing and return false.
For each edge on quad B, if all the corner points on quad A are on the outward facing side of the edge, then A and B are not colliding, stop processing and return false.
If all those tests have been performed and none have returned false, then A and B are colliding, so return true.
The SAT can be generalized to arbitrary convex polygons.
So I decided to go with box2d in the end. This was the best solution because of the diffrent mask-qualifiers, the objects didn't collide but it could be easily checked wether they should be colliding.
I had to make my own contactlistener that overrides the default contactlistener. Here I could do anything if any 2 objects collided.
Thanks everyone for the help.
I'm using a triangulation library to compute the Constrained Delaunay Triangulation of a set of rectangles within some large boundary. The algorithm returns all the edges, but also adds edges inside of the rectangles that define the constraints. I want to be able to find if an edge lies inside of a rectangle in O(1) time.
Here's a more general description of the problem I want to solve. Given a set of nonoverlapping rectangles (the borders of the rectangles may touch) and an edge e with endpoints (x1,y1) and (x2, y2), find in O(1) time if e lies within any of the rectangles (including the border).
Also let me know of any data structures I can use for speedups! I'm also implementing this in java so I have easy access to hash sets, maps and all those nice data structures.
Since the rectangles are completely enclosed, the inside of each rectangle will simply be the CDT of the rectangle itself -- which is to say, two triangles, meeting along a diagonal of the rectangle. So you can just insert all rectangles' diagonals (remember, two possible diagonals per rectangle) into a hashtable, and check which edges exactly match those endpoints.
It is possible to break up the area that all of the rectangles cover into a N by M grid of boxes. By labeling each box with the rectangle it is in or the rectangles it overlaps. It is possible to obtain O(1) queries, with O(N*M) pre-processing.
However, in order for it to work, the grid has to created based on an algorithm that allows for calculating which box a point lies in in O(1). It also requires that the number of rectangles a box overlaps be very small (ideally no more than 2 or 3) as otherwise the average query time could be O(log N) or worst. This means that the number of boxes can get very large.
There are 2 areas (java.awt.geom.Area) area1 and area2. I need to verify if area2 is inside area1? (area1 contains area2).
I have tried:
areaDelta = (Area)area1.clone();
areaDelta.add(area2);
return areaDelta.equals(area1);
But it doesnt always work as it should (If the bounds of area2 are on the bounds of area1, it returns true, should return false).
In fact I have 2 polygons (java.awt.Polygon) and I need the Polygon.contains(Polygon) method, may be this can be easier then for areas.
Any ideas?
Polygons can be convex and non-convex.
Since you have Polygon.contains(Point), you can achieve what you need by testing if every point of your second polygon is inside the first polygon (I dream of a JDK version which would implement every basic need of a programmer, like .NET).
EDIT: To handle concave polygons, you first need to split your polygons into convex ones, then you'll be able to properly use the method mentioned above. I used two different polygon decomposition algorithms in one of my applications, and I would suggest you to look at their code:
Bayazit Decomposer
Ewjordan Decomposer
I have two geo-spatial simple convex polygon areas, in latitudes and longitudes (decimal degrees) that I want to compute using Javas Polygon class. I basically want to see if these two lat,long polygons intersect, and to calculate the areas (in sq meters) of both.
Now java.awt.Polygon class only uses x,y co-ordinate system, but I need to use lats,longs.
How can I do this, and/or is there any other classes/libraries available?
Why not use Polygon class multiplying coordinates for 10^n making them integers? Polygon accepts arrays of int as points.
Just an Idea
All you need to do is convert from spherical to rectangular coordinates if you think that really matters.
I'm not sure that it does, because the java.awt.Polygon is merely a data structure holding for pairs of values. If you read the javadocs, they say
The Polygon class encapsulates a description of a closed, two-dimensional region within a coordinate space. This region is bounded by an arbitrary number of line segments, each of which is one side of the polygon. Internally, a polygon comprises of a list of (x,y) coordinate pairs, where each pair defines a vertex of the polygon, and two successive pairs are the endpoints of a line that is a side of the polygon. The first and final pairs of (x,y) points are joined by a line segment that closes the polygon.
They happen to label those points as x and y, which makes all of us think rectangular coordinates, but they need not be from your point of view. A bug on the service of your sphere would view it as a 2D space. Your radius is large and constant. You just can't count on using any of Polygon's methods (e.g., contains(), getBounds2D(), etc.)
In this case, the important thing is your area calculation. You can use a Polygon for your area calculation, storing lats and longs, as long as you view Polygon as a data structure.
You might also thing of abandoning this idea and writing your own. It's not too hard to create your own Point and Polygon for spherical coordinates and doing it all with that coordinate system in mind from the start. Better abstraction, less guessing for clients. Your attempt to reuse java.awt.Polygon is admirable, but not necessary.
You can perform the area calculation easily by converting it to a contour integral and using Gaussian quadrature to integrate along each straight line boundary segment. You can even include the curvature of each segment at each integration point, since you know the formula.
Going off my intuition here.
If the polygons are small in ratio to the size of the planet you can treat them as flat polygons. The steps involved would be converting the lat/long into absolute x/y/z, taking any three of the points and finding the normal of the plane the polygons lie on and then using this to project the points into two dimensions. Once you have the 2D points it's easy to calculate the area or if they intersect.
Probably not the best answer but hopefully it will motivate some people to make better ones because it's a good question.
Maybe you could use GeoTools for this. It allows you to create Geometry objects, and check wether they intersect (see: Geometry Relationships)
Here is a solution that works like a charm:
Class PolygonArea from net.sf.geographiclib
Refer link below with sample code:
https://geographiclib.sourceforge.io/html/java/net/sf/geographiclib/PolygonArea.html
gradle dependency:
compile group: 'net.sf.geographiclib', name: 'GeographicLib-Java', version: '1.42'