This is kind of clunky, written in C++, assumes you know your centroid
and convex hull, but is a fairly straight-forward manner of getting
the minimum bounding rectangle. The rotation is in there if you want
peel it out:

// findMBR
//
// Finds the minimum bounding rectangle of the convex hull
// We know that one side of the MBR is collinear with at
// least one side of the convex hull.
//
// Works by examining each side of the hull, rotating hull
// so it's axis-aligned. Then we calculate the aabr and area.
// If this is the smallest, we save the coordinates and angle
// of rotation. Once we are done, we rotate the coordinates of
// the best aabr back based on the angle of rotation.
//
// This is O(n*n) - but n isn't terribly large
//
// The "rotating calipers" method is O(n), but it is harder to
// implement for MRVIN
//
void ConvexHull::findMBR(void) {
        if (gDebug_level > 1) {
        cout << "        findMBR, vc = " << aVertices.size() << "\n";
                cout << "        Vertices: \n";
                for (unsigned v = 0; v < aVertices.size(); v++) {
                        Vertex * pv = aVertices.at(v);

                        cout << "         " << pv->lId << ": (" << pv->dX << ", 
" << pv->dY << ")\n";
                }
        }

        mbrArea = REALLY_BIG_NUMBER;

        mbrX1 = 0; //       (x2,y2)   (x3,y3)
        mbrY1 = 0; //         +-------+
        mbrX2 = 0; //         |       |
        mbrY2 = 0; //         |       |
        mbrX3 = 0; //         |       |
        mbrY3 = 0; //         +-------+
        mbrX4 = 0; //       (x1,y1)   (x4,y4)
        mbrY4 = 0; //

        double bangle = 0, bxmin = 0, bxmax = 0, bymin = 0, bymax = 0;


    Vertex * A = aVertices.at(0);

    for (unsigned v = 1; v <= aVertices.size(); v++) {
                Vertex * B = aVertices.at(v%aVertices.size());

                double angle = atan((B->dX - A->dX)/(B->dY - A->dY) );
                
                double xmin = REALLY_BIG_NUMBER;
                double ymin = REALLY_BIG_NUMBER;
                double xmax = -(REALLY_BIG_NUMBER);
                double ymax = -(REALLY_BIG_NUMBER);

                for (unsigned w = 0; w < aVertices.size(); w++) {
                        Vertex * v = aVertices.at(w);

                        // Rotate the point to make AB axis-aligned
                        double x = centroid->dX + (v->dX - centroid->dX) * 
cos(angle) -
(v->dY - centroid->dY) * sin(angle);
                        double y = centroid->dY + (v->dX - centroid->dX) * 
sin(angle) +
(v->dY - centroid->dY) * cos(angle);

                        // Find the aabr
                        if (x < xmin) xmin = x;
                        if (x > xmax) xmax = x;
                        if (y < ymin) ymin = y;
                        if (y > ymax) ymax = y;
                }

                // Get the aabr area
                double area = abs((xmax - xmin) * (ymax - ymin));

                // If this is the smallest aabr, save the paramters
                if (area < mbrArea) {
                        mbrArea = area;
                        bangle =  -(angle);
                        bxmin = xmin;
                        bxmax = xmax;                   
                        bymin = ymin;
                        bymax = ymax;

                } // Loop throught the vertices

                B = A;

    } // Loop through the segments


        // Now we need to rotate the aabr back to get the real mmbr
        mbrX1 = centroid->dX + (bxmin - centroid->dX) * cos(bangle) - (bymin
- centroid->dY) * sin(bangle);
        mbrY1 = centroid->dY + (bxmin - centroid->dX) * sin(bangle) + (bymin
- centroid->dY) * cos(bangle);

        mbrX2 = centroid->dX + (bxmin - centroid->dX) * cos(bangle) - (bymax
- centroid->dY) * sin(bangle);
        mbrY2 = centroid->dY + (bxmin - centroid->dX) * sin(bangle) + (bymax
- centroid->dY) * cos(bangle);

        mbrX3 = centroid->dX + (bxmax - centroid->dX) * cos(bangle) - (bymax
- centroid->dY) * sin(bangle);
        mbrY3 = centroid->dY + (bxmax - centroid->dX) * sin(bangle) + (bymax
- centroid->dY) * cos(bangle);

        mbrX4 = centroid->dX + (bxmax - centroid->dX) * cos(bangle) - (bymin
- centroid->dY) * sin(bangle);
        mbrY4 = centroid->dY + (bxmax - centroid->dX) * sin(bangle) + (bymin
- centroid->dY) * cos(bangle);

        return;
}


-=--=---=----=----=---=--=-=--=---=----=---=--=-=-
Eric B. Wolf                           720-334-7734






On Tue, Jan 18, 2011 at 11:02 AM, Sean Gillies <[email protected]> wrote:
> A minimalist package for affine transformations of Python geospatial
> objects (in a GeoJSON format, say) would be handy, but I'm not aware
> of one. Numpy certainly has what you need, and matplotlib has some
> higher level classes based on numpy such as
> http://matplotlib.sourceforge.net/devel/transformations.html#matplotlib.transforms.Affine2D.
>
> Cheers,
>
> On Mon, Jan 17, 2011 at 10:14 AM, simo <[email protected]> wrote:
>> Hi all,
>>
>> As preamble, I have to say I'm new to Python and don't know (much)
>> about Java - I come from a PHP world.
>>
>> Anyway, since several months I follow GiS python activity, and I was
>> waiting for the day I'll have opportunity and overall time to work
>> with shapely and others open source python projects ....
>>
>> Finally that time has come and I'm trying to adapt Julien Gaffuri's
>> SmallestSurroundingRectangle to python  (available here :
>> http://opencarto.svn.sourceforge.net/viewvc/opencarto/trunk/src/main/java/org/opencarto/geomalgo/SmallestSurroundingRectangle.java?revision=168&view=markup
>> )
>>
>> His algorithm call a Rotate method and I was not able to find
>> something similar into Python.
>> Do you know if such method is included somewhere?
>>
>> the java rotation class is available at :
>> http://opencarto.svn.sourceforge.net/viewvc/opencarto/trunk/src/main/java/org/opencarto/geomalgo/Rotation.java?revision=176&view=markup
>>
>> subsidiary question : what about a scaling method ?
>>
>> the scaling class is available at :
>> http://opencarto.svn.sourceforge.net/viewvc/opencarto/trunk/src/main/java/org/opencarto/geomalgo/Scaling.java?revision=168&view=markup
>>
>> many thanks,
>>
>> simo
>
>
>
> --
> Sean
>

Reply via email to