Does anyone know an algorithm which checks for congruence between two sets of polygons? To be more specific, see the figure below.
I'm looking for a way to check whether a given set of colored triangles is congruent to another set, i.e. whether a given set (e.g. the blue triangles) via a number of translations, rotations or reflections can be superimposed on another set (e.g. the red triangles). In the example above, all 3 sets of triangles (blue, red and green) are congruent.
The actual triangle I'm working on is larger than this and has more sets.
I've googled and found this paper, but it concerns 3-D polygons and isn't directly (in my view) implementable.
Any constructive ideas or links would be welcome.
Edit
Just to clarify, each set of triangles must be treated as a whole connected figure, i.e. each triangle in the set is fixed in it's position relative to the other triangles in the set.
Also, I only need an algorithm which could determine whether one set of triangles is congruent to another set, but with a much larger triangle than the one above and with many more sets. Imagine a triangle with side length N and a total of N^2 smaller triangles, divided into N differently colored sets of N triangles.
A combination of rotations and reflections can be represented by a rotation and at most one reflection, so you can ignore reflections if you run a rotation-only algorithm twice, once with the original figure and once with a reflected figure.
The centre of gravity of the triangles (or, easier, the centre of gravity of a figure which has mass only at the vertices of the triangles) is not affected by rotation, so I would start by computing the centre of gravity of each figure. Now represent the figure by a list giving the direction and distance of each point in the figure from its centre of gravity.
If the set of distances are different the figures cannot be rotations of each other, and I guess most non-congruencies will be spotted at this stage. For total cost N^2 you can consider rotating a vertex in one figure to each possible vertex of the other figure and then applying this calculated rotation to all of the other vertices and seeing if they match up. Possibly some version of https://en.wikipedia.org/wiki/Lexicographically_minimal_string_rotation could be used to speed this up. It may help to represent directions by the angle between the directions to vertices after sorting them into order.
Related
This question is an extension on some computation details of this question.
Suppose one has a set of (potentially overlapping) circles, and one wishes to compute the area this set of circles covers. (For simplicity, one can assume some precomputation steps have been made, such as getting rid of circles included entirely in other circles, as well as that the circles induce one connected component.)
One way to do this is mentioned in Ants Aasma's and Timothy's Shields' answers, being that the area of overlapping circles is just a collection of circle slices and polygons, both of which the area is easy to compute.
The trouble I'm encountering however is the computation of these polygons. The nodes of the polygons (consisting of circle centers and "outer" intersection points) are easy enough to compute:
And at first I thought a simple algorithm of picking a random node and visiting neighbors in clockwise order would be sufficient, but this can result in the following "outer" polygon to be constructed, which is not part of the correct polygons.
So I thought of different approaches. A Breadth First Search to compute minimal cycles, but I think the previous counterexample can easily be modified so that this approach results in the "inner" polygon containing the hole (and which is thus not a correct polygon).
I was thinking of maybe running a Las Vegas style algorithm, taking random points and if said point is in an intersection of circles, try to compute the corresponding polygon. If such a polygon exists, remove circle centers and intersection points composing said polygon. Repeat until no circle centers or intersection points remain.
This would avoid ending up computing the "outer" polygon or the "inner" polygon, but would introduce new problems (outside of the potentially high running time) e.g. more than 2 circles intersecting in a single intersection point could remove said intersection point when computing one polygon, but would be necessary still for the next.
Ultimately, my question is: How to compute such polygons?
PS: As a bonus question for after having computed the polygons, how to know which angle to consider when computing the area of some circle slice, between theta and 2PI - theta?
Once we have the points of the polygons in the right order, computing the area is a not too difficult.
The way to achieve that is by exploiting planar duality. See the Wikipedia article on the doubly connected edge list representation for diagrams, but the gist is, given an oriented edge whose right face is inside a polygon, the next oriented edge in that polygon is the reverse direction of the previous oriented edge with the same head in clockwise order.
Hence we've reduced the problem to finding the oriented edges of the polygonal union and determining the correct order with respect to each head. We actually solve the latter problem first. Each intersection of disks gives rise to a quadrilateral. Let's call the centers C and D and the intersections A and B. Assume without loss of generality that the disk centered at C is not smaller than the disk centered at D. The interior angle formed by A→C←B is less than 180 degrees, so the signed area of that triangle is negative if and only if A→C precedes B→C in clockwise order around C, in turn if and only if B→D precedes A→D in clockwise order around D.
Now we determine which edges are actually polygon boundaries. For a particular disk, we have a bunch of angle intervals around its center from before (each sweeping out the clockwise sector from the first endpoint to the second). What we need amounts to a more complicated version of the common interview question of computing the union of segments. The usual sweep line algorithm that increases the cover count whenever it scans an opening endpoint and decreases the cover count whenever it scans a closing endpoint can be made to work here, with the adjustment that we need to initialize the count not to 0 but to the proper cover count of the starting angle.
There's a way to do all of this with no trigonometry, just subtraction and determinants and comparisons.
I have a 3D mesh consisting of triangle polygons. My mesh can be either oriented left or right:
I'm looking for a method to detect mesh direction: right vs left.
So far I tried to use mesh centroid:
Compare centroid to bounding-box (b-box) center
See if centroid is located left of b-box center
See if centroid is located right of b-box center
But the problem is that the centroid and b-box center don't have a reliable difference in most cases.
I wonder what is a quick algorithm to detect my mesh direction.
Update
An idea proposed by #collapsar is ordering Convex Hull points in clockwise order and investigating the longest edge:
UPDATE
Another approach as suggested by #YvesDaoust is to investigate two specific regions of the mesh:
Count the vertices in two predefined regions of the bounding box. This is a fairly simple O(N) procedure.
Unless your dataset is sorted in some way, you can't be faster than O(N). But if the point density allows it, you can subsample by taking, say, every tenth point while applying the procedure.
You can as well keep your idea of the centroid, but applying it also in a subpart.
The efficiency of an algorithm to solve your problem will depend on the data structures that represent your mesh. You might need to be more specific about them in order to obtain a sufficiently performant procedure.
The algorithms are presented in an informal way. For a more rigorous analysis, math.stackexchange might be a more suitable place to ask (or another contributor is more adept to answer ...).
The algorithms are heuristic by nature. Proposals 1 and 3 will work fine for meshes whose local boundary's curvature is mostly convex locally (skipping a rigorous mathematical definition here). Proposal 2 should be less dependent on the mesh shape (and can be easily tuned to cater for ill-behaved shapes).
Proposal 1 (Convex Hull, 2D)
Let M be the set of mesh points, projected onto a 'suitable' plane as suggested by the graphics you supplied.
Compute the convex hull CH(M) of M.
Order the n points of CH(M) in clockwise order relative to any point inside CH(M) to obtain a point sequence seq(P) = (p_0, ..., p_(n-1)), with p_0 being an arbitrary element of CH(M). Note that this is usually a by-product of the convex hull computation.
Find the longest edge of the convex polygon implied by CH(M).
Specifically, find k, such that the distance d(p_k, p_((k+1) mod n)) is maximal among all d(p_i, p_((i+1) mod n)); 0 <= i < n;
Consider the vector (p_k, p_((k+1) mod n)).
If the y coordinate of its head is greater than that of its tail (ie. its projection onto the line ((0,0), (0,1)) is oriented upwards) then your mesh opens to the left, otherwise to the right.
Step 3 exploits the condition that the mesh boundary be mostly locally convex. Thus the convex hull polygon sides are basically short, with the exception of the side that spans the opening of the mesh.
Proposal 2 (bisector sampling, 2D)
Order the mesh points by their x coordinates int a sequence seq(M).
split seq(M) into 2 halves, let seq_left(M), seq_right(M) denote the partition elements.
Repeat the following steps for both point sets.
3.1. Select randomly 2 points p_0, p_1 from the point set.
3.2. Find the bisector p_01 of the line segment (p_0, p_1).
3.3. Test whether p_01 lies within the mesh.
3.4. Keep a count on failed tests.
Statistically, the mesh point subset that 'contains' the opening will produce more failures for the same given number of tests run on each partition. Alternative test criteria will work as well, eg. recording the average distance d(p_0, p_1) or the average length of (p_0, p_1) portions outside the mesh (both higher on the mesh point subset with the opening). Cut off repetition of step 3 if the difference of test results between both halves is 'sufficiently pronounced'. For ill-behaved shapes, increase the number of repetitions.
Proposal 3 (Convex Hull, 3D)
For the sake of completeness only, as your problem description suggests that the analysis effectively takes place in 2D.
Similar to Proposal 1, the computations can be performed in 3D. The convex hull of the mesh points then implies a convex polyhedron whose faces should be ordered by area. Select the face with the maximum area and compute its outward-pointing normal which indicates the direction of the opening from the perspective of the b-box center.
The computation gets more complicated if there is much variation in the side lengths of minimal bounding box of the mesh points, ie. if there is a plane in which most of the variation of mesh point coordinates occurs. In the graphics you've supplied that would be the plane in which the mesh points are rendered assuming that their coordinates do not vary much along the axis perpendicular to the plane.
The solution is to identify such a plane and project the mesh points onto it, then resort to proposal 1.
At the entrance, two polygons are given (the coordinates of the vertices of these polygons are listed in the order of their traversal; however, the traversal order for different polygon angles can be chosen different). Can one polygon be transformed into another using only parallel translation and proportional scaling?
I have following idea
So, find some common peak for two polygons and make the transfer of one polygon so that these vertices lie on one point then Scaling so that the neighboring point matches the corresponding point of another polygon, but I think it's wrong , at least I can't write it in code
Is there some special formula or theorem for this problem?
I would solve it like this.
Find the necessary parallel transport.
Find the necessary scaling.
See if they are the same polygon now.
So to start take the vertex that it farthest to the left, and if there is a tie, the one that is farthest down. Find that for both polygons. Use parallel transport to put that vertex at the origin for both.
Now take the vertex that is farthest to the right, and if there is a tie, the one that is farthest up. Find that for both polygons. If it is not at the same slope, then they are different. If it is, then scale one so that the points match.
Now see if all of the points match. If not, they are different. Otherwise the answer is yes.
Compute the axis-aligned bounding boxes of the two polygons.
If the aspect ratios do not match, the answer is negative. Otherwise the ratio of corresponding sides is your scaling factor. The translation is obtained by linking the top left corners and the transformation equations are
X = s.(x - xtl) + Xtl
Y = s.(y - ytl) + Ytl
where s is the scaling factor and (xtl, ytl), (Xtl, Ytl) are the corners.
Now choose a vertex of the first polygon, predict the coordinates in the other and find the matching vertex. If you can't, the answer is negative. Otherwise, you can compare the remaining vertices*.
*I assume that the polygons do not have overlapping vertices. If they can have arbitrary self-overlaps, I guess that you have to try matching all vertices, with all cyclic permutations.
I have two 2D rectangles, defined as an origin (x,y) a size (height, width) and an angle of rotation (0-360°). I can guarantee that both rectangles are the same size.
I need to calculate the approximate area of intersection of these two rectangles.
The calculation does not need to be exact, although it can be. I will be comparing the result with other areas of intersection to determine the largest area of intersection in a set of rectangles, so it only needs to be accurate relative to other computations of the same algorithm.
I thought about using the area of the bounding box of the intersected region, but I'm having trouble getting the vertices of the intersected region because of all of the different possible cases:
I'm writing this program in Objective-C in the Cocoa framework, for what it's worth, so if anyone knows any shortcuts using NSBezierPath or something you're welcome to suggest that too.
To supplement the other answers, your problem is an instance of line clipping, a topic heavily studied in computer graphics, and for which there are many algorithms available.
If you rotate your coordinate system so that one rectangle has a horizontal edge, then the problem is exactly line clipping from there on.
You could start at the Wikipedia article on the topic, and investigate from there.
A simple algorithm that will give an approximate answer is sampling.
Divide one of your rectangles up into grids of small squares. For each intersection point, check if that point is inside the other rectangle. The number of points that lie inside the other rectangle will be a fairly good approximation to the area of the overlapping region. Increasing the density of points will increase the accuracy of the calculation, at the cost of performance.
In any case, computing the exact intersection polygon of two convex polygons is an easy task, since any convex polygon can be seen as an intersection of half-planes. "Sequential cutting" does the job.
Choose one rectangle (any) as the cutting rectangle. Iterate through the sides of the cutting rectangle, one by one. Cut the second rectangle by the line that contains the current side of the cutting rectangle and discard everything that lies in the "outer" half-plane.
Once you finish iterating through all cutting sides, what remains of the other rectangle is the result.
You can actually compute the exact area.
Make one polygon out of the two rectangles. See this question (especially this answer), or use the gpc library.
Find the area of this polygon. See here.
The shared area is
area of rectangle 1 + area of rectangle 2 - area of aggregated polygon
Take each line segment of each rectangle and see if they intersect. There will be several possibilities:
If none intersect - shared area is zero - unless all points of one are inside the other. In that case the shared area is the area of the smaller one.
a If two consecutive edges of one rectactangle intersect with a single edge of another rectangle, this forms a triangle. Compute its area.
b. If the edges are not consequtive, this forms a quadrilateral. Compute a line from two opposite corners of the quadrilateral, this makes two triangles. Compute the area of each and sum.
If two edges of one intersect with two edges of another, then you will have a quadrilateral. Compute as in 2b.
If each edge of one intersects with each edge of the other, you will have an octagon. Break it up into triangles ( e.g. draw a ray from one vertex to each other vertex to make 4 triangles )
#edit: I have a more general solution.
Check the special case in 1.
Then start with any intersecting vertex, and follow the edges from there to any other intersection point until you are back to the first intersecting vertex. This forms a convex polygon. draw a ray from the first vertex to each opposite vetex ( e.g. skip the vertex to the left and right. ) This will divide it into a bunch of triangles. compute the area for each and sum.
A brute-force-ish way:
take all points from the set of [corners of
rectangles] + [points of intersection of edges]
remove the points that are not inside or on the edge of both rectangles.
Now You have corners of intersection. Note that the intersection is convex.
sort the remaining points by angle between arbitrary point from the set, arbitrary other point, and the given point.
Now You have the points of intersection in order.
calculate area the usual way (by cross product)
.
What is a fast algorithm for determining whether or not a point is inside a 3D mesh? For simplicity you can assume the mesh is all triangles and has no holes.
What I know so far is that one popular way of determining whether or not a ray has crossed a mesh is to count the number of ray/triangle intersections. It has to be fast because I am using it for a haptic medical simulation. So I cannot test all of the triangles for ray intersection. I need some kind of hashing or tree data structure to store the triangles in to help determine which triangle are relevant.
Also, I know that if I have any arbitrary 2D projection of the vertices, a simple point/triangle intersection test is all necessary. However, I'd still need to know which triangles are relevant and, in addition, which triangles lie in front of a the point and only test those triangles.
I solved my own problem. Basically, I take an arbitrary 2D projection (throw out one of the coordinates), and hash the AABBs (Axis Aligned Bounding Boxes) of the triangles to a 2D array. (A set of 3D cubes as mentioned by titus is overkill, as it only gives you a constant factor speedup.) Use the 2D array and the 2D projection of the point you are testing to get a small set of triangles, which you do a 3D ray/triangle intersection test on (see Intersections of Rays, Segments, Planes and Triangles in 3D) and count the number of triangles the ray intersection where the z-coordinate (the coordinate thrown out) is greater than the z-coordinate of the point. An even number of intersections means it is outside the mesh. An odd number of intersections means it is inside the mesh. This method is not only fast, but very easy to implement (which is exactly what I was looking for).
This is algorithm is efficient only if you have many queries to justify the time for constructing the data structure.
Divide the space into cubes of equal size (we'll figure out the size later). For each cube know which triangles has at least a point in it. Discard the cubes that don't contain anything. Do a ray casting algorithm as presented on wikipedia, but instead o testing if the line intersects each triangle, get all the cubes that intersect with the line, and then do ray casting only with the triangles in these cubes. Watch out not to test the same triangle more than one time because it is present in two cubes.
Finding the proper cube size is tricky, it shouldn't be neither to big or too small. It can only be found by trial and error.
Let's say number of cubes is c and number of triangles is t.
The mean number of triangles in a cube is t/c
k is mean number of cubes that intersect the ray
line-cube intersections + line-triangle intersection in those cubes has to be minimal
c+k*t/c=minimal => c=sqrt(t*k)
You'll have to test out values for the size of the cubes until c=sqrt(t*k) is true
A good starting guess for the size of the cube would be sqrt(mesh width)
To have some perspective, for 1M triangles you'll test on the order of 1k intersections
Ray Triangle Intersection appears to be a good algorithm when it comes to accuracy. The Wiki has some more algorithms. I am linking it here, but you might have seen this already.
Can you, perhaps improvise by, maintaining a matrix of relationship between the points and the plane to which they make the vertices? This subject appears to be a topic of investigation in the academia. Not sure how to access more discussions related to this.