I need to check if two java.awt.Polygons overlap, but I don't know how.
Area area = new Area(poly1);
area.intersect(new Area(poly2));
return area.isEmpty();
From a geometry perspective, there are conditions that are fulfilled by overlapping polygons.
1) If a segment in A crosses a segment in B, the polygons overlap.
2) If all vertices in B are inside A, or vice-versa, the polygons overlap.
3) If all vertices in A are also vertices of B, the polygons overlap.
Testing for (1) is fairly simple. You just do a little algebra and brute force. If lines are parallel, they don't cross. If the lines are non-parallel, they intersect. If the point of intersection is within either segment, they cross. Maximum iterations is length of A * length of B.
Testing for (2) is a little more complex. One method to tell if a point is inside a poly is this: Pick a point that you know is outside of the poly, often a negative value for x,y works for this. Then, draw a line from the reference point to the test point. If it crosses an odd number of segments, it's inside. It if crosses an even number, or zero segments, it is outside.
Related
I have n geometric shapes defined in GeoJson, I would like to calculate the intersection which involves maximum number of shapes.
I have the following constraints;
none of the shapes may intersects (no intersection between any of shapes, 0-participant intersection)
all shapes may intersects (there is an intersection that is in all shapes, n-participant intersection)
there might be more than one intersection with k participant (shape A B C intersects, shape D E F intersects, there are 2 3-participant intersection, doesn't need to find both, return when first 3-participant found)
So, as a starting point, I though I could do that by using brute force (trying to intersects n, n-1, n-2 combination of given shapes) but it's time complexity will be O(n!). I'm wondering that if the algorithm could be optimized?
EDIT:
Well, I forgot the tell about data types. I'm using Esri/geometry library for shapes. Specifically, Polygon class instances.
This problem feels like you can construct hard cases that cannot be solved efficiently, specifically if the shapes are not convex. Here are two ideas that you could try:
1. Iterative Intersection
Keep a list L of (disjoint) polygons with counts that is empty in the beginning. Now iterate through your given polygons P. For each polygon p from P intersect it with all polygons l from L. If there is an intersection between p and l then remove l from L and
add set_intersection(l, p) with previous count of l +1
add set_minus(l, p) with `previous count of l'
remember set_minus(p, l) and proceed to the next entry of L
when you are through all elements of L then add the remaining part of p to L with count 1.
Eventually you will have a list of disjoint polygons with counts that is equvalent to the number of participant polygons.
2. Space Decomposition
Build a bounding box around all polygons. Then iteratively split that space (similar to a KD-Tree). For each half (rectangle), compute the number of polygons from P intersecting that rectangle. Proceed best-first (always evaluate the rectangle that has the highest count). When you are at a certain level of the KD-Tree then stop and evaluate by brute-force or Iterative Intersection.
Both methods will benefit from a filter using minimum bounding rectangles around the polygons.
A list of unprocessed (non-empty) intersections together with the polygon indices from which the intersection was created is maintained. Initially it is filled with the single polygons. Always the intersection from most polygons and least maximal index of involved polygons is taken out and intersected with all polygons with higher indices (to avoid looking at the same subset of polygons again and again). This allows an efficient pruning:
if the number of polygons involved in the currently processed intersection and the remaining indices do not surpass the highest number of polygons to have a non-empty intersection, we do not need to pursue this intersection any longer.
Here is the algorithm in Python-like notation:
def findIntersectionFromMostMembers(polygons):
unprocessedIntersections = [(polygon, {i}) for i, polygon in enumerate(polygons)]
unprocessedIntersections.reverse() # make polygon_0 the last element
intersectionFromMostMembers, indicesMost = (polygons[0], {0})
while len(unprocessedIntersections) > 0:
# last element has most involved polygons and least maximal polygon index
# -> highest chance of being extended to best intersection
intersection, indices = unprocessedIntersections.pop() # take out unprocessed intersection from most polygons
if len(indices) + n - max(indices) - 1 <= len(indicesMost):
continue # pruning 1: this intersection cannot beat best found solution so far
for i in range(max(indices)+1, n): # pruning 2: only look at polyong with higher indices
intersection1 = intersection.intersect(polygons[i])
if not intersection1.isEmpty(): # pruning 3: empty intersections do not need to be considered any further
unprocessedIntersections.insertSorted(intersection1, indices.union({i}), key = lambda(t: len(t[1]), -max(t[1])))
if len(indices)+1 > len(indicesMost):
intersectionFromMostMembers, indicesMost = (intersection1, indices.union({i}))
return intersectionFromMostMembers, indicesMost
The performance highly depends on how many polygons in average do have an area in common. The fewer (<< n) polygons have areas in common, the more effective pruning 3 is. The more polygons have areas in common, the more effective pruning 1 is. Pruning 2 makes sure that no subset of polygons is considered twice. The worst scenario seems to be when a constant fraction of n (e.g. n/2) polygons have some area in common. Up to n=40 this algorithm terminates in reasonable time (in a few seconds or at most in a few minutes). If the non-empty intersection from most polygons involves only a few (any constant << n) polygons, much bigger sets of polygons can be processed in reasonable time.
I am creating vertex array for a mesh with given points.So far I was able to create a continuous mesh with thickness.However there is a problem at the intersection of two line segments, the vectors between those segment's sizes needs to be bigger or smaller depending on the situation in order to have a continuous look.
What I have now:
With the given angles theta1 and theta2, how can I calculate the length of red vectors?
What I want:
How I structured my mesh:
You're probably making it more complicated than it needs to be.
Let's start by calculating the red arrows. For any line segment (p_i, p_j), we can calculate the segment's normal with:
dir = normalize(p_j - p_i)
normal = (-dir.y, dir.x) //negate if you want the other direction
At the connection point between two segments, we can just average (and re-normalize) the incident normals. This gives us the red arrows.
The only question that remains is how much you need to shift. The resulting offset for the line segment o_l given an offset of the vertex o_v is:
o_l = o_v * dot(normal_l, normal_v)
This means the following: Both normals are unit vectors. Hence, their dot product is at most one. This is the case when both line segments are parallel. Then, the entire offset of the vertex is transferred to the line. The smaller the angle becomes, the smaller becomes the transferred offset. E.g. if the angle between two consecutive line segments is 120°, then the dot product of normals is 0.5. If you shift the vertex by 1 unit along its normal, both line segment will have a thickness of 0.5.
So, in order to produce a specific line thickness (o_l), we need to shift the vertex by o_v:
o_v = o_l / dot(normal_l, normal_v)
The construction with averaging the line segments' normal for the vertex normal ensures that dot(normal_l1, normal_ v) = dot(normal_l2, normal_v), i.e. the resulting line thickness is equal for both lines in any case.
I am implementing collision detection in my game, and am having a bit of trouble understanding how to calculate the vector to fix my shape overlap upon collision.
Say for example, I have two squares. squareA and squareB. For both of them, I know their xCo, yCo, width and height. squareA is moving however, so he has a velocity magnitude, and a velocity angle. Let's pretend I update the game once a second. I have illustrated the situation below.
Now, I need a formula to get the vector to fix the overlap. If I apply this vector onto the red square (squareA), they should not be overlapping anymore. This is what I am looking to achieve.
Can anyone help me figure out the formula to calculate the vector?
Bonus points if constructed in Java.
Bonus bonus points if you type out the answer instead of linking to a collision detection tutorial.
Thanks guys!
Also, how do I calculate the new velocity magnitude and angle? I would like sqaureA to continue moving along the x axis (sliding along the top of the blue square)
I had an function that looked something like this:
Position calculateValidPosition(Position start, Position end)
Position middlePoint = (start + end) /2
if (middlePoint == start || middlePoint == end)
return start
if( isColliding(middlePont) )
return calculateValidPosition(start, middlePoint)
else
return calculate(middlePoint, end)
I just made this code on the fly, so there would be a lot of room for improvements... starting by not making it recursive.
This function would be called when a collision is detected, passing as a parameter the last valid position of the object, and the current invalid position.
On each iteration, the first parameter is always valid (no collition), and the second one is invalid (there is collition).
But I think this can give you an idea of a possible solution, so you can adapt it to your needs.
Your question as stated requires an answer that is your entire application. But a simple answer is easy enough to provide.
You need to partition your space with quad-trees
You seem to indicate that only one object will be displaced when a collision is detected. (For the case of multiple interpenetrating objects, simply correct each pair of objects in the set until none are overlapping.)
Neither an elastic nor an inelastic collision is the desired behavior. You want a simple projection of the horizontal velocity (of square A), so Vx(t-1) = Vx(t+1), Vy(t-1) is irrelevant and Vy(t+1)=0. Here t is the time of collision.
The repositioning of Square A is simple.
Define Cn as the vector from the centroid of A to the vertex n (where the labeling of the vertices is arbitrary).
Define A(t-1) as the former direction of A.
Define Dn as the dot product of A(t-1) and the vector Cn
Define Rn as the width of A measured along Cn (and extending past the centroid in the opposite direction).
Define Sn as the dilation of B by a radius of Rn.
Let j be the vertex of B with highest y-value.
Let k be the vertex that is most nearly the front corner of A [in the intuitive sense, where the value of Dn indicates that Ck is most nearly parallel to A(t-1)].
Let K be the antipodal edge or vertex of A, relative to k.
Finally, translate A so that k and j are coincident and K is coincident with Sk.
Does anybody know how to find out if a set of coordinates are within a triangle for which you have the coordinates for. i know how to work out length of sides, area and perimeter, but i have no idea where to begin working out the whereabouts within the triangle of other points.
Any advice would be appreciated
You can create a Polygon object.
Polygon triangle = new Polygon();
Add the vertexes of your triangle with the addPoint(int x, int y) method.
And then, you just need to check if the set of coordinates is inside your triangle using contains(double x, double y) method.
Use the contains method of the Polygon class as documented here.
For a solution without using the Polygon-class:
Assume that you have giving three points A,B,C the vertices of your polygon. Let P be the point you want to check. First calculate the vectors representing the edges of your triangle. Let us call them AB, BC, CA. Also calculate the three vectors PA, PB, PC.
Now calculate the cross product between the first two of the vectors from above.
The cross product of the first pair gives you the sin(alpha), where alpha is the angle between AB and PA, multiplied with a vector pendenpicular to AB and PA. Ignore this vector because we are interested in the angle and take a look at the sine (in the case of 2D vectors you can imagine it as the vector standing perpendicular to your screen).
The sine can take values between (let's say for the ease) betwenn 0 and 2*Pi. It's 0 exactly at 0 and Pi. For every value in between the sine is positive and for every value between Pi and 2*Pi it's negative.
So let's say your Point p is on the left hand side of AB, so the sine would be positive.
By taking the cross product of each pair from above, you could easily guess that the point P is on the left hand side of each edge from the triangle. This just means that it has to be inside the triangle.
Of course this method can even be used from calculating whether a point P is in a polygon. Be aware of the fact, that this method only works if the sides of the polygon are directed.
I have one 2d line (it can be a curved line, with loops and so on), and multiple similar paths. I want to compare the first path with the rest, and determine which one is the most similar (in percentage if possible).
I was thinking maybe transforming the paths into bitmaps and then using a library to compare the bitmaps, but that seems like overkill. In my case, I have only an uninterrupted path, made of points, and no different colors or anything.
Can anyone help me?
Edit:
So the first line is the black one. I compare all other lines to it. I want a library or algorithm that can say: the red line is 90% accurate (because it has almost the same shape, and is close to the black one); the blue line is 5% accurate - this percentage is made up for this example... - because it has a similar shape, but it's smaller and not close to the black path.
So the criterion of similarity would be:
how close the lines are one to another
what shape do they have
how big they are
(color doesn't matter)
I know it's impossible to find a library that considers all this. But the most important comparisons should be: are they the same shape and size? The distance I can calculate on my own.
I can think of two measures to express similarity between two lines N (defined as straight line segments between points p0, p1... pr)
M (with straight line segments between q0, q1, ...qs). I assume that p0 and q0 are always closer than p0 and qs.
1) Area
Use the sum of the areas enclosed between N and M, where N and M are more different as the area gets larger.
To get N and M to form a closed shape you should connect p0 and q0 and pr and qs with straight line segments.
To be able to calculate the surface of the enclosed areas, introduce new points at the intersections between segments of N and M, so that you get one or more simple polygons without holes or self-intersections. The area of such a polygon is relatively straightforward to compute (search for "polygon area calculation" around on the web), sum the areas and you have your measure of (dis)similarity.
2) Sampling
Take a predefined number (say, 1000) of sample points O that lie on N (either evenly spaced with respect to the entire line, or evenly spaced
over each line segment of N). For each sample point o in O, we'll calculate the distance to the closest corresponding point on M: the result is the sum of these distances.
Next, reverse the roles: take the sample points from M and calculate each closest corresponding point on N, and sum their distances.
Whichever of these two produces the smallest sum (they're likely not the same!) is the measure of (dis)similarity.
Note: To locate the closest corresponding point on M, locate the closest point for every straight line segment in M (which is simple algebra, google for "shortest distance between a point and a straight line segment"). Use the result from the segment that has the smallest distance to o.
Comparison
Method 1 requires several geometric primitives (point, line segment, polygon) and operations on them (such as calculating intersection points and polygon areas),
in order to implement. This is more work, but produces a more robust result and is easier to optimize for lines consisting of lots of line segments.
Method 2 requires picking a "correct" number of sample points, which can be hard if the lines have alternating parts with little detail
and parts with lots of detail (i.e. a lot of line segments close together), and its implementation is likely to quickly get (very) slow
with a large number of sample points (matching every sample point against every line segment is a quadratic operation).
On the upside, it doesn't require a lot of geometric operations and is relatively easy to implement.