Smallest Rectangular Box that surrounds a polyhedron - computational-geometry

I'm looking for an algorithm that finds the smallest box enclosing a polyhedron.
My idea is as follows: find the largest side, and move the solid so that side aligns with the x axis. Find the next largest side that meets this side, and align it as close as possible to the z axis, while leaving the other side on x.
Then, calculate the greatest differences in x, y and z. Use those dimensions to create the surrounding shape and then shift the box back to the object's original location.
Is there a more efficient strategy for this?
Does my idea overlook some corner cases?
Edit: For now assume the object to be bounded is convex. Though, an answer for the general case would also be welcome.

The problem of finding minimal (volume) boxes for convex polyhedrons has been studied by O'Rourke, who proposes an O(n^3) algorithm:
J. O-Rourke. Finding minimal enclosing boxes. International Journal of
Computer & Information Sciences, 1985, 14(3), p.183.
O'Rourke's algorithm finds the minimal enclosing box for a set of points in R^3 -- but this is clearly equivalent to finding the enclosing box for the polyhedron formed as the convex hull of the underlying point-set.
Contrary to what one might expect (and the approach you've described, if I've understood you correctly), the minimal box is not necessarily oriented such that a face of the polyhedron is coplanar with a face of the box! Note the animation shown here for a simple tetrahedron.
If you're happy with the idea of simply find an enclosing box that's relatively small, rather than the smallest enclosing box, there may be other (faster) heuristics that can be applied...

Related

Point in polygon algorithm that returns true when the test point is on a polygon edge

I've implemented a point-in-polygon algorithm based on http://alienryderflex.com/polygon/.
It works fine but, as it says in the article:
If the test point is on the border of the polygon, this algorithm will deliver unpredictable results
It turns out I need the algorithm to return true when the test point is on the border/edge (and the vertices) of the polygon.
Is there either:
An alternative algorithm that will help me; or
A way to modify this algorithm to get what I want (e.g. by expanding the polygon a little bit before running the algorithm)
Expanding the polygon a bit is an option but this can be tricky with concave polygons.
My recommendation would be to shift the point into different directions (up/down/left/right) by a tiny amount and do the calculation for each of these shifted points. Then count it as being inside if at least one of the shifted points is determined to be inside.
Another option is to let the line on which the intersections are counted run in different directions, not only horizontally.
But then it might not be worth the while because, as your linked article states:
"That is not generally a problem, since the edge of the polygon is infinitely thin anyway, and points that fall right on the edge can go either way without hurting the look of the polygon."

polygon union without holes

Im looking for some fairly easy (I know polygon union is NOT an easy operation but maybe someone could point me in the right direction with a relativly easy one) algorithm on merging two intersecting polygons. Polygons could be concave without holes and also output polygon should not have holes in it. Polygons are represented in counter-clockwise manner. What I mean is presented on a picture. As you can see even if there is a hole in union of polygons I dont need it in the output. Input polygons are for sure without holes. I think without holes it should be easier to do but still I dont have an idea.
Remove all the vertices of the polygons which lie inside the other polygon: http://paulbourke.net/geometry/insidepoly/
Pick a starting point that is guaranteed to be in the union polygon (one of the extremes would work)
Trace through the polygon's edges in counter-clockwise fashion. These are points in your union. Trace until you hit an intersection (note that an edge may intersect with more than one edge of the other polygon).
Find the first intersection (if there are more than one). This is a point in your Union.
Go back to step 3 with the other polygon. The next point should be the point that makes the greatest angle with the previous edge.
You can proceed as below:
First, add to your set of points all the points of intersection of your polygons.
Then I would proceed like graham scan algorithm but with one more constraint.
Instead of selecting the point that makes the highest angle with the previous line (have a look at graham scan to see what I mean (*), chose the one with the highest angle that was part of one of the previous polygon.
You will get an envellope (not convex) that will describe your shape.
Note:
It's similar to finding the convex hull of your points.
For example graham scan algorithm will help you find the convex hull of the set of points in O (N*ln (N) where N is the number of points.
Look up for convex hull algorithms, and you can find some ideas.
Remarques:
(*)From wikipedia:
The first step in this algorithm is to find the point with the lowest
y-coordinate. If the lowest y-coordinate exists in more than one point
in the set, the point with the lowest x-coordinate out of the
candidates should be chosen. Call this point P. This step takes O(n),
where n is the number of points in question.
Next, the set of points must be sorted in increasing order of the
angle they and the point P make with the x-axis. Any general-purpose
sorting algorithm is appropriate for this, for example heapsort (which
is O(n log n)). In order to speed up the calculations, it is not
necessary to calculate the actual angle these points make with the
x-axis; instead, it suffices to calculate the cosine of this angle: it
is a monotonically decreasing function in the domain in question
(which is 0 to 180 degrees, due to the first step) and may be
calculated with simple arithmetic.
In the convex hull algorithm you chose the point of the angle that makes the largest angle with the previous side.
To "stick" with your previous polygon, just add the constraint that you must select a side that previously existed.
And you take off the constraint of having angle less than 180°
I don't have a full answer but I'm about to embark on a similar problem. I think there are two step which are fairly important. First would be to find a point on some polygon which lies on the outside edge. Second would be to make a list of bounding boxes for all the vertices and see which of these overlap. This means when you iterate through vertices, you don't have to do tests for all of them, only those which you know have a chance of intersecting (bounding box problems are lightweight).
Since you now have an outside point, you can now iterate through connected points until you detect an intersection. If you know which side is inside and which outside (you may need to do some work on the first vertex to know this), you know which way to go on the intersection. Then it's merely a matter of switching polygons.
This gets a little more interesting if you want to maintain that hole (which I do) in which case, I would probably make sure I had used up all my intersecting bounding boxes. You also didn't specify what should happen if your polygons don't intersect at all. But that's either going to be leave them alone (which could potentially be a problem if you're expecting one polygon out) or return an error.

Is there a simple algorithm for calculating the maximum inscribed circle into a convex polygon?

I found some solutions, but they're too messy.
Yes. The Chebyshev center, x*, of a set C is the center of the largest ball that lies inside C. [Boyd, p. 416] When C is a convex set, then this problem is a convex optimization problem.
Better yet, when C is a polyhedron, then this problem becomes a linear program.
Suppose the m-sided polyhedron C is defined by a set of linear inequalities: ai^T x <= bi, for i in {1, 2, ..., m}. Then the problem becomes
maximize R
such that ai^T x + R||a|| <= bi, i in {1, 2, ..., m}
R >= 0
where the variables of minimization are R and x, and ||a|| is the Euclidean norm of a.
Perhaps these "too messy" solutions are what you actually looking for, and there are no simplier ones?
I can suggest a simple, but potentially imprecise solution, which uses numerical analysis. Assume you have a resilient ball, and you inflate it, starting from radius zero. If its center is not in the center you're looking for, then it will move, because the walls would "push" it in the proper direction, until it reaches the point, from where he can't move anywhere else. I guess, for a convex polygon, the ball will eventually move to the point where it has maximum radius.
You can write a program that emulates the process of circle inflation. Start with an arbitrary point, and "inflate" the circle until it reaches a wall. If you keep inflating it, it will move in one of the directions that don't make it any closer to the walls it already encounters. You can determine the possible ways where it could move by drawing the lines that are parallel to the walls through the center you're currently at.
In this example, the ball would move in one of the directions marked with green:
(source: coldattic.info)
Then, move your ball slightly in one of these directions (a good choice might be moving along the bisection of the angle), and repeat the step. If the new radius would be less than the one you have, retreat and decrease the pace you move it. When you'll have to make your pace less than a value of, say, 1 inch, then you've found the centre with precision of 1 in. (If you're going to draw it on a screen, precision of 0.5 pixel would be good enough, I guess).
If an imprecise solution is enough for you, this is simple enough, I guess.
Summary: It is not trivial. So it is very unlikely that it will not get messy. But there are some lecture slides which you may find useful.
Source: http://www.eggheadcafe.com/software/aspnet/30304481/finding-the-maximum-inscribed-circle-in-c.aspx
Your problem is not trivial, and there
is no C# code that does this straight
out of the box. You will have to write
your own. I found the problem
intriguing, and did some research, so
here are a few clues that may help.
First, here's an answer in "plain
English" from mathforum.org:
Link
The answer references Voronoi Diagrams
as a methodology for making the
process more efficient. In researching
Voronoi diagrams, in conjunction with
the "maximum empty circle" problem
(same problem, different name), I came
across this informative paper:
http://www.cosy.sbg.ac.at/~held/teaching/compgeo/slides/vd_slides.pdf
It was written by Martin Held, a
Computational Geometry professor at
the University of Salzberg in Austria.
Further investigation of Dr. Held's
writings yielded a couple of good
articles:
http://www.cosy.sbg.ac.at/~held/projects/vroni/vroni.html
http://www.cosy.sbg.ac.at/~held/projects/triang/triang.html
Further research into Vornoi Diagrams
yielded the following site:
http://www.voronoi.com/
This site has lots of information,
code in various languages, and links
to other resources.
Finally, here is the URL to the
Mathematics and Computational Sciences
Division of the National Institute of
Standards and Technology (U.S.), a
wealth of information and links
regarding mathematics of all sorts:
http://math.nist.gov/mcsd/
-- HTH,
Kevin Spencer Microsoft MVP
The largest inscribed circle (I'm assuming it's unique) will intersect some of the faces tangentially, and may fail to intersect others. Let's call a face "relevant" if the largest inscribed circle intersects it, and "irrelevant" otherwise.
If your convex polygon is in fact a triangle, then the problem can be solved by calculating the triangle's incenter, by intersecting angle bisectors. This may seem a trivial case, but even when
your convex polygon is complicated, the inscribed circle will always be tangent to at least three faces (proof? seems geometrically obvious), and so its center can be calculated as the incenter of three relevant faces (extended outwards to make a triangle which circumscribes the original polygon).
Here we assume that no two such faces are parallel. If two are parallel, we have to interpret the "angle bisector" of two parallel lines to mean that third parallel line between them.
This immediately suggests a rather terrible algorithm: Consider all n-choose-3 subsets of faces, find the incenters of all triangles as above, and test each circle for containment in the original polygon. Maximize among those that are legal. But this is cubic in n and we can do much better.
But it's possible instead to identify faces that are irrelevant upfront: If a face is tangent
to some inscribed circle, then there is a region of points bounded by that face and by the two angle bisectors at its endpoints, wherein the circle's center must lie. If even the circle whose center lies at the farthest tip of that triangular region is "legal" (entirely contained in the polygon), then the face itself is irrelevant, and can be removed. The two faces touching it should be extended beyond it so that they meet.
By iteratively removing faces which are irrelevant in this sense, you should be able to reduce the
polygon to a triangle, or perhaps a trapezoid, at which point the problem will be easily solved, and its solution will still lie within the original polygon.

Polygon packing 2D

I have problem of packing 2 arbitrary polygons. I.e. we have 2 arbitrary polygons. We are to find such placement of this polygons (we could make rotations and movements), when rectangle, which circumscribes this polygons has minimal area.
I know, that this is a NP-complete problem. I want to choose an efficient algorithm for solving this problem. I' looking for No-Fit-Polygon approach. But I could't find anywhere the simple and clear algorithm for finding the NFP of two arbitrary polygons.
The parameter space does not seem too big and testing it is not too bad either. If you fix one polygon, the other ploygon can be shifted along x-axis by X, and shifted along y-axis by Y and rotated by r.
The interesting region for X and Y can be determined by finding some bounding box for for the polygons. r of course is between and 360 degrees.
So how about you tried a set of a set of equally spaced intervals in the interesting range for X,Y and r. Perhaps, once you found the interesting points in these dimensions, you can do more finer grained search.
If its NP-complete then you need heuristics, not algorithms. I'd try putting each possible pair of sides together and then sliding one against the other to minimise area, constrained by possible overlap if they are concave of course.
There is an implementation of a robust and comprehensive no-fit polygon generation in a C++ library using an orbiting approach: https://github.com/kallaballa/libnfporb
(I am the author of libnfporb)

Is there an efficient algorithm to generate a 2D concave hull?

Having a set of (2D) points from a GIS file (a city map), I need to generate the polygon that defines the 'contour' for that map (its boundary). Its input parameters would be the points set and a 'maximum edge length'. It would then output the corresponding (probably non-convex) polygon.
The best solution I found so far was to generate the Delaunay triangles and then remove the external edges that are longer than the maximum edge length. After all the external edges are shorter than that, I simply remove the internal edges and get the polygon I want. The problem is, this is very time-consuming and I'm wondering if there's a better way.
One of the former students in our lab used some applicable techniques for his PhD thesis. I believe one of them is called "alpha shapes" and is referenced in the following paper:
http://www.cis.rit.edu/people/faculty/kerekes/pdfs/AIPR_2007_Gurram.pdf
That paper gives some further references you can follow.
This paper discusses the Efficient generation of simple polygons for characterizing the shape of a set of points in the plane and provides the algorithm. There's also a Java applet utilizing the same algorithm here.
The guys here claim to have developed a k nearest neighbors approach to determining the concave hull of a set of points which behaves "almost linearly on the number of points". Sadly their paper seems to be very well guarded and you'll have to ask them for it.
Here's a good set of references that includes the above and might lead you to find a better approach.
The answer may still be interesting for somebody else: One may apply a variation of the marching square algorithm, applied (1) within the concave hull, and (2) then on (e.g. 3) different scales that my depend on the average density of points. The scales need to be int multiples of each other, such you build a grid you can use for efficient sampling. This allows to quickly find empty samples=squares, samples that are completely within a "cluster/cloud" of points, and those, which are in between. The latter category then can be used to determine easily the poly-line that represents a part of the concave hull.
Everything is linear in this approach, no triangulation is needed, it does not use alpha shapes and it is different from the commercial/patented offering as described here ( http://www.concavehull.com/ )
A quick approximate solution (also useful for convex hulls) is to find the north and south bounds for each small element east-west.
Based on how much detail you want, create a fixed sized array of upper/lower bounds.
For each point calculate which E-W column it is in and then update the upper/lower bounds for that column. After you processed all the points you can interpolate the upper/lower points for those columns that missed.
It's also worth doing a quick check beforehand for very long thin shapes and deciding wether to bin NS or Ew.
A simple solution is to walk around the edge of the polygon. Given a current edge om the boundary connecting points P0 and P1, the next point on the boundary P2 will be the point with the smallest possible A, where
H01 = bearing from P0 to P1
H12 = bearing from P1 to P2
A = fmod( H12-H01+360, 360 )
|P2-P1| <= MaxEdgeLength
Then you set
P0 <- P1
P1 <- P2
and repeat until you get back where you started.
This is still O(N^2) so you'll want to sort your pointlist a little. You can limit the set of points you need to consider at each iteration if you sort points on, say, their bearing from the city's centroid.
Good question! I haven't tried this out at all, but my first shot would be this iterative method:
Create a set N ("not contained"), and add all points in your set to N.
Pick 3 points from N at random to form an initial polygon P. Remove them from N.
Use some point-in-polygon algorithm and look at points in N. For each point in N, if it is now contained by P, remove it from N. As soon as you find a point in N that is still not contained in P, continue to step 4. If N becomes empty, you're done.
Call the point you found A. Find the line in P closest to A, and add A in the middle of it.
Go back to step 3
I think it would work as long as it performs well enough — a good heuristic for your initial 3 points might help.
Good luck!
You can do it in QGIS with this plug in;
https://github.com/detlevn/QGIS-ConcaveHull-Plugin
Depending on how you need it to interact with your data, probably worth checking out how it was done here.
As a wildly adopted reference, PostGIS starts with a convexhull and then caves it in, you can see it here.
https://github.com/postgis/postgis/blob/380583da73227ca1a52da0e0b3413b92ae69af9d/postgis/postgis.sql.in#L5819
The Bing Maps V8 interactive SDK has a concave hull option within the advanced shape operations.
https://www.bing.com/mapspreview/sdkrelease/mapcontrol/isdk/advancedshapeoperations?toWww=1&redig=D53FACBB1A00423195C53D841EA0D14E#JS
Within ArcGIS 10.5.1, the 3D Analyst extension has a Minimum Bounding Volume tool with the geometry types of concave hull, sphere, envelope, or convex hull. It can be used at any license level.
There is a concave hull algorithm here: https://github.com/mapbox/concaveman

Resources