Is there a way to compute the empty area between a group of touching polygons? - algorithm

Given a bunch of convex polygons layed out like a house truss, is there a way to compute the empty area, or get a polygon for each of those "holes" between the polygons?
I tried starting from any given polygon and then finding the intersections between some of the lines of the polygons and somehow I'm stuck at how to properly select which lines to use for the intersections.
I then tried to verify for a clockwise detection of the area but it seem that my algo for determining the CW/CCW of two lines does not work as, I think, it act as if the lines have the same origin instead of being "in sequence" from each other.

According to comments the solution is quite easy
1.prepare data
represent your mesh as table of points and remove redundant points (point = x,y,z... + int cnt=0; )
and table of lines (line = 2 * index of point from point table + bool deleted=false)
while creating table of lines for each used point increment its cnt counter
2.remove redundant lines (join border between thick lines)
find all lines that are overlapping and lie on the same line
they have the same or opposite direction
remove the shorter one and dissect the bigger one and update all tables accordingly (also point cnt !!!)
after this find all lines between points used booth more than twice
delete them ...
3.find all closed loops
something like this:
1.create list of polygons
polygon is list of point indexes
2.take any undeleted line
if found add new polygon to list and
copy its points to polygon
flag line as deleted
if not found stop
3.find line with point matching last polygon point
add the other point to polygon
flag line as deleted
repeat bullet 2 until there is no such line found
4.goto 1
4.now found polygon with the biggest bounding box
this polygon is the outer perimeter
so delete it
also you can draw it by different color for debugging purposes
5.now sum the rest
all remaining polygons are the holes
so triangulate them
and sum all triangle areas by basic math formula ...
also you can draw them by other different color for debugging purposes

This is not a straightforward problem, as the complete geometry needs to be computed incrementally, using some intersection points and/or chamfering/trimming rules.
I imagine two approaches:
1) build yourself a toolbox of the required geometric operations (using analytic geometry), among which segment/segment intersection and probably a few others (which will map to the truss design rules); using this toolbox, construct all required polygon vertices "by hand", based on the picture; lastly, compute the area of the polygonal holes with the general formula: http://en.wikipedia.org/wiki/Polygon#Area_and_centroid.
2) use a ready-made polygon manipulation library like Clipper (http://www.angusj.com/delphi/clipper.php), which will allow you to draw the logs without much care about the trimmings at endpoints (you will perform a union of rectangles and get a polygon with holes).
After my understanding of your question, the first approach is better.
UPDATE:
If what you have is a set of polygons corresponding to every log, the answer is different:
If you only care about the total area of the voids, compute the area of the outer outline and deduce the areas of every log.
And if you need the areas of individual holes, then use the second approach: perform the union of the polygons and query for the holes.

Related

CGAL arrangements: compute the ordered intersection of a polyline with a grid

Given a general polyline and an orthogonal grid, I would like to compute a simpler polyline whose vertices lie on the grid edges/vertices. This can look like this:
Left: A dense polyline as input, Right: A coarser polyline whose vertices lie on the intersection of the input polyline with the grid edges/vertices
(Sorry about the link to the image, but stack overflow apparently doesn't allow me to embed pictures before getting 10 credit points).
The grid is always orthogonal but its vertices do not necessarily have integer coordinates as some x or y lines might have coordinates defined by a previous geometric intersection computation. The initial curve can be represented as a polyline (though it would be nice to have also bezier curve support), not necessarily x-monotone, and it might intersect the grid also along whole edges.
My first thought was to call CGAL::compute_subcurves(..) with the grid lines and the curve I'm adding. I was hoping to get back a list of polylines, each composed of maximal multiple segments inside a face of the original grid. In practice even if the input is composed of polylines and the output of monotone polylines, I get back a list of separated segments. These include also the grid segments and also the polyline segments, and these are not ordered by "walking on the curve segments" as needed to compute the ordered interesection points. If they would have been ordered, a solution would be to iteratively go over them and check which one intersects the original grid, and then save the points.
Another option I thought of is to start with an arrangement of the grid lines, incrementally add polyline segements and have a notification mechanism notifying me on new edges that are pairwise disjoint in their interior, but in the case an edge of the intersected polylines is an original edge of the grid I won't get a notification and I'll miss it. Incrementally adding segments and checking for collisions also doesn't seem to be straightforward as the arrangement API do_intersect(..) seems to return at most a single point, while a given segment of the input polyline might easily intersect two grid lines next to a corner or even lie entirely on a grid segment.
I'm probably missing some simple solution. Can someone give me a pointer, or some api call that might help here?
Edit: There might have been a confusion. The grid is orthogonal but not necessarily regular and might have coordinates that could not globally scale to integers such as here.
Use Arrangement_with_history_2 (instead of Arrangement_2); see https://doc.cgal.org/latest/Arrangement_on_surface_2/classCGAL_1_1Arrangement__with__history__2.html. After you compute the arrangement, you can use point location to locate the end points of your polylines in the arrangement. Then, for each one, you can easily follow the original curve. If you are concerned with performance, you can try inserting (at least) the grid lines incrementally. Another option is to extend the halfedge records and insert the grid lines and each polyline separately. With the appropriate observer, you can mark the generated halfedges that correspond to a given polyline uniquely. I think you can even save the extra point location, by locating one of the two end points of a polyline before inserting it, and then provide the resulting location to the (incremental) insertion function.

Randomly placing a polygon inside of polygon

I have two polygons defined as a series of 2D floating point values. They are not guaranteed to be concave or convex. They do not cross over themselves. They cannot rotate. I want to place one randomly inside the other should it be possible based on it's size. The main problem is efficiency. I have to do this about 200 or so times in a few seconds.
I've been looking into this for a couple of days now, and have made no discernible headway. Any leads would be appreciated.
Disclaimer: If you are trying to pack multiple polygons inside a bigger polygon then I think, this problem is NP hard so it is unlikely that an efficient and exact algorithm can be developed to solve this problem. The polygon can continuously translate and rotate in a plane, which means the placements may be infinite and this makes the solution space of the problem also infinite. If you are just trying to find if the smaller polygon can fit inside the bigger one, I am short of an efficient answer, but as you have asked - "Any leads would be appreciated" - here is one.
Let the bigger polygon be B and smaller polygon (the one to be inserted) is S. B has a total of b points and S has a total of s points.
The image below shows a Bounding Box and a Minimum Bounding Rectangle. We use this to get the Fast Fail Filter (very simple idea... defined in next para). The box (a) shown below is faster to compute while box (b) is more accurate for filtering. Draw that box which gives better return on investment for your case. Though in the figure below they both are bounding an ellipse instead of a polygon but you get the idea.
(Image taken from: http://portal.ku.edu.tr/~cbasdogan/Tutorials/imageU21.JPG)
Crux: If any line of B intersects with any line of S, or if all lines of S are outside B, B cannot take S in.
Fast fail filter: Get the bounding rectangles of B and S. If you are not able to place the bounding rectangle of S inside the bounding rectangle of B, then you cannot place the polygon S inside polygon B. This way you fail faster if there is no chance of B to enclose S. Following image illustrates the three cases.
(Image taken from: http://www.cs.berkeley.edu/~ug/slide/pipeline/assignments/as4/figures/boundcull.gif)
Preprocessing: Determine the equation of lines that form B. Store them in a HashMap<<Point, Point>, Line> for a step that will be done later. You can uniquely define the line by slope m and intercept c and the end points of your line are going to be the key (<Point, Point>) of the HashMap.
The Algorithm:
For every S which has passed the above filter:
Read the points of S and determine the lines that form S
For every line of S, see if it intersects with any line of B† (they are stored in the HashMap already)
If there is no intersection, S is inside B and all you have to do is just draw the lines without any worry of intersection.
In the worst case, the complexity of this algorithm will be O(bs) for drawing each polygon.
†This step is written brute-force to keep the algo easy to understand. Otherwise a critical optimization that will give result faster is possible here. You can filter lines of B. You need not consider a line of B for intersection with S if the endpoints of the line of B are to the left of the leftmost point of S, or to the right of the rightmost point of S or above S or below S. This can save a lot of calculations.
If the other answer here is useful, this is an addendum to it. It shows another approach to see if smaller polygon is inside bigger one.
To test a polygon containment, you see if all the edges of the polygon are contained. To test all the edges, you test if all the points of every edge are contained.
Densify the smaller polygon by adding vertices between existing vertices. The image below shows densification of a line.
Now for the densified polygon, test if its points are all lying within the outer polygon. This test can be done by drawing lines from the point emanating to infinity on both sides and then counting how many times that line intersected with the bigger polygon.
If all points are within, then the polygon is within.
First Image source.
Second Image source.

Split Polygon into Small Polygons by contain 1 point each

I am not sure if this algorithm exists, much appreciated if someone can provide me the just the Algorithm's name, then I can Google it up.
Basically let's say I have N Points within a polygon (both convex and concave), and I would like to have a way/algorithm to split this polygon into N polygons, that each of these N polygon contains 1 point only.
Thanks.
I'm reluctant to post this as an answer, but it won't fit in the comments.
In the GIS world, this is sometimes referred to as voronoi algorithm. Most GIS tools, like ESRI ArcMap can generate veronoi polgons from a set of points. For your use case I think you can create a veronoi polygon set from your points using the package in the link below (it it's compatible), then take that output, and do some fancy spatial joining to replace your polygon with multiple polygons.
Here is a link to the wikipedia page describing the concept
http://en.wikipedia.org/wiki/Voronoi_diagram
also delaunoy triangulation is another approach you might want to look at
http://www.spatialdbadvisor.com/oracle_spatial_tips_tricks/283/application-of-delaunay-triangulation-and-inverse-distance-weighting-idw-in-oracle
here's another link that has the st_veronoi function mentioned with a link to the above.
http://www.spatialdbadvisor.com/source_code/223/geoprocessing-package-documentation
the basis of this package appears to be java JTS, which is apparently being compiled within java stored procs in oracle. JTS is the "standard" for geometry operations in Java. I think I'm going to give it a try myself.
Bear in mind, I have only done this using a tool like ArcGIS, not using anything i mentioned above.... so HTH and I'm not leading you down a rat hole.
I can't give you a name but can describe three different algorithms
I'm going to call the set of points you are given "targets" to simplify my solution beacuse I want to call arbitrary locations on the plain "points":
You're going to be doing quite a lot of arithmetic on 2-vectors
my algorithm to partition the polygon is simple: find the nearest target.
the set of points nearest to any target will have straight edges. the vertices will be equidistant to three (or more) of the targets (or be where the edge intersects the boundary polygon),
your algorithm might go like this:
cross the original set of targets with itself twice to produce a set of triples rejecting those that don't copntain three distinct targets.
for each set of three find the point equidistant from all three targets if that point is closer to any other target reject it.
eventually you'll have (at most) n-2 vertices, then you just need to work out how the edges join up. which you can do this by looking at which targets spawned each vertex.
now you need to add the edges which end at infinity take a cross of targets and itself
and find the halfway points between each pair of targets, any points that don't have eactly two nearest targets can be rejected, each of these ponts represents a line (perpendicular bisector) and it will end at one a vertex or at infinity
finally trim the map using the boundary polygon, you may want to drop one of the edges from any fragment that does not contain a target
another way
on the other hand you could use a fractal partitioning scheme to divide the polygon into chunks dividing each chunk smaller until it contains a single polygon, the results will be less aesthetically pleasing but looks weren't a design requirement AFAICT.
eg the fractal mapping used for IP addresses.
then having converted coordinates into numbers into divide this into chunks at convenient points, (IE by dropping unneeded trailing 1's)
another way
measure the extent of set of targets if it is wider than it is high draw a line vertically dividing it in half else draw horizontally.
if the lit hots one of the targets adjust it so that it misses.
repeat for each half until the extet is zero (which means a single point)
You didn't mention any restriction on the shapes of the containing polygons, so I'll assume you don't care. I'll also assume we're in two dimensions, though this can easily be extended. The idea is simple: create new polygons by slicing up your initial polygon with vertical strips halfway between points adjacent on the x-axis. In cases where points share an x-coordinate, split the strip containing them with vertical slices between the points on the y-axis.
Use markg's suggestions if long, thin slices don't work for you.

Find out how to flood fill a polygon with the smallest number of vector lines

Say I have a vector polygon with holes. I need to flood fill it by drawing connected segments. Of course, since there are holes, I can't fill it using a single continous polyline: I'll need to interrupt my path sometimes, then move to an area which was skipped and start another polyline there.
My goal is to find a set of polylines needed to fill the whole polygon. Better if I can find the smallest set (that is, the way I can fill the polygon with the minimum number of interruptions).
Bonus question: how could I do that for partial density fills? Say, I don't want to fill at 100% density but I want a 50% (this will require that fill lines, supposing they're parallel each other and have a single-unit width, are put at a distance of two units).
I couldn't find a similar question here, although there are many related to flood-fill algorithms.
Any ideas or pointers?
Update: this picture from Wikipedia shows a good hypotetical flood path. I believe I could do that using a bitmap. However I've got a vector polygon. Should I rasterize it?
I'm assuming here that the distance between lines is 1 unit.
A crude implementation, with no guarantee to find the minimum number of polyline, is:
Start with an empty set of polylines.
Determine minx and maxx of the polygon.
Loop x from xmin to xmax, with a step of 1. Line L is the vertical line at x.
Intersect vertical line L with your polygon (quick algorithm, easy to find). That will give you a set of segments: {(x,y1)-(x,y2)}.
For all polylines, and all segments, merge segment + end of polylines (see note 1 below). When you merge a segment and a polyline, append a small stretch at the end of the polyline (to joint it to the segment), and the segment itself. For all segments that you can't merge using that, add a new polyline in the global set.
At the end, try to merge again polylines if possible (ends close together).
Optimal algorithm for merging new segments to existing polylines should be easy to find (hashing on y), or a brute force algorithm may suffice:
number of new segments per line scan should not be too high if your polygons do not have zillions of holes,
number of global polylines at every step should not be too large,
you compare only with the end segment of each polylines, not the whole of it.
Added note (1): To cover the case where your polygon has nearly-vertical edges, the merge process should not look only at y-delta, but allow a merge if any two y range overlaps (that means end of polyline y-range overlap segment y-range).

Random but Regular Polygon Generator

I'm looking for a way to generate a set of random sided, but regular, polygons, inside a given rectangle or sector of a circle. To better explain, my given 2d space should have a random arrangement of regular polygons with various numbers of sides, so, e.g, if two hexagons are separated by a rectangle equal in length to their sides, the whole space cannot be filled with only more hexagons, some triangles may be required, etc.
I'm looking for one segment of a sort of kaleidoscope effect.
You are looking for tiling algorithms. See, for example, Penrose Tiler and Tilings and Tesselations pages for a start.
Another approach, I can think of:
First decide on how many objects you want. Say 'N'
Randomly Select 3 Points in your 2D Space.
Make use of 3 points to get a virtual triangle.
Now Select another point such a way that the point is outside the virtual triangle. Now form another virtual triangle by joining this point to 2 points from previous virtual triangle and then recurisevely form "N" virtual trianlges. Incase virtual triangles crossed, then you ignore the bigger trianlge and take triangles which had formed because of crossing points as new virtualtriangles
Now Generate a INSCRIBED Circle virtually to all virtual triangles which will never be able to intersect another virtual triangle since all virtual triangles are formed by without crossing any of the triangles as expalined above.
Make use of virtual circles to form any number of regular sides by dividing 360 degress to equal slices.
Now You can draw random regular polygons
I'm not sure I understand the requirements, but you can generate random regular polygons by randomly generating the following numbers:
radius (0 to whatever)
x and y of center (must be within radius of edges)
number of points (3 to whatever)
rotation (0 to 360)
To prevent overlapping, you can test each new polygon against each existing polygon and reject the new one if the distance between the centers is less than the sum of the radii.
Drawing the polygons is then a simple trig exercise.
See: "Heuristics for Generation of Random Polygons"
Generate N random points on a plane and extract the convex hull of the object (that is, if all polygons should be convex).
You can trivially reject before generating the convex hull if one of the points is inside another polygon. If it's not you still need to test the generated polygon against other polygons near it. (If you need to do this often, a spatial data structure is probably a something to look into).

Resources