So I have an image with 3 dots on it.
This is the correct orientation of the image but it can be at any degree of rotation. My goal is to identify the dots for ease we'll call them Left dot, right dot and bottom dot.
Now getting the bottom dot is easy as you just take the distances between the 3 dots and which ever dot isn't on the longest line is the bottom one.
So that leaves me with problem of identifying the left and right dot. I feel like I've forgotten some basic trig for figuring this out but my google-foo has failed me at uncovering a formula to determine the left and right side.
The 2D cross-product of two vectors, , is a scalar which is positive for when a is clockwise rotated with respect to b, and vice versa. So in the diagram below:
The left and right points satisfy and respectively.
Related
Consider the picture :
Given the black "irregular line" segments, I want to have the green boundary surrounding them.
My Attempt to solve :
Note, that I need to capture the concavity. Thus the convex hull algorithm will not work. I have used some interpolations, to draw the straight line segments indicated by overlayed red stripes. Then I attempted to run a sweep algorithm. These stripes are roughly parallel, if that helps.
That is, their headings lay within some small interval.
Heading H in { angle alpha - x , angle alpha +x } union { angle alpha - x + 180 , angle alpha +x+ 180 } for some small x
However, it needs to be guaranteed, that the green boundary should not intersect any red lines.
So, my naive attempt was :
Start at leftmost vertex of all lines.
Pick the line attached to the vertices. (if more vertices, then take the top most and bottom most)
Use this line to "partition" the plane. (or two lines or two "separatices", if 2 vertices)
Pick the next leftmost unvisited vertices.
See if the vertex lies above the top separatrix or below the bottom separatrix.
If above the top separatrix, add it to a set called "top chain", if below the bottom one, the add to bottom chain.
But this runs into problems.
The problem
To determine whether the newly picked point is at the top or at the bottom of a separatrix, I use the vector product method. But consider this :
Imagine you are at the green square. Your separatrix now is the black line, vector pointing to the left, as the arrow shows.
At this stage, you compare this with the green vector showing the next vertex to be picked on the blue line. The vector method, intended to measure angles between -Pi to Pi will consider this a negative value. Thus the point, although necessary, will not be picked up.
If you reverse the direction of the vector, then the Magenta line will not be picked up.
Question
How to efficiently solve this problem? I am using D, so bonus if there is a D library capable of this.
Filling concavities is a somewhat arbitrary operation. Have a look at Alpha-shapes, a generalization of the convex hulls.
https://en.wikipedia.org/wiki/Alpha_shape
There are 4 rules explained in Sutherland-Hodgman algorithm for clipping polygons:
If both vertices are inside the clipping area - save the second
If the first vertex is inside and the second is outside - compute the intersection with the border of the clipping area and save it
If the first vertex is outside and the second is inside - compute the intersection with the border of the clipping area and save it, and also save the second vertex
If both vertices are outside - save nothing
Due to this explanation, what will it do when a line formed by 2 vertices crosses the clipping area, like in the below image?
If I follow the algorithm steps I'll end up with no vertices at all... Is there no consideration for such a case? Maybe I should pre-calculate all the intersection areas and use also them?
I finally found the answer myself - I will share it here with everyone who likes to know...
You may see a description of the correct algorithm here: https://www.youtube.com/watch?v=Euuw72Ymu0M
It is wrongly described in many tutorials, that one should consider each vertex as inside/outside the clipping area, and then to apply the rules as described in the question above.
The correct algorithm - is to iterate over all the edges of the clipping area.
Instead of considering a vertex inside/outside the clipping area - the correct thing to do is to consider the vertex as in the inner/outer side of the specific edge we iterate on. It means that for instance, for the example image in the question - the left edge of the clipping area will consider the up-right corner of the blue rectangle as inside - because although it is outside the clipping area, it is in the inner side of the left edge. The up-left corner for instance, will be considered as outside by this edge.
If the algorithm is done in 2D, we have 4 edges of the clipping area. For example, we first apply the algorithm on the left edge - then we use its output for running the algorithm on the right edge, then the same for the upper edge and the bottom edge. The final answer will be the the output of the last one.
I.e. If we used Left->Right->Up->Bottom, the final output will be the vertex list outputted by the bottom edge.
You can try running this algorithm, following for each edge the rules described in the question - you'll see that you're final polygon will be exactly the clipped one
Please take a look at pic1 above first.
2 points combine a line, let's call it LineAB, and we can get a normal from our eye sight direction, let's call it view-direction, vector(lineAB) X view-direction, we can get a normal named plane-normal. in the pic1, plane-normal is directed to the top (green arrow), and the plane with plane-normal cut the map into 2 parts.
As the point C is on the same direction of the plane-normal, we regard it as inside, let's return true. Point D is on the anti-direction of plane-normal, it is outside, return false.
My problem is in the pic2 as following:
Now, there are many points A,A1,A2...A5,... An, build many lines such as lineAA1, line A1A2, ... LineAn-1An (one condition is: every angle between 2 adjacent lines are equal to or more than 90 degree) and plus with view direction (the direction from our eye sight), we can get many planes PAA1, PA1P2, ... PAn-1An which also cut the map to 2 parts.
I need to check one point is inside or outside.
for example, point C is inside but point D is outside.
Regarding one plane separating the dim(3)-space isn't difficult, to consider a piecewise assembled dim(2)-plane we need to dive deeper:
The problem may be reduced to separating the dim(2)-space.
If only for the calculation of the normal the 3rd dimension is considered, then that can solved in a different way:
Let v = (a,b) be the vector of a lineAB. The normal is (b, -a) or (-b, a) respectively.
If you want to check only if a point is within a polygon, just use the ray-casting-algorithm.
When it comes to dividing the dim(2)-space into two separate spaced by your polygonal chain, it won't be enough to check if the point is on the positive directon of the normals on each part line(A[i-1])(A[i]):
Polygonal chain
Point P is positive with respect to normal N0, but negative w.r.t. normal N1.
Also, the upper angles are all above 90° (some counter angles are also displayed), but the polygon chain isn't convex either w.r.t. the upward y-axis.
To solve your issue, you can use the ray-casting-algorithm, going towards negative y-direction, i.e. "downwards", and see if the amount of intersections is odd.
If the line ends at a higher x-coordinate than the start point, an odd amount of intersections means "true"
If the line ends at a lower x-coordinate than the start point, an odd amount of intersections means "false"
You can find if a ray from point C (with view direction) intersects with one of the segments AiAi+1. It could be done with binary search by X-coordinate (to find potential segment quickly)
I am trying to write an algorithm that rotates one square around its centre in 2D until it matches or is "close enough" to the rotated square which started in the same position, is the same size and has the same centre. Which is fairly easy.
However the corners of the square need to match up, thus to get a match the top right corner of the square to rotate must be close enough to what was originally the top right corner of the rotated square.
I am trying to make this as efficient as possible, so if the closeness of the two squares based on the above criteria gets worse I know I need to try and rotate back in the opposite direction.
I have already written the methods to rotate the squares, and test how close they are to one another
My main problem is how should I change the amount to rotate on each iteration based on how close I get
E.g. If the current measurement is closer than the previous, halve the angle and go in the same direction otherwise double the angle and rotate in the opposite direction?
However I don't think this is quite a poor solution in terms of efficiency.
Any ideas would be much appreciated.
How about this scheme:
Rotate in 0, 90, 180, 270 angle (note that there are efficient algorithm for these special rotations than the generic rotation); compare each of them to find the quadrant you need to be searching for. In other word, try to find the two axis with the highest match.
Then do a binary search, for example when you determined that your rotated square is in the 90-180 quadrant, then partition the search area into two octants: 90-135 and 135-180. Rotate by 90+45/2 and 180-45/2 and compare. If the 90+45/2 rotation have higher match value than the 180-45/2, then continue searching in the 90-135 octant, otherwise continue searching in the 135-180 octant. Lather, Rinse, Repeat.
Each time in the recursion, you do this:
partition the search space into two orthants (if the search space is from A to B, then the first orthant is A + (A + B) / 2 and the second orthant is B - (A + B) / 2)
check the left orthant: rotate by A + (A + B) / 4. Compare.
check the right orthant: rotate by B - (A + B) / 4. Compare.
Adjust the search space, either to left orthant or the right orthant based on whether the left or right one is have higher match value.
Another scheme I can think of is, instead of trying to rotate and search, you try to locate the "corners" of the rotated image.
If your image does not contain any transparencies, then there are four points located at sqrt(width^2+height^2) away from the center, whose color are exactly the same as the corners of the unrotated image. This will limit the number of rotations you will need to search in.
...also, to build upon the other suggestions here, remember that for any rectangle you rotate around its center, you only need to calculate the rotation of a single corner. You can infer the other three corners by adding or substracting the same offset that you calculated to get the first corner. This should speed up your calculations a bit (assuming [but not thinking] that this is a bottleneck here).
I have a map of polygons, for example:
alt text http://img13.imageshack.us/img13/2808/output.png
(sorry the image isn't so great, I'll try and get better one later)
The green lines are the shortest path from between the connected shapes. What I need to do is find the green lines that form the outer edge and which direction I need to traverse them in to circle CCW.
The polygons will always be convex and the lines will never cross. The lines are defined in terms of there X,Y endpoints. I have an index from polygons to related lines and it is tagged with which end is attached.
The reason I need this is because I need to find the edges forming each of the interior section and my wall following solution fails/crashes for the exterior section.
0. Clarification: I am not sure whether the green connections between the convex polygons are provided as part of the input or whether the program has to determine the appropriate green connections as shortest paths between polygons itself. I just noticed that your image is missing a green edge at the top right corner (that would be part of outer border if allowed).
1. Solution: Always choose the next edge. If your input specifies which green lines are allowed and which not, then you simply traverse the boundary of the outside component by finding one start point (e.g. by taking the polygon corner with lowest x-coordinate), ordering the green edges that depart from the polygon of this current point in counter-clock-wise order and choosing the edge immediately following the current point in CCW order. Now, take the other end of that edge as "current point" and repeat the same method to find the next edge... until you return to the first polygon.
2. Solution: Start with the convex hull. If you allow all possible green lines, you don't need them as input. The convex hull of all polygon edges is a first approximation to your solution (details of finding --- see further below): The convex hull contains real polygon edges (let's think of them as "black": They are part of your final solution, already in correct order) and edges that connect polygons (Let's think of them as red: They need to be replaced by green edges and possibly parts of other polygons).
Completing the 2nd solution: divide and conquer: Now, we need to replace each red edge by a combination of green and black edges. We just focus on one red line at a time (and apply the same method for each red line that we may have).
So we have one red line that contains two polygons that have one green line (the shortest connection between them) --- the four edges of these two lines define a quadrangle. If none of the other polygon corners are in this quadrangle, you are done: replace the red edge by the green edge and any black edges on the polygons to get to the connecting points.
But if you find polygon in the quadrangle, select from them the closest to the red edge. Move the red edge towards that point --- so that the new point cuts the red edge into two red edges. These two new red edges replace the one old red edge: apply this method recursively to both of them. Their corresponding quadrangles are much smaller and contain less polygon edges.
As you keep applying this divide and conquer method you will eventually end up with no remaining red edges (because you loose one red edge each time you find an empty quadrangle).
Convex hull: This is a difficult problem in n dimensions but easy in two dimensions: If you search the net or browse SO, you surely find a better solution than I can think of right now, but here is one that comes to mind (again: divide and conquer): Find one point A with maximal x-coordinate and one point B with minimal x-coordinate, connect them by two directed "blue" edges: A->B and B->A. Divide your points into two sets: those at the right hand side of the edge A->B and those on the left hand side (which really is the right hand side of B->A). We repeatedly replace each blue edge until we find the convex hull:
Take one blue edge A->B and look at the points its right hand side. If there are none, then this blue edge is really black (part of your solution). Otherwise, take the point C furthest to the right of the blue edge and replace the edge A->B by two blue edges A->C and C->B. Divide the points that were at the right hand side of A->B into those that are at the right hand side of A->C, those that are at the right hand side of C->B and those that are neither (they are ignored). Repeat until all blue edges are replaced.