I have a set of points (black dots in geographic coordinate value) derived from the convex hull (blue) of a polygon (red). see Figure:
[(560023.44957588764,6362057.3904932579),
(560023.44957588764,6362060.3904932579),
(560024.44957588764,6362063.3904932579),
(560026.94957588764,6362068.3904932579),
(560028.44957588764,6362069.8904932579),
(560034.94957588764,6362071.8904932579),
(560036.44957588764,6362071.8904932579),
(560037.44957588764,6362070.3904932579),
(560037.44957588764,6362064.8904932579),
(560036.44957588764,6362063.3904932579),
(560034.94957588764,6362061.3904932579),
(560026.94957588764,6362057.8904932579),
(560025.44957588764,6362057.3904932579),
(560023.44957588764,6362057.3904932579)]
I need to calculate the the major and minor axis length following these steps (form this post write in R-project and in Java) or following the this example procedure
- Compute the convex hull of the cloud.
- For each edge of the convex hull: 2a. compute the edge orientation, 2b. rotate the convex hull using this orientation in order to compute easily the bounding rectangle area with min/max of x/y of the rotated convex hull, 2c. Store the orientation corresponding to the minimum area found,
- Return the rectangle corresponding to the minimum area found.
After that we know the The angle Theta (represented the orientation of the bounding rectangle relative to the y-axis of the image). The minimum and maximum of a and b over all boundary points are found:
- a(xi,yi) = xi*cos Theta + yi sin Theta
- b(xi,yi) = xi*sin Theta + yi cos Theta
The values (a_max - a_min) and (b_max - b_min) defined the length and width, respectively, of the bounding rectangle for a direction Theta.
Given a clockwise-ordered list of n points in the convex hull of a set of points, it is an O(n) operation to find the minimum-area enclosing rectangle. (For convex-hull finding, in O(n log n) time, see activestate.com recipe 66527 or see the quite compact Graham scan code at tixxit.net.)
The following python program uses techniques similar to those of the usual O(n) algorithm for computing maximum diameter of a convex polygon. That is, it maintains three indexes (iL, iP, iR) to the leftmost, opposite, and rightmost points relative to a given baseline. Each index advances through at most n points. Sample output from the program is shown next (with an added header):
For example, the i=10 entry indicates that relative to the baseline from point 10 to 11, point 0 is leftmost, point 4 is opposite, and point 7 is rightmost, yielding an area of 187.451 units.
Note that the code uses
mostfar()
to advance each index. Themx, my
parameters tomostfar()
tell it what extreme to test for; as an example, withmx,my = -1,0
,mostfar()
will try to maximize -rx (where rx is the rotated x of a point), thus finding the leftmost point. Note that an epsilon allowance probably should be used whenif mx*rx + my*ry >= best
is done in inexact arithmetic: when a hull has numerous points, rounding error may be a problem and cause the method to incorrectly not advance an index.Code is shown below. The hull data is taken from the question above, with irrelevant large offsets and identical decimal places elided.
Note: To get the length and width of the minimal-area enclosing rectangle, modify the above code as shown below. This will produce an output line like
in which the second and third numbers indicate the length and width of the rectangle, and the four integers give index numbers of points that lie upon sides of it.
OpenCV has this. See this:
http://docs.opencv.org/trunk/dd/d49/tutorial_py_contour_features.html
7.b. Rotated Rectangle
With
You can get the length and width of the rectangle as well as its angle. You can also compute the corners if you wish to draw it.
There is a module that does this already on github. https://github.com/BebeSparkelSparkel/MinimumBoundingBox
All you need to do is insert your point cloud into it.
You can get the major and minor axis lengths by:
It also returns area, rectangle center, rectangle angle, and corner points.
I found recipe to compute convex hulls.
If we are talking about "full solutions" (one function to do whole stuff), I found only
arcpy
which is part ofArcGIS
program. It providesMinimumBoundingGeometry_management
function which looks like what you are looking for. But it's not open source. Unfortunately, there is lack of python open source GIS libraries.I just implemented this myself, so I figured I'd drop my version here for others to view:
Here are four different examples of it in action. For each example, I generated 4 random points and found the bounding box.
(edit by @heltonbiker) A simple code for plotting:
(end edit)
It's relatively quick too for these samples on 4 points:
Link to the same answer over on gis.stackexchange for my own reference.