The search for a set of points with a minimum sum of lengths to rectangles. What is the algorithm? - c++

Good day.
I have the task of finding the set of points in 2D space for which the sum of the distances to the rectangles is minimal. For example, for two rectangles, the result will be the next area (picture). Any point in this area has the minimum sum of lengths to A and B rectangles.
Which algorithm is suitable for finding a region, all points of which have the minimum sum of lengths? The number of rectangles can be different, they are randomly located. They can even overlap each other. The sides of the rectangles are parallel to the coordinate axes and cannot be rotated. The region must be either a rectangle or a line or a point.

Hint:
The distance map of a rectangle (function that maps any point (x,y) to the closest distance to the rectangle) is made of four slanted planes (slope 45°), four quarter of cones and the rectangle itself, which is at ground level, forming a continuous surface.
To obtain the global distance map, it "suffices" to sum the distance maps of the individual rectangles. A pretty complex surface will result. Depending on the geometries, the minimum might be achieved on a single vertex, a whole edge or a whole face.
The construction of the global map seems more difficult than that of a line arrangement, due to the conic patches. A very difficult problem in the general case, though the axis-aligned constraint might ease it.

Add on Yves's answer.
As Yves described, each rectangle 'divide' plane into 9 parts and adds different distance method in to the sum. Middle part (rectangle) add distance 0, side parts add coordinate distance to that side, corner parts add point distance to that corner. With that approach plan has to be divided into 9^n parts, and distance sum is calculated by adding appropriate rectangle distance functions. That is feasible if number of rectangles is not too large.
Probably it is not needed to calculate all parts since it is easy to calculate some bound on part min value and check is it needed to calculate part at all.
I am not sure, but it seems to me that global distance map is convex function. If that is the case than it can be solved iteratively by similar idea as in linear programming.

Related

Fit rectangle around points

I'm trying to fit a rectangle around a set of 8 2D-Points, while trying to minimize the covered area.
Example:
The rectangle may be scaled and rotated. However it needs to stay a rectangle.
My first approach was to brute force each possible rotation, fit the rectangle as close as possible, and calculate the covered area. The best fit would be then the rotation with the lowest area.
However this does not really sound like the best solution.
Is there any better way for doing this?
I don't know what you mean by "try every possible rotation", as there are infinitely many of them, but this basic idea actually yields a very efficient solution:
The first step is to compute the convex hull. How much this actually saves depends on the distribution of your data, but for points picked uniformly from a unit disk, the number of points on the hull is expected to be O(n^1/3). There are a number of ways to do that:
If the points are already sorted by one of their coordinates, the Graham scan algorithm does that in O(n). For every point in the given order, connect it to the previous two in the hull and then remove every concave point (the only candidate are those neighboring the new point) on the new hull.
If the points are not sorted, the gift-wrapping algorithm is a simple algorithm that runs at O(n*h). For each point on the hull starting from the leftmost point of the input, check every point to see if it's the next point on the hull. h is the number of points on the hull.
Chen's algorithm promises O(n log h) performance, but I haven't quite explored how it works.
another simle idea would be to sort the points by their azimuth and then remove the concave ones. However, this only seems like O(n+sort) at first, but I'm afraid it actually isn't.
At this point, checking every angle collected thus far should suffice (as conjenctured by both me and Oliver Charlesworth, and for which Evgeny Kluev offered a gist of a proof). Finally, let me refer to the relevant reference in Lior Kogan's answer.
For each direction, the bounding box is defined by the same four (not necessarily distinct) points for every angle in that interval. For the candidate directions, you will have at least one arbitrary choice to make. Finding these points might seem like an O(h^2) task until you realise that the extremes for the axis-aligned bounding box are the same extremes that you start the merge from, and that consecutive intervals have their extreme points either identical or consecutive. Let us call the extreme points A,B,C,D in the clockwise order, and let the corresponding lines delimiting the bounding box be a,b,c,d.
So, let's do the math. The bounding box area is given by |a,c| * |b,d|. But |a,c| is just the vector (AC) projected onto the rectangle's direction. Let u be a vector parallel to a and c and let v be the perpendicular vector. Let them vary smoothly across the range. In the vector parlance, the area becomes ((AC).v) / |v| * ((BD).u) / |u| = {((AC).v) ((BD).u)} / {|u| |v|}. Let us also choose that u = (1,y). Then v = (y, -1). If u is vertical, this poses a slight problem involving limits and infinities, so let's just choose u to be horizontal in that case instead. For numerical stability, let's just rotate 90° every u that is outside (1,-1)..(1,1). Translating the area to the cartesian form, if desired, is left as an exercise for the reader.
It has been shown that the minimum area rectangle of a set of points is collinear with one of the edges of the collection's convex hull polygon ["Determining the Minimum-Area Encasing Rectangle for an Arbitrary Closed Curve" [Freeman, Shapira 1975]
An O(nlogn) solution for this problem was published in "On the computation of minimum encasing rectangles and set diameters" [Allison, Noga, 1981]
A simple and elegant O(n) solution was published in "A Linear time algorithm for the minimum area rectangle enclosing a convex polygon" [Arnon, Gieselmann 1983] when the input is the convex hull (The complexity of constructing a convex hull is equal to the complexity of sorting the input points). The solution is based on the Rotating calipers method described in Shamos, 1978. An online demonstration is available here.
They first thing that came to mind when I saw this problem was to use principal component analysis. I conjecture that the smallest rectangle is the one that satisfies two conditions: that the edges are parallel with the principal axes and that at least four points lie on the edges (bounded points). There should be an extension to n dimensions.

Detecting set of planes from point cloud

I have a set of point cloud, and I would like to test if there is a corner in a 3D room. So I would like to discuss my approach and if there is a better approach or not in terms of speed, because I want to test it on mobile phones.
I will try to use hough tranform to detect lines, then I will try to see if there are three lines that are intersecting and they make a two plane that are intersecting too.
If the point cloud data comes from a depth sensor, then you have a relatively dense sampling of your walls. One thing I found that works well with depth sensors (e.g. Kinect or DepthSense) is a robust version of the RANSAC procedure that #MartinBeckett suggested.
Instead of picking 3 points at random, pick one point at random, and get the neighboring points in the cloud. There are two ways to do that:
The proper way: use a 3D nearest neighbor query data structure, like a KD-tree, to get all the points within some small distance from your query point.
The sloppy but faster way: use the pixel grid neighborhood of your randomly selected pixel. This may include points that are far from it in 3D, because they are on a different plane/object, but that's OK, since this pixel will not get much support from the data.
The next step is to generate a plane equation from that group of 3D points. You can use PCA on their 3D coordinates to get the two most significant eigenvectors, which define the plane surface (the last eigenvector should be the normal).
From there, the RANSAC algorithm proceeds as usual: check how many other points in the data are close to that plane, and find the plane(s) with maximal support. I found it better to find the largest support plane, remove the supporting 3D points, and run the algorithm again to find other 'smaller' planes. This way you may be able to get all the walls in your room.
EDIT:
To clarify the above: the support of a hypothesized plane is the set of all 3D points whose distance from that plane is at most some threshold (e.g. 10 cm, should depend on the depth sensor's measurement error model).
After each run of the RANSAC algorithm, the plane that had the largest support is chosen. All the points supporting that plane may be used to refine the plane equation (this is more robust than just using the neighboring points) by performing PCA/linear regression on the support set.
In order to proceed and find other planes, the support of the previous iteration should be removed from the 3D point set, so that remaining points lie on other planes. This may be repeated as long as there are enough points and best plane fit error is not too large.
In your case (looking for a corner), you need at least 3 perpendicular planes. If you find two planes with large support which are roughly parallel, then they may be the floor and some counter, or two parallel walls. Either the room has no visible corner, or you need to keep looking for a perpendicular plane with smaller support.
Normal approach would be ransac
Pick 3 points at random.
Make a plane.
Check if each other point lies on the plane.
If enough are on the plane - recalculate a best plane from all these points and remove them from the set
If not try another 3 points
Stop when you have enough planes, or too few points left.
Another approach if you know that the planes are near vertical or near horizontal.
pick a small vertical range
Get all the points in this range
Try and fit 2d lines
Repeat for other Z ranges
If you get a parallel set of lines in each Z slice then they are probably have a plane - recalculate the best fit plane for the points.
I would first like to point out
Even though this is an old post, I would like to present a complementary approach, similar to Hough Voting, to find all corner locations, composed of plane intersections, jointly:
Uniformly sample the space. Ensure that there is at least a distance $d$ between the points (e.g. you can even do this is CloudCompare with a 'space' subsampling)
Compute the point cloud normals at these points.
Randomly pick 3 points from this downsampled cloud.
Each oriented point (point+plane) defines a hypothetical plane. Therefore, each 3 point picked define 3 planes. Those planes, if not parallel and not intersecting at a line, always intersect at a single point.
Create a voting space to describe the corner: The intersection of the 3 planes (the point) might a valid parameterization. So our parameter space has 3 free parameters.
For each 3 points cast a vote in the accumulator space to the corner point.
Go to (2) and repeat until all sampled points are exhausted, or enough iterations are done. This way we'll be casting votes for all possible corner locations.
Take the local maxima of the accumulator space. Depending on the votes, we'll be selecting the corners from intersection of the largest planes (as they'll receive more votes) to the intersection of small planes. The largest 4 are probably the corners of the room. If not, one could also consider the other local maxima.
Note that the voting space is a quantized 3D space and the corner location will be a rough estimate of the actual one. If desired, one could store the planes intersection at that very location and refine them (with iterative optimization similar to ICP or etc) to get a very fine corner location.
This approach will be quite fast and probably very accurate, given that you could refine the location. I believe it's the best algorithm presented so far. Of course this assumes that we could compute the normals of the point clouds (we can always do that at sample locations with the help of the eigenvectors of the covariance matrix).
Please also look here, where I have put out a list of plane-fitting related questions at stackoverflow:
3D Plane fitting algorithms

Find points of angles in a rectangle in 3D coordinate system

I have points in 3D which make 2 or 3 side of rectangle. How I can calculate the coordinates of the cube's corners? Is it possible?
Updated: https://github.com/CPIGroup/3d-Camera-scanDimensions
This is just an idea, not a proven method.
First, find the planes. Randomly select 3 points, find a plane that passes through them, normalize the 4 parameters. Repeat 1000 or so times. You will end up with 1000 4-tuples of numbers. Use one of the clustering analysis methods to find 2 or 3 groups of 4-tuples that are very close together. Average each of the groups. These will be, approximately, planes of your box's sides.
Now make them more precise. For each plane, find all points that are close to it but not close to other planes (for some value of "close", perhaps to be found using a clustering method too). For each such group of points, find a best fit plane using least squares.
If you have three planes, great; intersect them and you have a vertex and three edges. For two planes, you only have one edge. Either way, you can now try to find other edges. For simplicity, consider your plane to be an XY plane and your known edge an X axis. You now need to find the leftmost (rightmost) vertical line such that most of the points are to the left (resp. right) of it. Project all the points to the X axis. You now have a 1-dimensional case of your original problem: there is a lot of random points on some interval, find the interval. Use a clustering method again.
I'm not super experienced with this, but possibly you could use RANSAC ?
There seem to be many papers on the plane detection from pointclouds using RANSAC
Also you might want to have a look at the Point Clouds Library(PCL).It's a pretty impressive project with many useful features including also planar segmentation
As soon as the planes are detected, it should be a matter of finding the edges/corners which should be a lot simpler.

How to render a circle with as few vertices as possible?

I'm trying to figure out how to decide how many vertices I need to have to make my circle look as smooth as possible.
Here is an example of two circles, both having 24 vertices:
As you see, the bigger the circle becomes, the more vertices I need to hide the straight lines.
At first I thought that the minimum length of one line on the edge should be 6px, but that approach failed when I increased the circle size: I got way too many vertices. I also thought about calculating the angles, but I quickly realised that angles doesn't differ on different sized circles. I also checked this answer, but I don't have a clue how to convert it into code (and some weird stuff there: th uses itself for calculating itself), and I think it doesn't even work, since the author is using the angle from one slice to the middle of circle, which doesn't change if the circle gets larger.
Then I realised that maybe the solution is to check the angle between two vertices at the edges, in this way:
As you see, the fewer vertices, the bigger the lengths are for those triangles. So this has to be the answer, I just don't know how to calculate the number of vertices by using this information.
The answer you link to actually implements exactly the idea you propose at the end of your question.
The decisive formula that you need from that answer is this one:
th = arccos(2 * (1 - e / r)^2 - 1)
This tells you the angle between two vertices, where r is the radius of the circle and e is the maximum error you're willing to tolerate, i.e. the maximum deviation of your polygon from the circle -- this is the error marked in your diagram. For example, you might choose to set e to 0.5 of a pixel.
Because th is measured in radians, and 360 degrees (a full circle) is equal to 2*pi in radians, the number of vertices you need is
num_vertices = ceil(2*pi/th)
In case you want to draw the polygon triangles from the center of the circle, the formula for the required number of sides is:
sides = PI / arccos(1 - error / radius)
where error is the maximum deviation of polygon from the circle, in pixels and radius is also expressed in pixels.
Error 0.33 seems to produce results indistinguishable from an ideal circle. Circles drawn at error 0.5, on close inspection still show some subtly visible angles between sides, especially visible in small circles.
This function obviously breaks down when radius is much smaller than error, and may produce NaN values. You may want to use a special case (for example draw 3 sides) in this situation.
The graph below shows number of sides obtained from the function, with error set to 0.33:
First of all, if you are using OpenGL or DirectX you can significantly decrease the number of vertices by using a triangle fan structure.
As for the problem of the amount of vertices, I would imagine the number of vertices required for a smooth circle to scale with the circumference. This scales with r, so I would advice to find a good factor A such that:
#vertices = A * r
The angles are the same in the two cases of 24 vertices.
But with larger circle, the human eye is able to better see the individual straight lines.
So you need some heuristic that takes into account
the angle between two consecutive line segments in the curve, and
the size, and possibly
the scaling for display.
The third point is difficult since one does not in general know the size at which some graphic will be displayed. E.g., an SVG format picture can be displayed at any size. The most general solution, I think, is to have direct support for various figures (Bezier lines, circles, etc.) in the renderer, and then define the figure with a few parameters instead of as a sequence of points. Or, define it in terms of some figure that the renderer supports, e.g. as a sequence of connected Bezier curves. That way, the renderer can add the necessary number of points to make it look smooth and nice.
However, I guess that you're not creating a renderer, so then perhaps only the first two points above are relevant.

computing overlapping of two square in collision

I am trying to compute the overlapping area of two colliding rectangles.
I found the Separating Axis Theorem to compute if they are in collision or not, but I'm not sure can I to use it for computing the area of the collision ?
If yes, please advise which computation do I have to perform?
Basically, I need to compute the percentage of hidden part of a picture (the rectangle A is a picture 256*256 for example), and one other picture overlaps it, I want to get the percentage of the hided part in comparison to the global surface of the picture.
Check for intersections of edges. Either no edges intersect (easy, 100% or 0% overlap) or some edges overlap. In the latter case, you have an even number of intersection points (disregarding points where edges touch). Trace the resulting convex overlap polygon and calculate its area.