Find Minimum area ellipse enclosing a set of points in c++

后端 未结 3 1183
孤街浪徒
孤街浪徒 2021-01-27 22:07

I have a set of 2D points. I need to find a minimum area ellipse enclosing all the points. Could someone give an idea of how the problem has to be tackled. For a circle it was s

3条回答
  •  感情败类
    2021-01-27 22:25

    as Rory Daulton suggest you need to clearly specify the constraints of solution and removal of any will greatly complicates things. For starters assume this for now:

    • it is 2D problem
    • ellipse is axis aligned
    • center is arbitrary instead of (0,0)

    I would attack this as standard genere and test problem with approximation search (which is hybrid between binary search and linear search) to speed it up (but you can also try brute force from start so you see if it works).

    1. compute constraints of solution

      To limit the search you need to find approximate placement position and size of the ellipse. For that you can use out-scribed circle for your points. It is clear that ellipse area will be less or equal to the circle and placement will be near by. The circle does not have to be necessarily the smallest one possible so we can use for example this:

      1. find bounding box of the points
      2. let the circle be centered to that bounding box and with radius be the max distance from its center to any of the points.

      This will be O(n) complexity where n is number of your points.

    2. search "all" the possible ellipses and remember best solution

      so we need to find ellipse center (x0,y0) and semi-axises rx,ry while area = M_PI*rx*ry is minimal. With approximation search each variable has factor of O(log(m)) and each iteration need to test validity which is O(n) so final complexity would be O(n.log^4(m)) where m is average number of possible variations of each search parameter (dependent on accuracy and search constraints). With simple brute search it would be O(n.m^4) which is really scary especially for floating point where m can be really big.

      To speed this up we know that the area of ellipse will be less then or equal to area of found circle so we can ignore all the bigger ellipses. The constrains to rx,ry can be derived from the aspect ratio of the bounding box +/- some reserve.

    Here simple small C++ example using that approx class from link above:

    //---------------------------------------------------------------------------
    // input points
    const int n=15; // number of random points to test
    float pnt[n][2];
    // debug bounding box
    float box_x0,box_y0,box_x1,box_y1;
    // debug outscribed circle
    float circle_x,circle_y,circle_r;
    // solution ellipse
    float ellipse_x,ellipse_y,ellipse_rx,ellipse_ry;
    //---------------------------------------------------------------------------
    void compute(float x0,float y0,float x1,float y1) // cal with bounding box where you want your points will be generated
        {
        int i;
        float x,y;
        // generate n random 2D points inside defined area
        Randomize();
        for (i=0;ix) x0=x; if (x1y) y0=y; if (y1=ab.a)
                {
                m=aa.a/ab.a; // convert to circle of radius rx
                for (i=0;iaa.a*aa.a) { e=2.0*area; break; }
                    }
                }
            else{
                m=ab.a/aa.a; // convert to circle of radius ry
                for (i=0;iab.a*ab.a) { e=2.0*area; break; }
                    }
                }
             }
    
        ellipse_x =ax.aa;
        ellipse_y =ay.aa;
        ellipse_rx=aa.aa;
        ellipse_ry=ab.aa;
        }
    //---------------------------------------------------------------------------
    

    Even this simple example with only 15 points took around 2 seconds to compute. You can improve performance by adding heuristics like test only areas lower then circle_r^2 etc, or better select solution area with some math rule. If you use brute force instead of approximation search that expect the computation time could be even minutes or more hence the O(scary)...

    Beware this example will not work for any aspect ratio of the points as I hardcoded the upper bound for rx,ry to 2.0*circle_r which may not be enough. Instead you can compute the upper bound from aspect ratio of the points and or condition that rx*ry<=circle_r^2...

    There are also other ("faster") methods for example variation of CCD (cyclic coordinate descend) can be used. But such methods usually can not guarantee that optimal solution will be found or any at all ...

    Here overview of the example output:

    The dots are individual points from pnt[n], the gray dashed stuff are bounding box and used out-scribed circle. The green ellipse is found solution.

提交回复
热议问题