A 3D surface is made from triangles with common vertices. I want to find the exterior edge, which might be concave.
All interior triangles have common vertices with neighbours. Ie no vertex is partway along an edge.
There are no holes. The surface is not closed.
From other posts here it seems the best way is to build a list of edges, then discard all edges that are duplicated. What should remain are the exterior lines.
This post mentions sorting the vertices in Min, Mid, Max order:
// Determine the ordering of vertices.
min_vertex = min(t.v1, t.v2, t.v3);
mid_vertex = median(p.v1, t.v2, t.v3);
max_vertex = max(t.v1, t.v2, t.v3);
Presumably, median(p.v1 should be t.v1, and v1 format is x-value, y-value, z-value of each vertex.
I cannot figure out how to do this after many hours, and would appreciate any plain-language help or algorithm.
Speed of calculation is not a huge factor. 5-10000 triangles in Excel/vba
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.
Having two 3D cubes/cuboids, each defined by their different vertices (p1, p2, p3, p4, p5, p6, p7, p8), how can I find the minimum distance between the cubes?
I have been working on a simple Euclidean 3D distance algorithm with the min and max of each cube but it doesn't work for rotated cubes. Is there any overall method for this problem? In this picture there are two examples of the two cubes and possible positions where I want to calculate the minimum distance:
I don't see a shortcut, so I'll answer based on brute-force case exhaustion. This won't be the fastest approach but a very robust one.
You're looking for the shortest connecting line from a point in cube A to a point in cube B. At both ends, this shortest line will surely not end inside the cube, but on a surface, edge or vertex of the cube (assuming the cubes don't overlap). So you get 9 cases:
vertex / vertex
vertex / edge
vertex / surface
edge / vertex
edge / edge
edge / surface
surface / vertex
surface / edge
surface / surface
We can omit the surface / surface case, as it's only possible with surfaces parallel to each other, and in that situation some other case, using an edge or vertex, will give the same distance.
For each of the cases, you can find online a formula for computing the distance of the (infinitely extended) geometric objects, and then you should check for staying inside the finite surfaces or edges.
Finally, you can return the minimum of the valid distances.
Of course, there can be lots of optimizations, excluding cases that cannot produce shortest distances, e.g. surfaces pointing away from the other cube, but that needs careful analysis.
Let's say we have a class/struct Point
class Point
{
int x;
int y;
}
and a class Polygon that contains list of Points
class Polygon
{
List<Point> points;
Path(List<Point> points)
{
//some implementation
}
}
I am interested in finding the Minimal bounding rectangle points of the Polygon(https://en.wikipedia.org/wiki/Minimum_bounding_rectangle). The found minimal bounding rectangle sides might not be parallel to both axis , so I am trying to find an algorithm written in Java,C#,C++ .Can anyone propose or link such a solution, thanks!
It is possible to construct minimal bounding box (both min-area and min-perimeter) using Rotating Calipers approach.
You can find description at this wayback archive page
The minimum area rectangle enclosing a convex polygon P has a side
collinear with an edge of the polygon.
The above result dramatically restricts the range of possible
rectangles. Not only is it not necessary to check all directions, but
only as many as the polygon's number of edges.
Illustrating the above result: the four lines of support (red), with
one coinciding with an edge, determine the enclosing rectangle (blue).
A simple algorithm would be to compute for each edge the corresponding
rectangle collinear with it. But the construction of this rectangle
would imply computing the polygon's extreme points for each edge, a
process that takes O(n) time (for n edges). The entire algorithm would
then have quadratic time complexity.
A much more efficient algorithm can be found. Instead of recomputing
the extreme points, it is possible to update them in constant time,
using the Rotating Calipers. Indeed, consider a convex polygon, with a
two pair of lines of support through all four usual extreme points in
the x and y directions. The four lines already determine an enclosing
rectangle for the polygon. But unless the polygon has a horizontal or
vertical edge, this rectangle is not a candidate for the minimum area.
However, the lines can be rotated until the above condition is
satisfied. This procedure is at the heart of the following algorithm.
The input is assumed to be a convex polygon with n vertices given in
clockwise order.
Compute all four extreme points for the polygon, and call them xminP,
xmaxP, yminP ymaxP.
Construct four lines of support for P through all four points. These
determine two sets of "calipers".
If one (or more) lines coincide with an edge, then compute the area of
the rectangle determined by the four lines, and keep as minimum.
Otherwise, consider the current minimum area to be infinite.
Rotate the lines clockwise until one of them coincides with an edge of
its polygon.
Compute the area of the new rectangle, and compare it to the current
minimum area. Update the minimum if necessary, keeping track of the
rectangle determining the minimum.
Repeat steps 4 and 5, until the lines have been rotated an angle
greater than 90 degrees. Output the minimum area enclosing rectangle.
Because two pairs of "calipers" determine an enclosing rectangle, this
algorithm considers all possible rectangles that could have the
minimum area. Furthermore, aside from the initialization, there are
only as many steps in the algorithm's main loop as there are vertices.
Thus the algorithm has linear time complexity.
You can do this as follows:
Find the convex hull of the polygon points. A popular method is the Graham scan.
For each edge of the convex hull, find the minimum bounding rectangle that must have one side overlapping with that edge, so that the convex hull's edge is a subsegment of that rectangle's side.
Find the two perpendicular sides of the rectangle by walking along the convex hull vertices, and projecting the vertex to the first side, retaining the two that have all other projections between them. The final opposite side can be found in a similar manner. The vertices that lie on the rectangle, should be the starting point for when this step is executed again for the next edge on the convex hull (step 2).
Calculate the size of these rectangles, and retain the minimal one.
The complexity of this algorithm is determined by the first step, which is O(nlogn). The second step is O(n), as you have a selection of one edge and 3 vertices that rotates around the convex hull, visiting each edge once, and each vertex 3 times.
I am working with several convex polygons that overlap each other and I need to combine them back together to form one single polygon that may be convex or concave.
The problem is always as follows:
1) The polygons that I need to merge together are always convex.
2) The vertices of each polygon are defined in clockwise order.
3) The polygons are never in any specific order.
4) The final polygon can only be simple convex or concave polygon, i.e. no self-intersection, no duplicate vertices or holes in the shape.
Here is an example of the kind of polygons that I am working with.
![overlapping convex polygons]"image removed")
My current approach is to start from the first polygon and vertex by vertex I loop through all vertices of all of the polygons to find overlap. If there is no overlap, I store the vertex for the final outline and continue.
Upon finding overlapping vertices, I determine which polygon to continue to by measuring the angles of the possible paths and by choosing the one that leads towards the outside of the shape.
This method works until I encounter polygons that do not have vertices overlapping each other, but instead one polygon's vertex is overlapping another polygon's side, as is the case with the rectangle in the image.
I am currently planning on solving these situations by running line intersect checks for all shapes that I have not yet processed, but I am convinced that this cannot be the easiest or the best method in terms of performance.
Does someone know how I should approach this problem in a more efficient manner and/or universal manner?
I solved this issue and I'm posting the answer here in case someone else runs into this issue as well.
My first step was to implement a pre-processing loop based on trincot's suggestions.
I calculated the minimum and maximum x and y bounds for each individual shape.
I used these values to determine all overlapping shapes and I stored a simple array for each shape that I could later use to only look at shapes that can overlap each other.
Then, for the actual loop that determines the outline of the final polygon:
I start from the first shape and simply compare its vertices to those of the nearby shapes. If there is at least one vertex that isn't shared by another vertex, it must be on the outer edge and the loop starts from there. If there are only overlapping vertices, then I add the first shape to a table for all checked shapes and repeat this process with another shape until I find a vertex that is on the outer edge.
Once the starting vertex is found, the main loop will check the vertices of the starting shape one by one and measure how far from the given vertex is from every nearby shapes' edges. If the distance is zero, then the vertex either overlaps with another shape's vertex or the vertex lies on the side of another shape.
Upon finding the aforementioned type of vertex, I add the previous shape's number to the table of checked shapes so that it isn't checked again. Then, I check if there are other shapes that share this particular vertex. If there are, then I determine the outermost shape and continue from there, starting back from step 2.
Once all shapes have been checked, I check that all non-overlapping vertices from the starting shape were indeed added to the outline. If they weren't, I add them at the end.
There may be computationally faster methods, but I found this one to be simple to write, that it meets all of my requirements and it is fast enough for my needs.
Given a vertex, you could speed up the search of an "overlapping" vertex or edge as follows:
Finding vertices
Assuming that the coordinates are exact, in the sense that if two vertices overlap, they have exactly the same x and y coordinates, without any "error" of imprecision, then it would be good to first create a hash by x-coordinate, and then for each x-entry you would have a hash by y-coordinate. The value of that inner hash would be a list of polygons that have that vertex.
That structure can be built in O(n) time, and will allow you to find a matching vertex in constant time.
Only if that gives no match, you would go to the next algorithm:
Finding edges
In a pre-processing step (only once), create a segment tree for these polygons where a "segment" corresponds to a min/max x-coordinate range for a particular polygon.
Given a vertex, use the segment tree to find the polygons that are in the right x-coordinate range, i.e. where the x-coordinate of the vertex is within the min/max range of x-coordinates of the polygon.
Iterate those polygons, and eliminate those that do not have an y-coordinate range that has the y-coordinate of the vertex.
If no polygons remain, the vertex does not participate in any edge of another polygon.
You cannot get more than one polygon here, since that would mean another polygon shares the vertex, which is a case already covered by the hash-based algorithm.
If you get just one polygon, then continue your search by going through the edges of that polygon to find a match -- which is what you already planned on doing (line intersect check), but now you would only need to do it for one polygon.
You could speed that line intersect check up a little bit by first filtering the edges to those that have the right x-range. For convex polygons you would end up with at most two edges. At most one of those two will have the right y-range. If you get such an edge, check whether the vertex is really on that edge.
Say I have a polygon. It can be a convex one or not, it doesn't matter, but it doesn't have holes. It also has "inner" vertices and edges, meaning that it is partitioned.
Is there any kind of popular/known algorithm or standard procedures for when I want to check if a point is inside that kind of polygon?
I'm asking because Winding Number and Ray Casting aren't accurate in this case
Thanks in advance
You need to clarify what you mean by 'inner vertices and edges'. Let's take a very general case and hope that you find relevance.
The ray casting (point in polygon) algorithm shoots off a ray counting the intersections with the sides of the POLYGON (Odd intersections = inside, Even = outside).
Hence it accurately gives the correct result regardless of whether you start from inside the disjoint trapezoidal hole or the triangular hole (inner edges?) or even if a part of the polygon is completely seperated and/or self intersecting.
However, in what order do you feed the vertices of the polygon such that all the points are evaluated correctly?
Though this is code specific, if you're using an implementation that is counting every intersection with the sides of the polygon then this approach will work -
- Break the master polygon into polygonal components. eg - trapezoidal hole is a polygonal component.
- Start with (0,0) vertex (doesn't matter whether (0,0) actually lies wrt your polygon) followed by the first component' vertices, repeating its first vertex after the last vertex.
- Include another (0,0) vertex.
- Include the next component , repeating its first vertex after the last vertex.
- Repeat the above two steps for each component.
- End with a final (0,0) vertex.
2 component eg- Let the vertices of the two components be (1x,1y), (2x,2y), (3x,3y) and (Ax,Ay), (Bx,By), (Cx,Cy). Where (Ax,Ay), (Bx,By), (Cx,Cy) could be anything from a disjoint triangular hole, intersecting triangle or separated triangle.
Hence , the vertices of a singular continous polygon which is mathematically equivalent to the 2 components is -
(0,0),(1x,1y),(2x,2y),(3x,3y),(1x,1y),(0,0),(Ax,Ay),(Bx,By),(Cx,Cy),(Ax,Ay),(0,0)
To understand how it works, try drawing this mathematically equivalent polygon on a scratch pad.-
1. Mark all the vertices but don't join them yet.
2. Mark the repeated vertices separately also. Do this by marking them close to the original points, but not on them. (at a distance e, where e->0 (tends to/approaches) ) (to help visualize)
3. Now join all the vertices in the right order (as in the example above)
You will notice that this forms a continuous polygon and only becomes disjoint at the e=0 limit.
You can now send this mathematically equivalent polygon to your ray casting function (and maybe even winding number function?) without any issues.