Unordered cloud point of polygon contour to polygon - python

Dear Stackoverflow community,
I have contours of irregular polygons as unordered datapoints (like on the figure here: https://s16.postimg.org/pum4m0pn9/figure_4.png), and I am trying to order them (ie. to create a polygon).
I cannot use the convex hull envelope because of the non convex shape of the polygon. I cannot ase a minimum distance criterion because some points of other parts of the contour lie closer (example: point A has to be joined with B, but is closer to C). I cannot use a clockwise ordering because of the irregular shape of the contour.
Do anyone knos a way to implement (preferentially in Python) an algorithm that would reorder the datapoints from a starting point?

look here finding holes in 2D point set for some ideas on how to solve this
I would create point density map (similar to above linked answer)
create list of all lines
so add to it all possible combination of lines (between close points)
not intersecting empty area in map
remove all intersecting lines
apply closed loop / connectivity analysis on the lines
then handle the rest of unused points
by splitting nearest line by them ...
depending on you map grid size and point density you may need to blend/smooth the map to cover gaps
if grid size is too big then you can miss details like on the image between points A,C
if it is too small then significant gaps may occur near low density areas
But as said this has more then one solution so you need to tweak this a bit to make the wanted output perhaps some User input for shaking the solution a bit until wanted solution found...
[notes]
you can handle this as more covex polygons ...
add line only if winding rule met
stop when no more lines found
start again with unused points
and in the end try to connect found non closed polygons ...

Related

Using Python to get unblocked area

I have a rather complicated problem. Suppose I have the shape below. You can think of the red dot as a person and the pointy shape inside the big polygon as an obstacle. My goal is to compute the total unblocked vision of the person inside the big polygon, which is the area of the polygon minus the red shaded area.
I want to write a function that takes in the coordinates of the person, the coordinates of the ordered vertices of the obstacle(s) and those of the ordered vertices of the big polygon, and returns the area of the unblocked vision.
I have tried multiple things, and I'm aware of the shoelace algorithm, but the only way that I can come up with is through monte carlo. Can I get a hint on a more intelligent and efficient way to compute the area in a closed-form way?
I think your problem is solved by finding the "Visibility polygon".
https://en.wikipedia.org/wiki/Visibility_polygon
You can use https://karlobermeyer.github.io/VisiLibity1/ library to compute the visibility area.
The first task is to get the two extreme lines of sight from the person.
A simple brute-force checking. I doubt there's a better method, unless you need this calculation at each frame. (See (a) below).
Calculate the angle (relative to X-axis, or whatever) of the line person-to-obstacle_vertex for every vertex.
Find the lowest and highest values. This can be tricky if the obstacle may somehow warp around the person.
So yo can calculate the angle of each pair of sight lines (combinatory issue), an get that with maximum angle. For this job use the Dot-Product.
The second task is to get the area of the shaded region.
You need to get the two intersections of the sight lines and the outer polygon. And then build a list of vertices of the polygon between the two intersections. Add these intersections to that list.
The area can be calculated as the sum of area of triangles, those from the person to each edge (two points in that list). While you have all coordinates, an easier way is to use the Shoelace Algorithm.
(a) If the obstacle has thousands of vertices and the person moves continuosly I'd try to reduce the number of pairs to check. You can mantain a list of shown/hidden vertices, and when the person moves check the last two used vertices and their neighbours, until you get a new couple of ending vertices.

How to select the minimal set of circles that covers another circle?

I'm looking for some solutions that, given a set S of circles with 2D-center points and radii, returns a minimal sub-set M in S that covers entirely a specific circle with 2d-center point and radius. This last circle is not in S.
I've chosen circles, but it doesn't matter if we change them to squares, hexagons, etc.
You have two distinct problems: you need to turn the geometric problem into a combinatoric problem, and then you need to solve the combinatoric problem. For the latter, you are looking at a minimum set cover problem, and there should be plenty of literature on that. Personally I like Knuth's Dancing Links approach to enumerate all solutions of a set cover, but I guess for a single minimal solution you can do better. A CPLEX formulation (to match your tag) would use a binary variable for each row, and a ≥1 constraint for each column.
So now about turning geometry into combinatorics. All the lines of all your circles divide the plane into a bunch of areas. The areas are delimited by lines. Of particular relevance are the points where two or more circles meet. The exact shape of the line between these points is less relevant, and you might imagine pulling those arcs straight to come up with a more classical planar graph representation. So compute all the pair-wise intersections between all your circles. Order all intersections of a single circle by angle and connect them with graph edges in that order. Do so for all circles. Then you can do a kind of bucket fill to determine for each circle which graph faces are within and which are outside.
Now you have your matrix for the set cover: every graph face which is inside the big circle is a column you need to cover. Every circle is a row and covers some of these faces, and you know which.

Sort points in 2D space to make a spline

I have a sequence of points which are distributed in 2D space. They represent a shape but they are not ordered. So, I can plot them as points to give an idea of the shape, but if I plot the line connecting them, I miss the shape because the order of points is not the right order of connection.
I'm wondering, how can I put them in the right order such that, if I connect them one by one in sequence, I get a spline showing the shape they represent? I found and tried the convex hull in Matlab but with no results. The shape could be complex, for example a star and with convex hull I get a shape that is too much simplified (many points are not taken into account).
Thanks for help!
EDIT
Could be everything the image. I've randomly created one to show you a possible case, with some parts that are coming into the shape, and also points can have different distances.
I've tried with convex hull function in Matlab, that's what I get. Every time the contour have a "sharp corner", I miss it and the final shape is not what I'm looking for. Also, Matlab function has no parameter to set to change convex hull result (at least I can't see anything in the help).
hull = convhull(coords(:,1),coords(:,2));
plot(coords(hull,1),coords(hull,2),'.r');
You need to somehow order your points, so they can be in a sequence; in the case of your drawing example, the points can likely be ordered using the minimal distance, to the next -not yet used- point, starting at one end (you'll probably have to provide the end).
Then you can draw a spline, maybe using Chaikin's algorithm for curves that will locally approximate a bezier curve.
You need to start working on this, and post another question with your code, if you are having difficulties.
Alpha shapes may perform better than convexhulls for this problem. Alpha shapes will touch all the points in the exterior of a point cloud, even can carve out holes.
But for complicated shape reconstruction, I would recommend you to try a beta-skeleton bsed approach discussed in https://people.eecs.berkeley.edu/~jrs/meshpapers/AmentaBernEppstein.pdf
See more details on β-Skeleton at https://en.wikipedia.org/wiki/Beta_skeleton
Quote from the linked article:
The circle-based β-skeleton may be used in image analysis to reconstruct the shape of a two-dimensional object, given a set of sample points on the boundary of the object (a computational form of the connect the dots puzzle where the sequence in which the dots are to be connected must be deduced by an algorithm rather than being given as part of the puzzle).
it is possible to prove that the choice β = 1.7 will correctly reconstruct the entire boundary of any smooth surface, and not generate any edges that do not belong to the boundary, as long as the samples are generated sufficiently densely relative to the local curvature of the surface
Cheers

Corner detection in an array of points

I get a pointcloud from my lidar which is basically an numpy array of points in 2D cartesian coordinates. Is there any efficient way to detect corners formed by such 2D points?
What I tried until now was to detect clusters, then apply RANSAC on each cluster to detect two lines and then estimate the intersection point of those two lines. This method works well when I know how many clusters I have (in this case I put 3 boxes in front of my robot) and when the surrounding of the robot is free and no other objects are detected.
What I would like to do is run a general corner detection, then take the points surrounding each corner and check if lines are orthogonal. If it is the case then I can consider this corner as feature. This would make my algorithm more flexible when it comes to the surrounding environment.
Here is a visualization of the data I get:
There are many many ways to do this. First thing I'd try in your case would be to chain with a reasonable distance threshold for discontinuities, using the natural lidar scan ordering of the points. Then it become a problem of either estimating local curature or, as you have done, grow and merge linear segments.

Getting approximate vertices of curved-edge closed shapes (for calculating centroid and other properties)

I'm looking to draw outlines of 2D-closed irregular shapes with curved edges, and then compute both (a) the center of gravity (centroid) of the shape's area, and (b) the center of gravity of the shape's perimeter (i.e. the centroid of, e.g., a wire wrapped tightly around the outside of the shape). I have a late-beginner's level proficiency with Python and Matlab.
(a) and (b) are easy enough given a polygon's vertices: the centroid of a polygon's area is given by the equation here, and the centroid of a polygon's perimeter is just the average of all the line segments' midpoints weighted by the line segments' lengths. I've already written some functions to do this.
The trouble I'm having is getting/approximating those vertices from any of the ways I know how to draw a closed shape with curved edges. The best solution I've come up with so far is to use something like this matplotlib-based script to draw the curvy shape, and then call path.to_polygons(), which converts Path objects to polygons — but does so with surprisingly low resolution, such that the resulting approximation is quite poor (and too poor for my purposes — I'd like to compute those centroids fairly precisely).
So, I'm looking to either (i) find some way to increase the resolution of .to_polygons (about 10-fold), which would be satisfactory for my purposes, or (ii) try some new strategy entirely. One option would be to draw the shapes using something like Adobe Illustrator and then get an approximation of their vertices via some plugin or maybe an image processing toolbox (but I have no clue how to do either of those things). Another would be to draw the shape using some toolbox/library that already has built-in functions for finding the centroids of areas and perimeters (I've seen some having the former, but none with the latter). But I'm sure there are many other options out there that I haven't considered.

Categories