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

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.

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.

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.

Smallest circles enclosing points with minimized cost

I am trying to find the smallest circles enclosing points using a hierarchical search (in a tree). I searched a lot and I seem to only find smallest enclosing circle (singular) algorithms online. This is for a university class so I am asking for possible solutions and ideas more than actual code.
My problem is that I have a formula that involves two constants and the radius of a circle to compute its cost and I need to minimise the total cost. This means that for a set of points (x,y), I could find one circle enclosing all points, or multiples circles, each enclosing a part of the points, depending on the cost of each circle.
As an example, if the formulae is 1+2*radius**2, my answer will surely have multiple small circles. All points must be in a circle at the end.
My goal is to use a graph search algorithm like a*, branch and bound or breadth first and build a tree using a state and its possible actions.
I am currently trying to write my possible actions as adding a circle, removing a circle and change a circle's radius. To limit compute time, I decided to only try those actions on positions that are between two points or between two sets of points (where the center of my circles could be). But this algorithm seems to be far from optimal. If you have any ideas, it would really help me.
Thanks anyway for your help.
If the question is unclear, please tell me.
I'm going to focus on finding optimal solutions. You have a lot more options if you're open to approximate solutions, and I'm sure there will be other answers.
I would approach this problem by formulating it as an integer program. Abstractly, the program looks like
variable x_C: 1 if circle C is chosen; 0 if circle C is not chosen
minimize sum_C cost(C) * x_C
subject to
for all points p, sum_{C containing p} x_C >= 1
for all circles C, x_C in {0, 1}.
Now, there are of course infinitely many circles, but assuming that one circle that contains strictly more area than another costs more, there are O(n^3) circles that can reasonably be chosen, where n is the number of points. These are the degenerate circles covering exactly one point; the circles with two points forming a diameter; and the circles that pass through three points. You'll write code to expand the abstract integer program into a concrete one in a format accepted by an integer program solver (e.g., GLPK) and then run the solver.
The size of the integer program is O(n^4), which is prohibitively expensive for your larger instances. To get the cost down, you'll want to do column generation. This is where you'll need to figure out your solver's programmatic interface. You'll be looking for an option that, when solving the linear relaxation of the integer program, calls your code back with the current price of each point and expects an optional circle whose cost is less than the sum of the prices of the points that it encloses.
The naive algorithm to generate columns is still O(n^4), but if you switch to a sweep algorithm, the cost will be O(n^3 log n). Given a pair of points, imagine all of the circles passing by those points. All of the circle centers lie on the perpendicular bisector. For each other point, there is an interval of centers for which the circle encloses this point. Compute all of these event points, sort them, and then process the events in order, updating the current total price of the enclosed points as you go. (Since the circles are closed, process arrivals before departures.)
If you want to push this even further, look into branch and price. The high-level branching variables would be the decision to cover two points with the same circle or not.

Unordered cloud point of polygon contour to polygon

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 ...

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