converted few more comp. geometry functions to C++
authorVadim Pisarevsky <vadim.pisarevsky@gmail.com>
Tue, 22 Jan 2013 12:54:31 +0000 (16:54 +0400)
committerVadim Pisarevsky <vadim.pisarevsky@gmail.com>
Tue, 22 Jan 2013 12:54:31 +0000 (16:54 +0400)
modules/imgproc/src/_geom.h
modules/imgproc/src/contours.cpp
modules/imgproc/src/geometry.cpp
modules/imgproc/src/matchcontours.cpp
modules/imgproc/src/rotcalipers.cpp
modules/imgproc/src/shapedescr.cpp
samples/cpp/minarea.cpp

index 2505039..bfde73d 100644 (file)
@@ -52,16 +52,6 @@ CV_INLINE  float  icvDistanceL2_32f( CvPoint2D32f pt1, CvPoint2D32f pt2 )
 }
 
 
-int  icvIntersectLines( double x1, double dx1, double y1, double dy1,
-                        double x2, double dx2, double y2, double dy2,
-                        double* t2 );
-
-
-void icvIntersectLines3( double* a0, double* b0, double* c0,
-                         double* a1, double* b1, double* c1,
-                         CvPoint2D32f* point );
-
-
 /* curvature: 0 - 1-curvature, 1 - k-cosine curvature. */
 CvSeq* icvApproximateChainTC89( CvChain* chain, int header_size, CvMemStorage* storage, int method );
 
index 8c5dcb5..75e18b2 100644 (file)
@@ -1753,85 +1753,4 @@ void cv::findContours( InputOutputArray _image, OutputArrayOfArrays _contours,
     findContours(_image, _contours, noArray(), mode, method, offset);
 }
 
-double cv::arcLength( InputArray _curve, bool closed )
-{
-    Mat curve = _curve.getMat();
-    CV_Assert(curve.checkVector(2) >= 0 && (curve.depth() == CV_32F || curve.depth() == CV_32S));
-    CvMat _ccurve = curve;
-    return cvArcLength(&_ccurve, CV_WHOLE_SEQ, closed);
-}
-
-
-cv::Rect cv::boundingRect( InputArray _points )
-{
-    Mat points = _points.getMat();
-    CV_Assert(points.checkVector(2) >= 0 && (points.depth() == CV_32F || points.depth() == CV_32S));
-    CvMat _cpoints = points;
-    return cvBoundingRect(&_cpoints, 0);
-}
-
-
-double cv::contourArea( InputArray _contour, bool oriented )
-{
-    Mat contour = _contour.getMat();
-    CV_Assert(contour.checkVector(2) >= 0 && (contour.depth() == CV_32F || contour.depth() == CV_32S));
-    CvMat _ccontour = contour;
-    return cvContourArea(&_ccontour, CV_WHOLE_SEQ, oriented);
-}
-
-
-cv::RotatedRect cv::minAreaRect( InputArray _points )
-{
-    Mat points = _points.getMat();
-    CV_Assert(points.checkVector(2) >= 0 && (points.depth() == CV_32F || points.depth() == CV_32S));
-    CvMat _cpoints = points;
-    return cvMinAreaRect2(&_cpoints, 0);
-}
-
-
-void cv::minEnclosingCircle( InputArray _points,
-                             Point2f& center, float& radius )
-{
-    Mat points = _points.getMat();
-    CV_Assert(points.checkVector(2) >= 0 && (points.depth() == CV_32F || points.depth() == CV_32S));
-    CvMat _cpoints = points;
-    cvMinEnclosingCircle( &_cpoints, (CvPoint2D32f*)&center, &radius );
-}
-
-
-double cv::matchShapes( InputArray _contour1,
-                        InputArray _contour2,
-                        int method, double parameter )
-{
-    Mat contour1 = _contour1.getMat(), contour2 = _contour2.getMat();
-    CV_Assert(contour1.checkVector(2) >= 0 && contour2.checkVector(2) >= 0 &&
-              (contour1.depth() == CV_32F || contour1.depth() == CV_32S) &&
-              contour1.depth() == contour2.depth());
-
-    CvMat c1 = Mat(contour1), c2 = Mat(contour2);
-    return cvMatchShapes(&c1, &c2, method, parameter);
-}
-
-
-
-cv::RotatedRect cv::fitEllipse( InputArray _points )
-{
-    Mat points = _points.getMat();
-    CV_Assert(points.checkVector(2) >= 0 &&
-              (points.depth() == CV_32F || points.depth() == CV_32S));
-    CvMat _cpoints = points;
-    return cvFitEllipse2(&_cpoints);
-}
-
-
-double cv::pointPolygonTest( InputArray _contour,
-                             Point2f pt, bool measureDist )
-{
-    Mat contour = _contour.getMat();
-    CV_Assert(contour.checkVector(2) >= 0 &&
-              (contour.depth() == CV_32F || contour.depth() == CV_32S));
-    CvMat c = Mat(contour);
-    return cvPointPolygonTest( &c, pt, measureDist );
-}
-
 /* End of file. */
index 337362f..e0eb229 100644 (file)
@@ -92,97 +92,38 @@ cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] )
 }
 
 
-int
-icvIntersectLines( double x1, double dx1, double y1, double dy1,
-                   double x2, double dx2, double y2, double dy2, double *t2 )
-{
-    double d = dx1 * dy2 - dx2 * dy1;
-    int result = -1;
-
-    if( d != 0 )
-    {
-        *t2 = ((x2 - x1) * dy1 - (y2 - y1) * dx1) / d;
-        result = 0;
-    }
-    return result;
-}
-
-
-void
-icvIntersectLines3( double *a0, double *b0, double *c0,
-                    double *a1, double *b1, double *c1, CvPoint2D32f * point )
-{
-    double det = a0[0] * b1[0] - a1[0] * b0[0];
-
-    if( det != 0 )
-    {
-        det = 1. / det;
-        point->x = (float) ((b0[0] * c1[0] - b1[0] * c0[0]) * det);
-        point->y = (float) ((a1[0] * c0[0] - a0[0] * c1[0]) * det);
-    }
-    else
-    {
-        point->x = point->y = FLT_MAX;
-    }
-}
-
-
-CV_IMPL double
-cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
+double cv::pointPolygonTest( InputArray _contour, Point2f pt, bool measureDist )
 {
     double result = 0;
+    Mat contour = _contour.getMat();
+    int i, total = contour.checkVector(2), counter = 0;
+    int depth = contour.depth();
+    CV_Assert( total >= 0 && (depth == CV_32S || depth == CV_32F));
 
-    CvSeqBlock block;
-    CvContour header;
-    CvSeq* contour = (CvSeq*)_contour;
-    CvSeqReader reader;
-    int i, total, counter = 0;
-    int is_float;
+    bool is_float = depth == CV_32F;
     double min_dist_num = FLT_MAX, min_dist_denom = 1;
-    CvPoint ip = {0,0};
+    Point ip(cvRound(pt.x), cvRound(pt.y));
 
-    if( !CV_IS_SEQ(contour) )
-    {
-        contour = cvPointSeqFromMat( CV_SEQ_KIND_CURVE + CV_SEQ_FLAG_CLOSED,
-                                    _contour, &header, &block );
-    }
-    else if( CV_IS_SEQ_POINT_SET(contour) )
-    {
-        if( contour->header_size == sizeof(CvContour) && !measure_dist )
-        {
-            CvRect r = ((CvContour*)contour)->rect;
-            if( pt.x < r.x || pt.y < r.y ||
-                pt.x >= r.x + r.width || pt.y >= r.y + r.height )
-                return -1;
-        }
-    }
-    else if( CV_IS_SEQ_CHAIN(contour) )
-    {
-        CV_Error( CV_StsBadArg,
-            "Chains are not supported. Convert them to polygonal representation using cvApproxChains()" );
-    }
-    else
-        CV_Error( CV_StsBadArg, "Input contour is neither a valid sequence nor a matrix" );
+    if( total == 0 )
+        return measureDist ? -DBL_MAX : -1;
 
-    total = contour->total;
-    is_float = CV_SEQ_ELTYPE(contour) == CV_32FC2;
-    cvStartReadSeq( contour, &reader, -1 );
+    const Point* cnt = (const Point*)contour.data;
+    const Point2f* cntf = (const Point2f*)cnt;
 
-    if( !is_float && !measure_dist && (ip.x = cvRound(pt.x)) == pt.x && (ip.y = cvRound(pt.y)) == pt.y )
+    if( !is_float && !measureDist && ip.x == pt.x && ip.y == pt.y )
     {
-        // the fastest "pure integer" branch
-        CvPoint v0, v;
-        CV_READ_SEQ_ELEM( v, reader );
+        // the fastest "purely integer" branch
+        Point v0, v = cnt[total-1];
 
         for( i = 0; i < total; i++ )
         {
             int dist;
             v0 = v;
-            CV_READ_SEQ_ELEM( v, reader );
+            v = cnt[i];
 
             if( (v0.y <= ip.y && v.y <= ip.y) ||
-                (v0.y > ip.y && v.y > ip.y) ||
-                (v0.x < ip.x && v.x < ip.x) )
+               (v0.y > ip.y && v.y > ip.y) ||
+               (v0.x < ip.x && v.x < ip.x) )
             {
                 if( ip.y == v.y && (ip.x == v.x || (ip.y == v0.y &&
                     ((v0.x <= ip.x && ip.x <= v.x) || (v.x <= ip.x && ip.x <= v0.x)))) )
@@ -202,38 +143,32 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
     }
     else
     {
-        CvPoint2D32f v0, v;
-        CvPoint iv;
+        Point2f v0, v;
+        Point iv;
 
         if( is_float )
         {
-            CV_READ_SEQ_ELEM( v, reader );
+            v = cntf[total-1];
         }
         else
         {
-            CV_READ_SEQ_ELEM( iv, reader );
-            v = cvPointTo32f( iv );
+            v = cnt[total-1];
         }
 
-        if( !measure_dist )
+        if( !measureDist )
         {
             for( i = 0; i < total; i++ )
             {
                 double dist;
                 v0 = v;
                 if( is_float )
-                {
-                    CV_READ_SEQ_ELEM( v, reader );
-                }
+                    v = cntf[i];
                 else
-                {
-                    CV_READ_SEQ_ELEM( iv, reader );
-                    v = cvPointTo32f( iv );
-                }
+                    v = cnt[i];
 
                 if( (v0.y <= pt.y && v.y <= pt.y) ||
-                    (v0.y > pt.y && v.y > pt.y) ||
-                    (v0.x < pt.x && v.x < pt.x) )
+                   (v0.y > pt.y && v.y > pt.y) ||
+                   (v0.x < pt.x && v.x < pt.x) )
                 {
                     if( pt.y == v.y && (pt.x == v.x || (pt.y == v0.y &&
                         ((v0.x <= pt.x && pt.x <= v.x) || (v.x <= pt.x && pt.x <= v0.x)))) )
@@ -259,14 +194,9 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
 
                 v0 = v;
                 if( is_float )
-                {
-                    CV_READ_SEQ_ELEM( v, reader );
-                }
+                    v = cntf[i];
                 else
-                {
-                    CV_READ_SEQ_ELEM( iv, reader );
-                    v = cvPointTo32f( iv );
-                }
+                    v = cnt[i];
 
                 dx = v.x - v0.x; dy = v.y - v0.y;
                 dx1 = pt.x - v0.x; dy1 = pt.y - v0.y;
@@ -292,8 +222,8 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
                 }
 
                 if( (v0.y <= pt.y && v.y <= pt.y) ||
-                    (v0.y > pt.y && v.y > pt.y) ||
-                    (v0.x < pt.x && v.x < pt.x) )
+                   (v0.y > pt.y && v.y > pt.y) ||
+                   (v0.x < pt.x && v.x < pt.x) )
                     continue;
 
                 dist_num = dy1*dx - dx1*dy;
@@ -301,17 +231,25 @@ cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
                     dist_num = -dist_num;
                 counter += dist_num > 0;
             }
-
+            
             result = sqrt(min_dist_num/min_dist_denom);
             if( counter % 2 == 0 )
                 result = -result;
         }
     }
-
+    
     return result;
 }
 
 
+CV_IMPL double
+cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
+{
+    cv::AutoBuffer<double> abuf;
+    cv::Mat contour = cv::cvarrToMat(_contour, false, false, 0, &abuf);
+    return cv::pointPolygonTest(contour, pt, measure_dist != 0);
+}
+
 /*
  This code is described in "Computational Geometry in C" (Second Edition),
  Chapter 7.  It is not written to be comprehensible without the
index 44c01e0..eca3859 100644 (file)
 //M*/
 #include "precomp.hpp"
 
-/*F///////////////////////////////////////////////////////////////////////////////////////
-//    Name: cvMatchContours
-//    Purpose:
-//      Calculates matching of the two contours
-//    Context:
-//    Parameters:
-//      contour_1 - pointer to the first input contour object.
-//      contour_2 - pointer to the second input contour object.
-//      method - method for the matching calculation
-//      (now CV_IPPI_CONTOURS_MATCH_I1, CV_CONTOURS_MATCH_I2 or
-//      CV_CONTOURS_MATCH_I3 only  )
-//      rezult - output calculated measure
-//
-//F*/
-CV_IMPL  double
-cvMatchShapes( const void* contour1, const void* contour2,
-               int method, double /*parameter*/ )
+
+double cv::matchShapes(InputArray contour1, InputArray contour2, int method, double)
 {
-    CvMoments moments;
-    CvHuMoments huMoments;
     double ma[7], mb[7];
     int i, sma, smb;
     double eps = 1.e-5;
     double mmm;
     double result = 0;
 
-    if( !contour1 || !contour2 )
-        CV_Error( CV_StsNullPtr, "" );
-
-    // calculate moments of the first shape
-    cvMoments( contour1, &moments );
-    cvGetHuMoments( &moments, &huMoments );
-
-    ma[0] = huMoments.hu1;
-    ma[1] = huMoments.hu2;
-    ma[2] = huMoments.hu3;
-    ma[3] = huMoments.hu4;
-    ma[4] = huMoments.hu5;
-    ma[5] = huMoments.hu6;
-    ma[6] = huMoments.hu7;
-
-
-    // calculate moments of the second shape
-    cvMoments( contour2, &moments );
-    cvGetHuMoments( &moments, &huMoments );
-
-    mb[0] = huMoments.hu1;
-    mb[1] = huMoments.hu2;
-    mb[2] = huMoments.hu3;
-    mb[3] = huMoments.hu4;
-    mb[4] = huMoments.hu5;
-    mb[5] = huMoments.hu6;
-    mb[6] = huMoments.hu7;
+    HuMoments( moments(contour1), ma );
+    HuMoments( moments(contour2), mb );
 
     switch (method)
     {
     case 1:
+        for( i = 0; i < 7; i++ )
         {
-            for( i = 0; i < 7; i++ )
+            double ama = fabs( ma[i] );
+            double amb = fabs( mb[i] );
+
+            if( ma[i] > 0 )
+                sma = 1;
+            else if( ma[i] < 0 )
+                sma = -1;
+            else
+                sma = 0;
+            if( mb[i] > 0 )
+                smb = 1;
+            else if( mb[i] < 0 )
+                smb = -1;
+            else
+                smb = 0;
+
+            if( ama > eps && amb > eps )
             {
-                double ama = fabs( ma[i] );
-                double amb = fabs( mb[i] );
-
-                if( ma[i] > 0 )
-                    sma = 1;
-                else if( ma[i] < 0 )
-                    sma = -1;
-                else
-                    sma = 0;
-                if( mb[i] > 0 )
-                    smb = 1;
-                else if( mb[i] < 0 )
-                    smb = -1;
-                else
-                    smb = 0;
-
-                if( ama > eps && amb > eps )
-                {
-                    ama = 1. / (sma * log10( ama ));
-                    amb = 1. / (smb * log10( amb ));
-                    result += fabs( -ama + amb );
-                }
+                ama = 1. / (sma * log10( ama ));
+                amb = 1. / (smb * log10( amb ));
+                result += fabs( -ama + amb );
             }
-            break;
         }
+        break;
 
     case 2:
+        for( i = 0; i < 7; i++ )
         {
-            for( i = 0; i < 7; i++ )
+            double ama = fabs( ma[i] );
+            double amb = fabs( mb[i] );
+
+            if( ma[i] > 0 )
+                sma = 1;
+            else if( ma[i] < 0 )
+                sma = -1;
+            else
+                sma = 0;
+            if( mb[i] > 0 )
+                smb = 1;
+            else if( mb[i] < 0 )
+                smb = -1;
+            else
+                smb = 0;
+
+            if( ama > eps && amb > eps )
             {
-                double ama = fabs( ma[i] );
-                double amb = fabs( mb[i] );
-
-                if( ma[i] > 0 )
-                    sma = 1;
-                else if( ma[i] < 0 )
-                    sma = -1;
-                else
-                    sma = 0;
-                if( mb[i] > 0 )
-                    smb = 1;
-                else if( mb[i] < 0 )
-                    smb = -1;
-                else
-                    smb = 0;
-
-                if( ama > eps && amb > eps )
-                {
-                    ama = sma * log10( ama );
-                    amb = smb * log10( amb );
-                    result += fabs( -ama + amb );
-                }
+                ama = sma * log10( ama );
+                amb = smb * log10( amb );
+                result += fabs( -ama + amb );
             }
-            break;
         }
+        break;
 
     case 3:
+        for( i = 0; i < 7; i++ )
         {
-            for( i = 0; i < 7; i++ )
+            double ama = fabs( ma[i] );
+            double amb = fabs( mb[i] );
+
+            if( ma[i] > 0 )
+                sma = 1;
+            else if( ma[i] < 0 )
+                sma = -1;
+            else
+                sma = 0;
+            if( mb[i] > 0 )
+                smb = 1;
+            else if( mb[i] < 0 )
+                smb = -1;
+            else
+                smb = 0;
+
+            if( ama > eps && amb > eps )
             {
-                double ama = fabs( ma[i] );
-                double amb = fabs( mb[i] );
-
-                if( ma[i] > 0 )
-                    sma = 1;
-                else if( ma[i] < 0 )
-                    sma = -1;
-                else
-                    sma = 0;
-                if( mb[i] > 0 )
-                    smb = 1;
-                else if( mb[i] < 0 )
-                    smb = -1;
-                else
-                    smb = 0;
-
-                if( ama > eps && amb > eps )
-                {
-                    ama = sma * log10( ama );
-                    amb = smb * log10( amb );
-                    mmm = fabs( (ama - amb) / ama );
-                    if( result < mmm )
-                        result = mmm;
-                }
+                ama = sma * log10( ama );
+                amb = smb * log10( amb );
+                mmm = fabs( (ama - amb) / ama );
+                if( result < mmm )
+                    result = mmm;
             }
-            break;
         }
+        break;
     default:
         CV_Error( CV_StsBadArg, "Unknown comparison method" );
     }
-
+    
     return result;
 }
 
 
+CV_IMPL  double
+cvMatchShapes( const void* _contour1, const void* _contour2,
+               int method, double parameter )
+{
+    cv::AutoBuffer<double> abuf1, abuf2;
+    cv::Mat contour1 = cv::cvarrToMat(_contour1, false, false, 0, &abuf1);
+    cv::Mat contour2 = cv::cvarrToMat(_contour2, false, false, 0, &abuf2);
+
+    return cv::matchShapes(contour1, contour2, method, parameter);
+}
+
 /* End of file. */
index 2171ec1..adb7405 100644 (file)
 /*M///////////////////////////////////////////////////////////////////////////////////////
-//
-//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
-//
-//  By downloading, copying, installing or using the software you agree to this license.
-//  If you do not agree to this license, do not download, install,
-//  copy or use the software.
-//
-//
-//                        Intel License Agreement
-//                For Open Source Computer Vision Library
-//
-// Copyright (C) 2000, Intel Corporation, all rights reserved.
-// Third party copyrights are property of their respective owners.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-//   * Redistribution's of source code must retain the above copyright notice,
-//     this list of conditions and the following disclaimer.
-//
-//   * Redistribution's in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//
-//   * The name of Intel Corporation may not be used to endorse or promote products
-//     derived from this software without specific prior written permission.
-//
-// This software is provided by the copyright holders and contributors "as is" and
-// any express or implied warranties, including, but not limited to, the implied
-// warranties of merchantability and fitness for a particular purpose are disclaimed.
-// In no event shall the Intel Corporation or contributors be liable for any direct,
-// indirect, incidental, special, exemplary, or consequential damages
-// (including, but not limited to, procurement of substitute goods or services;
-// loss of use, data, or profits; or business interruption) however caused
-// and on any theory of liability, whether in contract, strict liability,
-// or tort (including negligence or otherwise) arising in any way out of
-// the use of this software, even if advised of the possibility of such damage.
-//
-//M*/
+ //
+ //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+ //
+ //  By downloading, copying, installing or using the software you agree to this license.
+ //  If you do not agree to this license, do not download, install,
+ //  copy or use the software.
+ //
+ //
+ //                           License Agreement
+ //                For Open Source Computer Vision Library
+ //
+ // Copyright (C) 2000, Intel Corporation, all rights reserved.
+ // Third party copyrights are property of their respective owners.
+ //
+ // Redistribution and use in source and binary forms, with or without modification,
+ // are permitted provided that the following conditions are met:
+ //
+ //   * Redistribution's of source code must retain the above copyright notice,
+ //     this list of conditions and the following disclaimer.
+ //
+ //   * Redistribution's in binary form must reproduce the above copyright notice,
+ //     this list of conditions and the following disclaimer in the documentation
+ //     and/or other materials provided with the distribution.
+ //
+ //   * The name of OpenCV Foundation may not be used to endorse or promote products
+ //     derived from this software without specific prior written permission.
+ //
+ // This software is provided by the copyright holders and contributors "as is" and
+ // any express or implied warranties, including, but not limited to, the implied
+ // warranties of merchantability and fitness for a particular purpose are disclaimed.
+ // In no event shall the OpenCV Foundation or contributors be liable for any direct,
+ // indirect, incidental, special, exemplary, or consequential damages
+ // (including, but not limited to, procurement of substitute goods or services;
+ // loss of use, data, or profits; or business interruption) however caused
+ // and on any theory of liability, whether in contract, strict liability,
+ // or tort (including negligence or otherwise) arising in any way out of
+ // the use of this software, even if advised of the possibility of such damage.
+ //
+ //M*/
 #include "precomp.hpp"
 
-typedef struct
+namespace cv
 {
-    int bottom;
-    int left;
-    float height;
-    float width;
-    float base_a;
-    float base_b;
-}
-icvMinAreaState;
-
-#define CV_CALIPERS_MAXHEIGHT      0
-#define CV_CALIPERS_MINAREARECT    1
-#define CV_CALIPERS_MAXDIST        2
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-//    Name:    icvRotatingCalipers
-//    Purpose:
-//      Rotating calipers algorithm with some applications
-//
-//    Context:
-//    Parameters:
-//      points      - convex hull vertices ( any orientation )
-//      n           - number of vertices
-//      mode        - concrete application of algorithm
-//                    can be  CV_CALIPERS_MAXDIST   or
-//                            CV_CALIPERS_MINAREARECT
-//      left, bottom, right, top - indexes of extremal points
-//      out         - output info.
-//                    In case CV_CALIPERS_MAXDIST it points to float value -
-//                    maximal height of polygon.
-//                    In case CV_CALIPERS_MINAREARECT
-//                    ((CvPoint2D32f*)out)[0] - corner
-//                    ((CvPoint2D32f*)out)[1] - vector1
-//                    ((CvPoint2D32f*)out)[0] - corner2
-//
-//                      ^
-//                      |
-//              vector2 |
-//                      |
-//                      |____________\
-//                    corner         /
-//                               vector1
-//
-//    Returns:
-//    Notes:
-//F*/
-
-/* we will use usual cartesian coordinates */
-static void
-icvRotatingCalipers( CvPoint2D32f* points, int n, int mode, float* out )
-{
-    float minarea = FLT_MAX;
-    float max_dist = 0;
-    char buffer[32] = {};
-    int i, k;
-    CvPoint2D32f* vect = (CvPoint2D32f*)cvAlloc( n * sizeof(vect[0]) );
-    float* inv_vect_length = (float*)cvAlloc( n * sizeof(inv_vect_length[0]) );
-    int left = 0, bottom = 0, right = 0, top = 0;
-    int seq[4] = { -1, -1, -1, -1 };
-
-    /* rotating calipers sides will always have coordinates
-       (a,b) (-b,a) (-a,-b) (b, -a)
-     */
-    /* this is a first base bector (a,b) initialized by (1,0) */
-    float orientation = 0;
-    float base_a;
-    float base_b = 0;
-
-    float left_x, right_x, top_y, bottom_y;
-    CvPoint2D32f pt0 = points[0];
-
-    left_x = right_x = pt0.x;
-    top_y = bottom_y = pt0.y;
-
-    for( i = 0; i < n; i++ )
-    {
-        double dx, dy;
 
-        if( pt0.x < left_x )
-            left_x = pt0.x, left = i;
+    struct MinAreaState
+    {
+        int bottom;
+        int left;
+        float height;
+        float width;
+        float base_a;
+        float base_b;
+    };
+
+    enum { CALIPERS_MAXHEIGHT=0, CALIPERS_MINAREARECT=1, CALIPERS_MAXDIST=2 };
+
+    /*F///////////////////////////////////////////////////////////////////////////////////////
+     //    Name:    rotatingCalipers
+     //    Purpose:
+     //      Rotating calipers algorithm with some applications
+     //
+     //    Context:
+     //    Parameters:
+     //      points      - convex hull vertices ( any orientation )
+     //      n           - number of vertices
+     //      mode        - concrete application of algorithm
+     //                    can be  CV_CALIPERS_MAXDIST   or
+     //                            CV_CALIPERS_MINAREARECT
+     //      left, bottom, right, top - indexes of extremal points
+     //      out         - output info.
+     //                    In case CV_CALIPERS_MAXDIST it points to float value -
+     //                    maximal height of polygon.
+     //                    In case CV_CALIPERS_MINAREARECT
+     //                    ((CvPoint2D32f*)out)[0] - corner
+     //                    ((CvPoint2D32f*)out)[1] - vector1
+     //                    ((CvPoint2D32f*)out)[0] - corner2
+     //
+     //                      ^
+     //                      |
+     //              vector2 |
+     //                      |
+     //                      |____________\
+     //                    corner         /
+     //                               vector1
+     //
+     //    Returns:
+     //    Notes:
+     //F*/
+
+    /* we will use usual cartesian coordinates */
+    static void rotatingCalipers( const Point2f* points, int n, int mode, float* out )
+    {
+        float minarea = FLT_MAX;
+        float max_dist = 0;
+        char buffer[32] = {};
+        int i, k;
+        AutoBuffer<float> buf(n*3);
+        float* inv_vect_length = buf;
+        Point2f* vect = (Point2f*)(inv_vect_length + n);
+        int left = 0, bottom = 0, right = 0, top = 0;
+        int seq[4] = { -1, -1, -1, -1 };
+
+        /* rotating calipers sides will always have coordinates
+         (a,b) (-b,a) (-a,-b) (b, -a)
+         */
+        /* this is a first base bector (a,b) initialized by (1,0) */
+        float orientation = 0;
+        float base_a;
+        float base_b = 0;
+
+        float left_x, right_x, top_y, bottom_y;
+        Point2f pt0 = points[0];
+
+        left_x = right_x = pt0.x;
+        top_y = bottom_y = pt0.y;
 
-        if( pt0.x > right_x )
-            right_x = pt0.x, right = i;
+        for( i = 0; i < n; i++ )
+        {
+            double dx, dy;
 
-        if( pt0.y > top_y )
-            top_y = pt0.y, top = i;
+            if( pt0.x < left_x )
+                left_x = pt0.x, left = i;
 
-        if( pt0.y < bottom_y )
-            bottom_y = pt0.y, bottom = i;
+            if( pt0.x > right_x )
+                right_x = pt0.x, right = i;
 
-        CvPoint2D32f pt = points[(i+1) & (i+1 < n ? -1 : 0)];
+            if( pt0.y > top_y )
+                top_y = pt0.y, top = i;
 
-        dx = pt.x - pt0.x;
-        dy = pt.y - pt0.y;
+            if( pt0.y < bottom_y )
+                bottom_y = pt0.y, bottom = i;
 
-        vect[i].x = (float)dx;
-        vect[i].y = (float)dy;
-        inv_vect_length[i] = (float)(1./sqrt(dx*dx + dy*dy));
+            Point2f pt = points[(i+1) & (i+1 < n ? -1 : 0)];
 
-        pt0 = pt;
-    }
+            dx = pt.x - pt0.x;
+            dy = pt.y - pt0.y;
 
-    //cvbInvSqrt( inv_vect_length, inv_vect_length, n );
+            vect[i].x = (float)dx;
+            vect[i].y = (float)dy;
+            inv_vect_length[i] = (float)(1./sqrt(dx*dx + dy*dy));
 
-    /* find convex hull orientation */
-    {
-        double ax = vect[n-1].x;
-        double ay = vect[n-1].y;
+            pt0 = pt;
+        }
 
-        for( i = 0; i < n; i++ )
+        // find convex hull orientation
         {
-            double bx = vect[i].x;
-            double by = vect[i].y;
-
-            double convexity = ax * by - ay * bx;
+            double ax = vect[n-1].x;
+            double ay = vect[n-1].y;
 
-            if( convexity != 0 )
+            for( i = 0; i < n; i++ )
             {
-                orientation = (convexity > 0) ? 1.f : (-1.f);
-                break;
+                double bx = vect[i].x;
+                double by = vect[i].y;
+
+                double convexity = ax * by - ay * bx;
+
+                if( convexity != 0 )
+                {
+                    orientation = (convexity > 0) ? 1.f : (-1.f);
+                    break;
+                }
+                ax = bx;
+                ay = by;
             }
-            ax = bx;
-            ay = by;
+            CV_Assert( orientation != 0 );
         }
-        assert( orientation != 0 );
-    }
-    base_a = orientation;
-
-/*****************************************************************************************/
-/*                         init calipers position                                        */
-    seq[0] = bottom;
-    seq[1] = right;
-    seq[2] = top;
-    seq[3] = left;
-/*****************************************************************************************/
-/*                         Main loop - evaluate angles and rotate calipers               */
-
-    /* all of edges will be checked while rotating calipers by 90 degrees */
-    for( k = 0; k < n; k++ )
-    {
-        /* sinus of minimal angle */
-        /*float sinus;*/
-
-        /* compute cosine of angle between calipers side and polygon edge */
-        /* dp - dot product */
-        float dp0 = base_a * vect[seq[0]].x + base_b * vect[seq[0]].y;
-        float dp1 = -base_b * vect[seq[1]].x + base_a * vect[seq[1]].y;
-        float dp2 = -base_a * vect[seq[2]].x - base_b * vect[seq[2]].y;
-        float dp3 = base_b * vect[seq[3]].x - base_a * vect[seq[3]].y;
-
-        float cosalpha = dp0 * inv_vect_length[seq[0]];
-        float maxcos = cosalpha;
-
-        /* number of calipers edges, that has minimal angle with edge */
-        int main_element = 0;
-
-        /* choose minimal angle */
-        cosalpha = dp1 * inv_vect_length[seq[1]];
-        maxcos = (cosalpha > maxcos) ? (main_element = 1, cosalpha) : maxcos;
-        cosalpha = dp2 * inv_vect_length[seq[2]];
-        maxcos = (cosalpha > maxcos) ? (main_element = 2, cosalpha) : maxcos;
-        cosalpha = dp3 * inv_vect_length[seq[3]];
-        maxcos = (cosalpha > maxcos) ? (main_element = 3, cosalpha) : maxcos;
-
-        /*rotate calipers*/
+        base_a = orientation;
+
+        /*****************************************************************************************/
+        /*                         init calipers position                                        */
+        seq[0] = bottom;
+        seq[1] = right;
+        seq[2] = top;
+        seq[3] = left;
+        /*****************************************************************************************/
+        /*                         Main loop - evaluate angles and rotate calipers               */
+
+        /* all of edges will be checked while rotating calipers by 90 degrees */
+        for( k = 0; k < n; k++ )
         {
-            //get next base
-            int pindex = seq[main_element];
-            float lead_x = vect[pindex].x*inv_vect_length[pindex];
-            float lead_y = vect[pindex].y*inv_vect_length[pindex];
-            switch( main_element )
+            /* sinus of minimal angle */
+            /*float sinus;*/
+
+            /* compute cosine of angle between calipers side and polygon edge */
+            /* dp - dot product */
+            float dp0 = base_a * vect[seq[0]].x + base_b * vect[seq[0]].y;
+            float dp1 = -base_b * vect[seq[1]].x + base_a * vect[seq[1]].y;
+            float dp2 = -base_a * vect[seq[2]].x - base_b * vect[seq[2]].y;
+            float dp3 = base_b * vect[seq[3]].x - base_a * vect[seq[3]].y;
+
+            float cosalpha = dp0 * inv_vect_length[seq[0]];
+            float maxcos = cosalpha;
+
+            /* number of calipers edges, that has minimal angle with edge */
+            int main_element = 0;
+
+            /* choose minimal angle */
+            cosalpha = dp1 * inv_vect_length[seq[1]];
+            maxcos = (cosalpha > maxcos) ? (main_element = 1, cosalpha) : maxcos;
+            cosalpha = dp2 * inv_vect_length[seq[2]];
+            maxcos = (cosalpha > maxcos) ? (main_element = 2, cosalpha) : maxcos;
+            cosalpha = dp3 * inv_vect_length[seq[3]];
+            maxcos = (cosalpha > maxcos) ? (main_element = 3, cosalpha) : maxcos;
+
+            /*rotate calipers*/
             {
-            case 0:
-                base_a = lead_x;
-                base_b = lead_y;
-                break;
-            case 1:
-                base_a = lead_y;
-                base_b = -lead_x;
-                break;
-            case 2:
-                base_a = -lead_x;
-                base_b = -lead_y;
-                break;
-            case 3:
-                base_a = -lead_y;
-                base_b = lead_x;
-                break;
-            default: assert(0);
+                //get next base
+                int pindex = seq[main_element];
+                float lead_x = vect[pindex].x*inv_vect_length[pindex];
+                float lead_y = vect[pindex].y*inv_vect_length[pindex];
+                switch( main_element )
+                {
+                    case 0:
+                        base_a = lead_x;
+                        base_b = lead_y;
+                        break;
+                    case 1:
+                        base_a = lead_y;
+                        base_b = -lead_x;
+                        break;
+                    case 2:
+                        base_a = -lead_x;
+                        base_b = -lead_y;
+                        break;
+                    case 3:
+                        base_a = -lead_y;
+                        base_b = lead_x;
+                        break;
+                    default:
+                        CV_Error(CV_StsError, "main_element should be 0, 1, 2 or 3");
+                }
             }
-        }
-        /* change base point of main edge */
-        seq[main_element] += 1;
-        seq[main_element] = (seq[main_element] == n) ? 0 : seq[main_element];
-
-
-        switch (mode)
-        {
-        case CV_CALIPERS_MAXHEIGHT:
-            {
-                /* now main element lies on edge alligned to calipers side */
-
-                /* find opposite element i.e. transform  */
-                /* 0->2, 1->3, 2->0, 3->1                */
-                int opposite_el = main_element ^ 2;
-
-                float dx = points[seq[opposite_el]].x - points[seq[main_element]].x;
-                float dy = points[seq[opposite_el]].y - points[seq[main_element]].y;
-                float dist;
-
-                if( main_element & 1 )
-                    dist = (float)fabs(dx * base_a + dy * base_b);
-                else
-                    dist = (float)fabs(dx * (-base_b) + dy * base_a);
+            /* change base point of main edge */
+            seq[main_element] += 1;
+            seq[main_element] = (seq[main_element] == n) ? 0 : seq[main_element];
 
-                if( dist > max_dist )
-                    max_dist = dist;
-
-                break;
-            }
-        case CV_CALIPERS_MINAREARECT:
-            /* find area of rectangle */
+            switch (mode)
             {
-                float height;
-                float area;
+                case CALIPERS_MAXHEIGHT:
+                {
+                    /* now main element lies on edge alligned to calipers side */
 
-                /* find vector left-right */
-                float dx = points[seq[1]].x - points[seq[3]].x;
-                float dy = points[seq[1]].y - points[seq[3]].y;
+                    /* find opposite element i.e. transform  */
+                    /* 0->2, 1->3, 2->0, 3->1                */
+                    int opposite_el = main_element ^ 2;
 
-                /* dotproduct */
-                float width = dx * base_a + dy * base_b;
+                    float dx = points[seq[opposite_el]].x - points[seq[main_element]].x;
+                    float dy = points[seq[opposite_el]].y - points[seq[main_element]].y;
+                    float dist;
 
-                /* find vector left-right */
-                dx = points[seq[2]].x - points[seq[0]].x;
-                dy = points[seq[2]].y - points[seq[0]].y;
+                    if( main_element & 1 )
+                        dist = (float)fabs(dx * base_a + dy * base_b);
+                    else
+                        dist = (float)fabs(dx * (-base_b) + dy * base_a);
 
-                /* dotproduct */
-                height = -dx * base_b + dy * base_a;
+                    if( dist > max_dist )
+                        max_dist = dist;
 
-                area = width * height;
-                if( area <= minarea )
+                    break;
+                }
+                case CALIPERS_MINAREARECT:
+                    /* find area of rectangle */
                 {
-                    float *buf = (float *) buffer;
-
-                    minarea = area;
-                    /* leftist point */
-                    ((int *) buf)[0] = seq[3];
-                    buf[1] = base_a;
-                    buf[2] = width;
-                    buf[3] = base_b;
-                    buf[4] = height;
-                    /* bottom point */
-                    ((int *) buf)[5] = seq[0];
-                    buf[6] = area;
+                    float height;
+                    float area;
+
+                    /* find vector left-right */
+                    float dx = points[seq[1]].x - points[seq[3]].x;
+                    float dy = points[seq[1]].y - points[seq[3]].y;
+
+                    /* dotproduct */
+                    float width = dx * base_a + dy * base_b;
+
+                    /* find vector left-right */
+                    dx = points[seq[2]].x - points[seq[0]].x;
+                    dy = points[seq[2]].y - points[seq[0]].y;
+
+                    /* dotproduct */
+                    height = -dx * base_b + dy * base_a;
+
+                    area = width * height;
+                    if( area <= minarea )
+                    {
+                        float *buf = (float *) buffer;
+
+                        minarea = area;
+                        /* leftist point */
+                        ((int *) buf)[0] = seq[3];
+                        buf[1] = base_a;
+                        buf[2] = width;
+                        buf[3] = base_b;
+                        buf[4] = height;
+                        /* bottom point */
+                        ((int *) buf)[5] = seq[0];
+                        buf[6] = area;
+                    }
+                    break;
                 }
-                break;
-            }
-        }                       /*switch */
-    }                           /* for */
+            }                       /*switch */
+        }                           /* for */
 
-    switch (mode)
-    {
-    case CV_CALIPERS_MINAREARECT:
+        switch (mode)
         {
-            float *buf = (float *) buffer;
-
-            float A1 = buf[1];
-            float B1 = buf[3];
-
-            float A2 = -buf[3];
-            float B2 = buf[1];
+            case CALIPERS_MINAREARECT:
+            {
+                float *buf = (float *) buffer;
 
-            float C1 = A1 * points[((int *) buf)[0]].x + points[((int *) buf)[0]].y * B1;
-            float C2 = A2 * points[((int *) buf)[5]].x + points[((int *) buf)[5]].y * B2;
+                float A1 = buf[1];
+                float B1 = buf[3];
 
-            float idet = 1.f / (A1 * B2 - A2 * B1);
+                float A2 = -buf[3];
+                float B2 = buf[1];
 
-            float px = (C1 * B2 - C2 * B1) * idet;
-            float py = (A1 * C2 - A2 * C1) * idet;
+                float C1 = A1 * points[((int *) buf)[0]].x + points[((int *) buf)[0]].y * B1;
+                float C2 = A2 * points[((int *) buf)[5]].x + points[((int *) buf)[5]].y * B2;
 
-            out[0] = px;
-            out[1] = py;
+                float idet = 1.f / (A1 * B2 - A2 * B1);
 
-            out[2] = A1 * buf[2];
-            out[3] = B1 * buf[2];
+                float px = (C1 * B2 - C2 * B1) * idet;
+                float py = (A1 * C2 - A2 * C1) * idet;
 
-            out[4] = A2 * buf[4];
-            out[5] = B2 * buf[4];
-        }
-        break;
-    case CV_CALIPERS_MAXHEIGHT:
-        {
-            out[0] = max_dist;
+                out[0] = px;
+                out[1] = py;
+                
+                out[2] = A1 * buf[2];
+                out[3] = B1 * buf[2];
+                
+                out[4] = A2 * buf[4];
+                out[5] = B2 * buf[4];
+            }
+                break;
+            case CALIPERS_MAXHEIGHT:
+            {
+                out[0] = max_dist;
+            }
+                break;
         }
-        break;
     }
-
-    cvFree( &vect );
-    cvFree( &inv_vect_length );
+    
 }
 
 
-CV_IMPL  CvBox2D
-cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
+cv::RotatedRect cv::minAreaRect( InputArray _points )
 {
-    cv::Ptr<CvMemStorage> temp_storage;
-    CvBox2D box;
-    cv::AutoBuffer<CvPoint2D32f> _points;
-    CvPoint2D32f* points;
-
-    memset(&box, 0, sizeof(box));
-
-    int i, n;
-    CvSeqReader reader;
-    CvContour contour_header;
-    CvSeqBlock block;
-    CvSeq* ptseq = (CvSeq*)array;
-    CvPoint2D32f out[3];
-
-    if( CV_IS_SEQ(ptseq) )
-    {
-        if( !CV_IS_SEQ_POINT_SET(ptseq) &&
-            (CV_SEQ_KIND(ptseq) != CV_SEQ_KIND_CURVE ||
-            CV_SEQ_ELTYPE(ptseq) != CV_SEQ_ELTYPE_PPOINT ))
-            CV_Error( CV_StsUnsupportedFormat,
-                "Input sequence must consist of 2d points or pointers to 2d points" );
-        if( !storage )
-            storage = ptseq->storage;
-    }
-    else
-    {
-        ptseq = cvPointSeqFromMat( CV_SEQ_KIND_GENERIC, array, &contour_header, &block );
-    }
-
-    if( storage )
-    {
-        temp_storage = cvCreateChildMemStorage( storage );
-    }
-    else
+    Mat hull;
+    Point2f out[3];
+    RotatedRect box;
+    
+    convexHull(_points, hull, true, true);
+    
+    if( hull.depth() != CV_32F )
     {
-        temp_storage = cvCreateMemStorage(1 << 10);
+        Mat temp;
+        hull.convertTo(temp, CV_32F);
+        hull = temp;
     }
-
-    ptseq = cvConvexHull2( ptseq, temp_storage, CV_CLOCKWISE, 1 );
-    n = ptseq->total;
-
-    _points.allocate(n);
-    points = _points;
-    cvStartReadSeq( ptseq, &reader );
-
-    if( CV_SEQ_ELTYPE( ptseq ) == CV_32SC2 )
-    {
-        for( i = 0; i < n; i++ )
-        {
-            CvPoint pt;
-            CV_READ_SEQ_ELEM( pt, reader );
-            points[i].x = (float)pt.x;
-            points[i].y = (float)pt.y;
-        }
-    }
-    else
-    {
-        for( i = 0; i < n; i++ )
-        {
-            CV_READ_SEQ_ELEM( points[i], reader );
-        }
-    }
-
+    
+    int n = hull.checkVector(2);
+    const Point2f* hpoints = (const Point2f*)hull.data;
+    
     if( n > 2 )
     {
-        icvRotatingCalipers( points, n, CV_CALIPERS_MINAREARECT, (float*)out );
+        rotatingCalipers( hpoints, n, CALIPERS_MINAREARECT, (float*)out );
         box.center.x = out[0].x + (out[1].x + out[2].x)*0.5f;
         box.center.y = out[0].y + (out[1].y + out[2].y)*0.5f;
         box.size.width = (float)sqrt((double)out[1].x*out[1].x + (double)out[1].y*out[1].y);
@@ -421,10 +370,10 @@ cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
     }
     else if( n == 2 )
     {
-        box.center.x = (points[0].x + points[1].x)*0.5f;
-        box.center.y = (points[0].y + points[1].y)*0.5f;
-        double dx = points[1].x - points[0].x;
-        double dy = points[1].y - points[0].y;
+        box.center.x = (hpoints[0].x + hpoints[1].x)*0.5f;
+        box.center.y = (hpoints[0].y + hpoints[1].y)*0.5f;
+        double dx = hpoints[1].x - hpoints[0].x; 
+        double dy = hpoints[1].y - hpoints[0].y;
         box.size.width = (float)sqrt(dx*dx + dy*dy);
         box.size.height = 0;
         box.angle = (float)atan2( dy, dx );
@@ -432,10 +381,21 @@ cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
     else
     {
         if( n == 1 )
-            box.center = points[0];
+            box.center = hpoints[0];
     }
-
+    
     box.angle = (float)(box.angle*180/CV_PI);
     return box;
 }
 
+
+CV_IMPL CvBox2D
+cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
+{
+    cv::AutoBuffer<double> abuf;
+    cv::Mat points = cv::cvarrToMat(array, false, false, 0, &abuf);
+
+    cv::RotatedRect rr = cv::minAreaRect(points);
+    return (CvBox2D)rr;
+}
+
index b1bc1ba..7c2d1ee 100644 (file)
 //M*/
 #include "precomp.hpp"
 
-/* calculates length of a curve (e.g. contour perimeter) */
-CV_IMPL  double
-cvArcLength( const void *array, CvSlice slice, int is_closed )
+namespace cv
 {
-    double perimeter = 0;
 
-    int i, j = 0, count;
-    const int N = 16;
-    float buf[N];
-    CvMat buffer = cvMat( 1, N, CV_32F, buf );
-    CvSeqReader reader;
-    CvContour contour_header;
-    CvSeq* contour = 0;
-    CvSeqBlock block;
+static int intersectLines( double x1, double dx1, double y1, double dy1,
+                          double x2, double dx2, double y2, double dy2, double *t2 )
+{
+    double d = dx1 * dy2 - dx2 * dy1;
+    int result = -1;
 
-    if( CV_IS_SEQ( array ))
-    {
-        contour = (CvSeq*)array;
-        if( !CV_IS_SEQ_POLYLINE( contour ))
-            CV_Error( CV_StsBadArg, "Unsupported sequence type" );
-        if( is_closed < 0 )
-            is_closed = CV_IS_SEQ_CLOSED( contour );
-    }
-    else
+    if( d != 0 )
     {
-        is_closed = is_closed > 0;
-        contour = cvPointSeqFromMat(
-            CV_SEQ_KIND_CURVE | (is_closed ? CV_SEQ_FLAG_CLOSED : 0),
-            array, &contour_header, &block );
+        *t2 = ((x2 - x1) * dy1 - (y2 - y1) * dx1) / d;
+        result = 0;
     }
-
-    if( contour->total > 1 )
-    {
-        int is_float = CV_SEQ_ELTYPE( contour ) == CV_32FC2;
-
-        cvStartReadSeq( contour, &reader, 0 );
-        cvSetSeqReaderPos( &reader, slice.start_index );
-        count = cvSliceLength( slice, contour );
-
-        count -= !is_closed && count == contour->total;
-
-        /* scroll the reader by 1 point */
-        reader.prev_elem = reader.ptr;
-        CV_NEXT_SEQ_ELEM( sizeof(CvPoint), reader );
-
-        for( i = 0; i < count; i++ )
-        {
-            float dx, dy;
-
-            if( !is_float )
-            {
-                CvPoint* pt = (CvPoint*)reader.ptr;
-                CvPoint* prev_pt = (CvPoint*)reader.prev_elem;
-
-                dx = (float)pt->x - (float)prev_pt->x;
-                dy = (float)pt->y - (float)prev_pt->y;
-            }
-            else
-            {
-                CvPoint2D32f* pt = (CvPoint2D32f*)reader.ptr;
-                CvPoint2D32f* prev_pt = (CvPoint2D32f*)reader.prev_elem;
-
-                dx = pt->x - prev_pt->x;
-                dy = pt->y - prev_pt->y;
-            }
-
-            reader.prev_elem = reader.ptr;
-            CV_NEXT_SEQ_ELEM( contour->elem_size, reader );
-            // Bugfix by Axel at rubico.com 2010-03-22, affects closed slices only
-            // wraparound not handled by CV_NEXT_SEQ_ELEM
-            if( is_closed && i == count - 2 )
-                cvSetSeqReaderPos( &reader, slice.start_index );
-
-            buffer.data.fl[j] = dx * dx + dy * dy;
-            if( ++j == N || i == count - 1 )
-            {
-                buffer.cols = j;
-                cvPow( &buffer, &buffer, 0.5 );
-                for( ; j > 0; j-- )
-                    perimeter += buffer.data.fl[j-1];
-            }
-        }
-    }
-
-    return perimeter;
+    return result;
 }
 
-
-static CvStatus
-icvFindCircle( CvPoint2D32f pt0, CvPoint2D32f pt1,
-               CvPoint2D32f pt2, CvPoint2D32f * center, float *radius )
+static bool findCircle( Point2f pt0, Point2f pt1, Point2f pt2,
+                       Point2f* center, float* radius )
 {
     double x1 = (pt0.x + pt1.x) * 0.5;
     double dy1 = pt0.x - pt1.x;
@@ -142,26 +70,21 @@ icvFindCircle( CvPoint2D32f pt0, CvPoint2D32f pt1,
     double dx2 = pt2.y - pt1.y;
     double t = 0;
 
-    CvStatus result = CV_OK;
-
-    if( icvIntersectLines( x1, dx1, y1, dy1, x2, dx2, y2, dy2, &t ) >= 0 )
+    if( intersectLines( x1, dx1, y1, dy1, x2, dx2, y2, dy2, &t ) >= 0 )
     {
         center->x = (float) (x2 + dx2 * t);
         center->y = (float) (y2 + dy2 * t);
-        *radius = (float) icvDistanceL2_32f( *center, pt0 );
-    }
-    else
-    {
-        center->x = center->y = 0.f;
-        radius = 0;
-        result = CV_NOTDEFINED_ERR;
+        *radius = (float)norm(*center - pt0);
+        return true;
     }
 
-    return result;
+    center->x = center->y = 0.f;
+    radius = 0;
+    return false;
 }
 
 
-CV_INLINE double icvIsPtInCircle( CvPoint2D32f pt, CvPoint2D32f center, float radius )
+static double pointInCircle( Point2f pt, Point2f center, float radius )
 {
     double dx = pt.x - center.x;
     double dy = pt.y - center.y;
@@ -169,18 +92,17 @@ CV_INLINE double icvIsPtInCircle( CvPoint2D32f pt, CvPoint2D32f center, float ra
 }
 
 
-static int
-icvFindEnslosingCicle4pts_32f( CvPoint2D32f * pts, CvPoint2D32f * _center, float *_radius )
+static int findEnslosingCicle4pts_32f( Point2f* pts, Point2f& _center, float& _radius )
 {
     int shuffles[4][4] = { {0, 1, 2, 3}, {0, 1, 3, 2}, {2, 3, 0, 1}, {2, 3, 1, 0} };
 
     int idxs[4] = { 0, 1, 2, 3 };
     int i, j, k = 1, mi = 0;
     float max_dist = 0;
-    CvPoint2D32f center;
-    CvPoint2D32f min_center;
+    Point2f center;
+    Point2f min_center;
     float radius, min_radius = FLT_MAX;
-    CvPoint2D32f res_pts[4];
+    Point2f res_pts[4];
 
     center = min_center = pts[0];
     radius = 1.f;
@@ -188,7 +110,7 @@ icvFindEnslosingCicle4pts_32f( CvPoint2D32f * pts, CvPoint2D32f * _center, float
     for( i = 0; i < 4; i++ )
         for( j = i + 1; j < 4; j++ )
         {
-            float dist = icvDistanceL2_32f( pts[i], pts[j] );
+            float dist = norm(pts[i] - pts[j]);
 
             if( max_dist < dist )
             {
@@ -198,65 +120,62 @@ icvFindEnslosingCicle4pts_32f( CvPoint2D32f * pts, CvPoint2D32f * _center, float
             }
         }
 
-    if( max_dist == 0 )
-        goto function_exit;
-
-    k = 2;
-    for( i = 0; i < 4; i++ )
+    if( max_dist > 0 )
     {
-        for( j = 0; j < k; j++ )
-            if( i == idxs[j] )
-                break;
-        if( j == k )
-            idxs[k++] = i;
-    }
+        k = 2;
+        for( i = 0; i < 4; i++ )
+        {
+            for( j = 0; j < k; j++ )
+                if( i == idxs[j] )
+                    break;
+            if( j == k )
+                idxs[k++] = i;
+        }
 
-    center = cvPoint2D32f( (pts[idxs[0]].x + pts[idxs[1]].x)*0.5f,
-                           (pts[idxs[0]].y + pts[idxs[1]].y)*0.5f );
-    radius = (float)(icvDistanceL2_32f( pts[idxs[0]], center )*1.03);
-    if( radius < 1.f )
-        radius = 1.f;
+        center = Point2f( (pts[idxs[0]].x + pts[idxs[1]].x)*0.5f, (pts[idxs[0]].y + pts[idxs[1]].y)*0.5f );
+        radius = (float)(norm(pts[idxs[0]] - center)*1.03);
+        if( radius < 1.f )
+            radius = 1.f;
 
-    if( icvIsPtInCircle( pts[idxs[2]], center, radius ) >= 0 &&
-        icvIsPtInCircle( pts[idxs[3]], center, radius ) >= 0 )
-    {
-        k = 2; //rand()%2+2;
-    }
-    else
-    {
-        mi = -1;
-        for( i = 0; i < 4; i++ )
+        if( pointInCircle( pts[idxs[2]], center, radius ) >= 0 &&
+           pointInCircle( pts[idxs[3]], center, radius ) >= 0 )
         {
-            if( icvFindCircle( pts[shuffles[i][0]], pts[shuffles[i][1]],
-                               pts[shuffles[i][2]], &center, &radius ) >= 0 )
+            k = 2; //rand()%2+2;
+        }
+        else
+        {
+            mi = -1;
+            for( i = 0; i < 4; i++ )
             {
-                radius *= 1.03f;
-                if( radius < 2.f )
-                    radius = 2.f;
-
-                if( icvIsPtInCircle( pts[shuffles[i][3]], center, radius ) >= 0 &&
-                    min_radius > radius )
+                if( findCircle( pts[shuffles[i][0]], pts[shuffles[i][1]],
+                               pts[shuffles[i][2]], &center, &radius ) >= 0 )
                 {
-                    min_radius = radius;
-                    min_center = center;
-                    mi = i;
+                    radius *= 1.03f;
+                    if( radius < 2.f )
+                        radius = 2.f;
+
+                    if( pointInCircle( pts[shuffles[i][3]], center, radius ) >= 0 &&
+                       min_radius > radius )
+                    {
+                        min_radius = radius;
+                        min_center = center;
+                        mi = i;
+                    }
                 }
             }
+            CV_Assert( mi >= 0 );
+            if( mi < 0 )
+                mi = 0;
+            k = 3;
+            center = min_center;
+            radius = min_radius;
+            for( i = 0; i < 4; i++ )
+                idxs[i] = shuffles[mi][i];
         }
-        assert( mi >= 0 );
-        if( mi < 0 )
-            mi = 0;
-        k = 3;
-        center = min_center;
-        radius = min_radius;
-        for( i = 0; i < 4; i++ )
-            idxs[i] = shuffles[mi][i];
     }
 
-  function_exit:
-
-    *_center = center;
-    *_radius = radius;
+    _center = center;
+    _radius = radius;
 
     /* reorder output points */
     for( i = 0; i < 4; i++ )
@@ -265,159 +184,88 @@ icvFindEnslosingCicle4pts_32f( CvPoint2D32f * pts, CvPoint2D32f * _center, float
     for( i = 0; i < 4; i++ )
     {
         pts[i] = res_pts[i];
-        assert( icvIsPtInCircle( pts[i], center, radius ) >= 0 );
+        CV_Assert( pointInCircle( pts[i], center, radius ) >= 0 );
     }
 
     return k;
 }
 
+}
 
-CV_IMPL int
-cvMinEnclosingCircle( const void* array, CvPoint2D32f * _center, float *_radius )
+void cv::minEnclosingCircle( InputArray _points, Point2f& _center, float& _radius )
 {
-    const int max_iters = 100;
+    int max_iters = 100;
     const float eps = FLT_EPSILON*2;
-    CvPoint2D32f center = { 0, 0 };
-    float radius = 0;
-    int result = 0;
+    bool result = false;
+    Mat points = _points.getMat();
+    int i, j, k, count = points.checkVector(2);
+    int depth = points.depth();
+    Point2f center;
+    float radius = 0.f;
+    CV_Assert(count >= 0 && (depth == CV_32F || depth == CV_32S));
 
-    if( _center )
-        _center->x = _center->y = 0.f;
-    if( _radius )
-        *_radius = 0;
-
-    CvSeqReader reader;
-    int k, count;
-    CvPoint2D32f pts[8];
-    CvContour contour_header;
-    CvSeqBlock block;
-    CvSeq* sequence = 0;
-    int is_float;
-
-    if( !_center || !_radius )
-        CV_Error( CV_StsNullPtr, "Null center or radius pointers" );
-
-    if( CV_IS_SEQ(array) )
-    {
-        sequence = (CvSeq*)array;
-        if( !CV_IS_SEQ_POINT_SET( sequence ))
-            CV_Error( CV_StsBadArg, "The passed sequence is not a valid contour" );
-    }
-    else
-    {
-        sequence = cvPointSeqFromMat(
-            CV_SEQ_KIND_GENERIC, array, &contour_header, &block );
-    }
+    _center.x = _center.y = 0.f;
+    _radius = 0.f;
 
-    if( sequence->total <= 0 )
-        CV_Error( CV_StsBadSize, "" );
+    if( count == 0 )
+        return;
 
-    cvStartReadSeq( sequence, &reader, 0 );
+    bool is_float = depth == CV_32F;
+    const Point* ptsi = (const Point*)points.data;
+    const Point2f* ptsf = (const Point2f*)points.data;
 
-    count = sequence->total;
-    is_float = CV_SEQ_ELTYPE(sequence) == CV_32FC2;
+    Point2f pt = is_float ? ptsf[0] : Point2f((float)ptsi[0].x,(float)ptsi[0].y);
+    Point2f pts[4] = {pt, pt, pt, pt};
 
-    if( !is_float )
+    for(int i = 1; i < count; i++ )
     {
-        CvPoint *pt_left, *pt_right, *pt_top, *pt_bottom;
-        CvPoint pt;
-        pt_left = pt_right = pt_top = pt_bottom = (CvPoint *)(reader.ptr);
-        CV_READ_SEQ_ELEM( pt, reader );
-
-        for(int i = 1; i < count; i++ )
-        {
-            CvPoint* pt_ptr = (CvPoint*)reader.ptr;
-            CV_READ_SEQ_ELEM( pt, reader );
-
-            if( pt.x < pt_left->x )
-                pt_left = pt_ptr;
-            if( pt.x > pt_right->x )
-                pt_right = pt_ptr;
-            if( pt.y < pt_top->y )
-                pt_top = pt_ptr;
-            if( pt.y > pt_bottom->y )
-                pt_bottom = pt_ptr;
-        }
-
-        pts[0] = cvPointTo32f( *pt_left );
-        pts[1] = cvPointTo32f( *pt_right );
-        pts[2] = cvPointTo32f( *pt_top );
-        pts[3] = cvPointTo32f( *pt_bottom );
-    }
-    else
-    {
-        CvPoint2D32f *pt_left, *pt_right, *pt_top, *pt_bottom;
-        CvPoint2D32f pt;
-        pt_left = pt_right = pt_top = pt_bottom = (CvPoint2D32f *) (reader.ptr);
-        CV_READ_SEQ_ELEM( pt, reader );
-
-        for(int i = 1; i < count; i++ )
-        {
-            CvPoint2D32f* pt_ptr = (CvPoint2D32f*)reader.ptr;
-            CV_READ_SEQ_ELEM( pt, reader );
-
-            if( pt.x < pt_left->x )
-                pt_left = pt_ptr;
-            if( pt.x > pt_right->x )
-                pt_right = pt_ptr;
-            if( pt.y < pt_top->y )
-                pt_top = pt_ptr;
-            if( pt.y > pt_bottom->y )
-                pt_bottom = pt_ptr;
-        }
-
-        pts[0] = *pt_left;
-        pts[1] = *pt_right;
-        pts[2] = *pt_top;
-        pts[3] = *pt_bottom;
+        Point2f pt = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
+
+        if( pt.x < pts[0].x )
+            pts[0] = pt;
+        if( pt.x > pts[1].x )
+            pts[1] = pt;
+        if( pt.y < pts[2].y )
+            pts[2] = pt;
+        if( pt.y > pts[3].y )
+            pts[3] = pt;
     }
 
     for( k = 0; k < max_iters; k++ )
     {
         double min_delta = 0, delta;
-        CvPoint2D32f ptfl, farAway = { 0, 0};
+        Point2f ptf, farAway(0,0);
         /*only for first iteration because the alg is repared at the loop's foot*/
-        if(k==0)
-            icvFindEnslosingCicle4pts_32f( pts, &center, &radius );
-
-        cvStartReadSeq( sequence, &reader, 0 );
+        if( k == 0 )
+            findEnslosingCicle4pts_32f( pts, center, radius );
 
-        for(int i = 0; i < count; i++ )
+        for( i = 0; i < count; i++ )
         {
-            if( !is_float )
-            {
-                ptfl.x = (float)((CvPoint*)reader.ptr)->x;
-                ptfl.y = (float)((CvPoint*)reader.ptr)->y;
-            }
-            else
-            {
-                ptfl = *(CvPoint2D32f*)reader.ptr;
-            }
-            CV_NEXT_SEQ_ELEM( sequence->elem_size, reader );
+            ptf = is_float ? ptsf[i] : Point2f((float)ptsi[i].x,(float)ptsi[i].y);
 
-            delta = icvIsPtInCircle( ptfl, center, radius );
+            delta = pointInCircle( ptf, center, radius );
             if( delta < min_delta )
             {
                 min_delta = delta;
-                farAway = ptfl;
+                farAway = ptf;
             }
         }
         result = min_delta >= 0;
         if( result )
             break;
 
-        CvPoint2D32f ptsCopy[4];
-        /* find good replacement partner for the point which is at most far away,
-        starting with the one that lays in the actual circle (i=3) */
-        for(int i = 3; i >=0; i-- )
+        Point2f ptsCopy[4];
+        // find good replacement partner for the point which is at most far away,
+        // starting with the one that lays in the actual circle (i=3)
+        for( i = 3; i >= 0; i-- )
         {
-            for(int j = 0; j < 4; j++ )
-            {
-                ptsCopy[j]=(i != j)? pts[j]: farAway;
-            }
+            for( j = 0; j < 4; j++ )
+                ptsCopy[j] = i != j ? pts[j] : farAway;
 
-            icvFindEnslosingCicle4pts_32f(ptsCopy, &center, &radius );
-            if( icvIsPtInCircle( pts[i], center, radius )>=0){ // replaced one again in the new circle?
+            findEnslosingCicle4pts_32f( ptsCopy, center, radius );
+            if( pointInCircle( pts[i], center, radius ) >= 0)
+            {
+                // replaced one again in the new circle?
                 pts[i] = farAway;
                 break;
             }
@@ -426,121 +274,462 @@ cvMinEnclosingCircle( const void* array, CvPoint2D32f * _center, float *_radius
 
     if( !result )
     {
-        cvStartReadSeq( sequence, &reader, 0 );
         radius = 0.f;
-
         for(int i = 0; i < count; i++ )
         {
-            CvPoint2D32f ptfl;
-            float t, dx, dy;
+            Point2f ptf = is_float ? ptsf[i] : Point2f((float)ptsi[i].x,(float)ptsi[i].y);
+            float dx = center.x - ptf.x, dy = center.y - ptf.y;
+            float t = dx*dx + dy*dy;
+            radius = MAX(radius, t);
+        }
 
-            if( !is_float )
-            {
-                ptfl.x = (float)((CvPoint*)reader.ptr)->x;
-                ptfl.y = (float)((CvPoint*)reader.ptr)->y;
-            }
-            else
-            {
-                ptfl = *(CvPoint2D32f*)reader.ptr;
-            }
+        radius = (float)(sqrt(radius)*(1 + eps));
+    }
+
+    _center = center;
+    _radius = radius;
+}
+
+
+// calculates length of a curve (e.g. contour perimeter)
+double cv::arcLength( InputArray _curve, bool is_closed )
+{
+    Mat curve = _curve.getMat();
+    int count = curve.checkVector(2);
+    int depth = curve.depth();
+    CV_Assert( count >= 0 && (depth == CV_32F || depth == CV_32S));
+    double perimeter = 0;
 
-            CV_NEXT_SEQ_ELEM( sequence->elem_size, reader );
-            dx = center.x - ptfl.x;
-            dy = center.y - ptfl.y;
-            t = dx*dx + dy*dy;
-            radius = MAX(radius,t);
+    int i, j = 0;
+    const int N = 16;
+    float buf[N];
+
+    if( count <= 1 )
+        return 0.;
+
+    bool is_float = depth == CV_32F;
+    int last = is_closed ? count-1 : 0;
+    const Point* pti = (const Point*)curve.data;
+    const Point2f* ptf = (const Point2f*)curve.data;
+
+    Point2f prev = is_float ? ptf[last] : Point2f((float)pti[last].x,(float)pti[last].y);
+
+    for( i = 0; i < count; i++ )
+    {
+        Point2f p = is_float ? ptf[i] : Point2f((float)pti[i].x,(float)pti[i].y);
+        float dx = p.x - prev.x, dy = p.y - prev.y;
+        buf[j] = dx*dx + dy*dy;
+
+        if( ++j == N || i == count-1 )
+        {
+            Mat bufmat(1, j, CV_32F, buf);
+            sqrt(bufmat, bufmat);
+            for( ; j > 0; j-- )
+                perimeter += buf[j-1];
         }
+        prev = p;
+    }
 
-        radius = (float)(sqrt(radius)*(1 + eps));
-        result = 1;
+    return perimeter;
+}
+
+// area of a whole sequence
+double cv::contourArea( InputArray _contour, bool oriented )
+{
+    Mat contour = _contour.getMat();
+    int npoints = contour.checkVector(2);
+    int depth = contour.depth();
+    CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_32S));
+
+    if( npoints == 0 )
+        return 0.;
+
+    double a00 = 0;
+    bool is_float = depth == CV_32F;
+    const Point* ptsi = (const Point*)contour.data;
+    const Point2f* ptsf = (const Point2f*)contour.data;
+    Point2f prev = is_float ? ptsf[npoints-1] : Point2f((float)ptsi[npoints-1].x, (float)ptsi[npoints-1].y);
+
+    for( int i = 0; i < npoints; i++ )
+    {
+        Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
+        a00 += (double)prev.x * p.y - (double)prev.y * p.x;
+        prev = p;
     }
 
-    *_center = center;
-    *_radius = radius;
+    a00 *= 0.5;
+    if( !oriented )
+        a00 = fabs(a00);
 
-    return result;
+    return a00;
 }
 
 
-/* area of a whole sequence */
-static CvStatus
-icvContourArea( const CvSeq* contour, double *area )
+cv::RotatedRect cv::fitEllipse( InputArray _points )
 {
-    if( contour->total )
+    Mat points = _points.getMat();
+    int i, n = points.checkVector(2);
+    int depth = points.depth();
+    CV_Assert( n >= 0 && (depth == CV_32F || depth == CV_32S));
+
+    RotatedRect box;
+
+    if( n < 5 )
+        CV_Error( CV_StsBadSize, "There should be at least 5 points to fit the ellipse" );
+
+    // New fitellipse algorithm, contributed by Dr. Daniel Weiss
+    Point2f c(0,0);
+    double gfp[5], rp[5], t;
+    const double min_eps = 1e-6;
+    bool is_float = depth == CV_32F;
+    const Point* ptsi = (const Point*)points.data;
+    const Point2f* ptsf = (const Point2f*)points.data;
+
+    AutoBuffer<double> _Ad(n*5), _bd(n);
+    double *Ad = _Ad, *bd = _bd;
+
+    // first fit for parameters A - E
+    Mat A( n, 5, CV_64F, Ad );
+    Mat b( n, 1, CV_64F, bd );
+    Mat x( 5, 1, CV_64F, gfp );
+
+    for( i = 0; i < n; i++ )
+    {
+        Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
+        c += p;
+    }
+    c.x /= n;
+    c.y /= n;
+
+    for( i = 0; i < n; i++ )
     {
-        CvSeqReader reader;
-        int lpt = contour->total;
-        double a00 = 0, xi_1, yi_1;
-        int is_float = CV_SEQ_ELTYPE(contour) == CV_32FC2;
+        Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
+        p -= c;
 
-        cvStartReadSeq( contour, &reader, 0 );
+        bd[i] = 10000.0; // 1.0?
+        Ad[i*5] = -(double)p.x * p.x; // A - C signs inverted as proposed by APP
+        Ad[i*5 + 1] = -(double)p.y * p.y;
+        Ad[i*5 + 2] = -(double)p.x * p.y;
+        Ad[i*5 + 3] = p.x;
+        Ad[i*5 + 4] = p.y;
+    }
+
+    solve(A, b, x, DECOMP_SVD);
+
+    // now use general-form parameters A - E to find the ellipse center:
+    // differentiate general form wrt x/y to get two equations for cx and cy
+    A = Mat( 2, 2, CV_64F, Ad );
+    b = Mat( 2, 1, CV_64F, bd );
+    x = Mat( 2, 1, CV_64F, rp );
+    Ad[0] = 2 * gfp[0];
+    Ad[1] = Ad[2] = gfp[2];
+    Ad[3] = 2 * gfp[1];
+    bd[0] = gfp[3];
+    bd[1] = gfp[4];
+    solve( A, b, x, DECOMP_SVD );
+    
+    // re-fit for parameters A - C with those center coordinates
+    A = Mat( n, 3, CV_64F, Ad );
+    b = Mat( n, 1, CV_64F, bd );
+    x = Mat( 3, 1, CV_64F, gfp );
+    for( i = 0; i < n; i++ )
+    {
+        Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
+        p -= c;
+        bd[i] = 1.0;
+        Ad[i * 3] = (p.x - rp[0]) * (p.x - rp[0]);
+        Ad[i * 3 + 1] = (p.y - rp[1]) * (p.y - rp[1]);
+        Ad[i * 3 + 2] = (p.x - rp[0]) * (p.y - rp[1]);
+    }
+    solve(A, b, x, DECOMP_SVD);
+    
+    // store angle and radii
+    rp[4] = -0.5 * atan2(gfp[2], gfp[1] - gfp[0]); // convert from APP angle usage
+    t = sin(-2.0 * rp[4]);
+    if( fabs(t) > fabs(gfp[2])*min_eps )
+        t = gfp[2]/t;
+    else
+        t = gfp[1] - gfp[0];
+    rp[2] = fabs(gfp[0] + gfp[1] - t);
+    if( rp[2] > min_eps )
+        rp[2] = sqrt(2.0 / rp[2]);
+    rp[3] = fabs(gfp[0] + gfp[1] + t);
+    if( rp[3] > min_eps )
+        rp[3] = sqrt(2.0 / rp[3]);
+    
+    box.center.x = (float)rp[0] + c.x;
+    box.center.y = (float)rp[1] + c.y;
+    box.size.width = (float)(rp[2]*2);
+    box.size.height = (float)(rp[3]*2);
+    if( box.size.width > box.size.height )
+    {
+        float tmp;
+        CV_SWAP( box.size.width, box.size.height, tmp );
+        box.angle = (float)(90 + rp[4]*180/CV_PI);
+    }
+    if( box.angle < -180 )
+        box.angle += 360;
+    if( box.angle > 360 )
+        box.angle -= 360;
+    
+    return box;
+}
+
+
+namespace cv
+{
+
+// Calculates bounding rectagnle of a point set or retrieves already calculated
+static Rect pointSetBoundingRect( const Mat& points )
+{
+    int npoints = points.checkVector(2);
+    int depth = points.depth();
+    CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_32S));
+
+    int  xmin = 0, ymin = 0, xmax = -1, ymax = -1, i;
+    bool is_float = depth == CV_32F;
 
+    if( npoints == 0 )
+        return Rect();
+
+    const Point* pts = (const Point*)points.data;
+    Point pt = pts[0];
+
+#if CV_SSE4_2
+    if(cv::checkHardwareSupport(CV_CPU_SSE4_2))
+    {
         if( !is_float )
         {
-            xi_1 = ((CvPoint*)(reader.ptr))->x;
-            yi_1 = ((CvPoint*)(reader.ptr))->y;
+            __m128i minval, maxval;
+            minval = maxval = _mm_loadl_epi64((const __m128i*)(&pt)); //min[0]=pt.x, min[1]=pt.y
+
+            for( i = 1; i < npoints; i++ )
+            {
+                __m128i ptXY = _mm_loadl_epi64((const __m128i*)&pts[i]);
+                minval = _mm_min_epi32(ptXY, minval);
+                maxval = _mm_max_epi32(ptXY, maxval);
+            }
+            xmin = _mm_cvtsi128_si32(minval);
+            ymin = _mm_cvtsi128_si32(_mm_srli_si128(minval, 4));
+            xmax = _mm_cvtsi128_si32(maxval);
+            ymax = _mm_cvtsi128_si32(_mm_srli_si128(maxval, 4));
         }
         else
         {
-            xi_1 = ((CvPoint2D32f*)(reader.ptr))->x;
-            yi_1 = ((CvPoint2D32f*)(reader.ptr))->y;
-        }
-        CV_NEXT_SEQ_ELEM( contour->elem_size, reader );
+            __m128 minvalf, maxvalf, z = _mm_setzero_ps(), ptXY = _mm_setzero_ps();
+            minvalf = maxvalf = _mm_loadl_pi(z, (const __m64*)(&pt));
+
+            for( i = 1; i < npoints; i++ )
+            {
+                ptXY = _mm_loadl_pi(ptXY, (const __m64*)&pts[i]);
+
+                minvalf = _mm_min_ps(minvalf, ptXY);
+                maxvalf = _mm_max_ps(maxvalf, ptXY);
+            }
 
-        while( lpt-- > 0 )
+            float xyminf[2], xymaxf[2];
+            _mm_storel_pi((__m64*)xyminf, minvalf);
+            _mm_storel_pi((__m64*)xymaxf, maxvalf);
+            xmin = cvFloor(xyminf[0]);
+            ymin = cvFloor(xyminf[1]);
+            xmax = cvFloor(xymaxf[0]);
+            ymax = cvFloor(xymaxf[1]);
+        }
+    }
+    else
+#endif
+    {
+        if( !is_float )
         {
-            double dxy, xi, yi;
+            xmin = xmax = pt.x;
+            ymin = ymax = pt.y;
 
-            if( !is_float )
+            for( i = 1; i < npoints; i++ )
             {
-                xi = ((CvPoint*)(reader.ptr))->x;
-                yi = ((CvPoint*)(reader.ptr))->y;
+                pt = pts[i];
+
+                if( xmin > pt.x )
+                    xmin = pt.x;
+
+                if( xmax < pt.x )
+                    xmax = pt.x;
+
+                if( ymin > pt.y )
+                    ymin = pt.y;
+
+                if( ymax < pt.y )
+                    ymax = pt.y;
             }
-            else
+        }
+        else
+        {
+            Cv32suf v;
+            // init values
+            xmin = xmax = CV_TOGGLE_FLT(pt.x);
+            ymin = ymax = CV_TOGGLE_FLT(pt.y);
+
+            for( i = 1; i < npoints; i++ )
             {
-                xi = ((CvPoint2D32f*)(reader.ptr))->x;
-                yi = ((CvPoint2D32f*)(reader.ptr))->y;
+                pt = pts[i];
+                pt.x = CV_TOGGLE_FLT(pt.x);
+                pt.y = CV_TOGGLE_FLT(pt.y);
+
+                if( xmin > pt.x )
+                    xmin = pt.x;
+
+                if( xmax < pt.x )
+                    xmax = pt.x;
+
+                if( ymin > pt.y )
+                    ymin = pt.y;
+
+                if( ymax < pt.y )
+                    ymax = pt.y;
             }
-            CV_NEXT_SEQ_ELEM( contour->elem_size, reader );
 
-            dxy = xi_1 * yi - xi * yi_1;
-            a00 += dxy;
-            xi_1 = xi;
-            yi_1 = yi;
+            v.i = CV_TOGGLE_FLT(xmin); xmin = cvFloor(v.f);
+            v.i = CV_TOGGLE_FLT(ymin); ymin = cvFloor(v.f);
+            // because right and bottom sides of the bounding rectangle are not inclusive
+            // (note +1 in width and height calculation below), cvFloor is used here instead of cvCeil
+            v.i = CV_TOGGLE_FLT(xmax); xmax = cvFloor(v.f);
+            v.i = CV_TOGGLE_FLT(ymax); ymax = cvFloor(v.f);
         }
-
-        *area = a00 * 0.5;
     }
-    else
-        *area = 0;
+    
+    return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
+}
+
 
-    return CV_OK;
+static Rect maskBoundingRect( const Mat& img )
+{
+    CV_Assert( img.depth() <= CV_8S && img.channels() == 1 );
+
+    Size size = img.size();
+    int xmin = size.width, ymin = -1, xmax = -1, ymax = -1, i, j, k;
+
+    for( i = 0; i < size.height; i++ )
+    {
+        const uchar* _ptr = img.ptr(i);
+        const uchar* ptr = (const uchar*)alignPtr(_ptr, 4);
+        int have_nz = 0, k_min, offset = (int)(ptr - _ptr);
+        j = 0;
+        offset = MIN(offset, size.width);
+        for( ; j < offset; j++ )
+            if( _ptr[j] )
+            {
+                have_nz = 1;
+                break;
+            }
+        if( j < offset )
+        {
+            if( j < xmin )
+                xmin = j;
+            if( j > xmax )
+                xmax = j;
+        }
+        if( offset < size.width )
+        {
+            xmin -= offset;
+            xmax -= offset;
+            size.width -= offset;
+            j = 0;
+            for( ; j <= xmin - 4; j += 4 )
+                if( *((int*)(ptr+j)) )
+                    break;
+            for( ; j < xmin; j++ )
+                if( ptr[j] )
+                {
+                    xmin = j;
+                    if( j > xmax )
+                        xmax = j;
+                    have_nz = 1;
+                    break;
+                }
+            k_min = MAX(j-1, xmax);
+            k = size.width - 1;
+            for( ; k > k_min && (k&3) != 3; k-- )
+                if( ptr[k] )
+                    break;
+            if( k > k_min && (k&3) == 3 )
+            {
+                for( ; k > k_min+3; k -= 4 )
+                    if( *((int*)(ptr+k-3)) )
+                        break;
+            }
+            for( ; k > k_min; k-- )
+                if( ptr[k] )
+                {
+                    xmax = k;
+                    have_nz = 1;
+                    break;
+                }
+            if( !have_nz )
+            {
+                j &= ~3;
+                for( ; j <= k - 3; j += 4 )
+                    if( *((int*)(ptr+j)) )
+                        break;
+                for( ; j <= k; j++ )
+                    if( ptr[j] )
+                    {
+                        have_nz = 1;
+                        break;
+                    }
+            }
+            xmin += offset;
+            xmax += offset;
+            size.width += offset;
+        }
+        if( have_nz )
+        {
+            if( ymin < 0 )
+                ymin = i;
+            ymax = i;
+        }
+    }
+    
+    if( xmin >= size.width )
+        xmin = ymin = 0;
+    return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
 }
 
+}
 
-/****************************************************************************************\
+cv::Rect cv::boundingRect(InputArray array)
+{
+    Mat m = array.getMat();
+    return m.depth() <= CV_8U ? maskBoundingRect(m) : pointSetBoundingRect(m);
+}
 
- copy data from one buffer to other buffer
+////////////////////////////////////////////// C API ///////////////////////////////////////////
 
-\****************************************************************************************/
+CV_IMPL int
+cvMinEnclosingCircle( const void* array, CvPoint2D32f * _center, float *_radius )
+{
+    cv::AutoBuffer<double> abuf;
+    cv::Mat points = cv::cvarrToMat(array, false, false, 0, &abuf);
+    cv::Point2f center;
+    float radius;
+
+    cv::minEnclosingCircle(points, center, radius);
+    if(_center)
+        *_center = center;
+    if(_radius)
+        *_radius = radius;
+    return 1;
+}
 
-static CvStatus
+static void
 icvMemCopy( double **buf1, double **buf2, double **buf3, int *b_max )
 {
-    int bb;
-
-    if( (*buf1 == NULL && *buf2 == NULL) || *buf3 == NULL )
-        return CV_NULLPTR_ERR;
+    CV_Assert( (*buf1 != NULL || *buf2 != NULL) && *buf3 != NULL );
 
-    bb = *b_max;
+    int bb = *b_max;
     if( *buf2 == NULL )
     {
         *b_max = 2 * (*b_max);
         *buf2 = (double *)cvAlloc( (*b_max) * sizeof( double ));
 
-        if( *buf2 == NULL )
-            return CV_OUTOFMEM_ERR;
-
         memcpy( *buf2, *buf3, bb * sizeof( double ));
 
         *buf3 = *buf2;
@@ -552,21 +741,17 @@ icvMemCopy( double **buf1, double **buf2, double **buf3, int *b_max )
         *b_max = 2 * (*b_max);
         *buf1 = (double *) cvAlloc( (*b_max) * sizeof( double ));
 
-        if( *buf1 == NULL )
-            return CV_OUTOFMEM_ERR;
-
         memcpy( *buf1, *buf3, bb * sizeof( double ));
 
         *buf3 = *buf1;
         cvFree( buf2 );
         *buf2 = NULL;
     }
-    return CV_OK;
 }
 
 
 /* area of a contour sector */
-static CvStatus icvContourSecArea( CvSeq * contour, CvSlice slice, double *area )
+static double icvContourSecArea( CvSeq * contour, CvSlice slice )
 {
     CvPoint pt;                 /*  pointer to points   */
     CvPoint pt_s, pt_e;         /*  first and last points  */
@@ -579,14 +764,9 @@ static CvStatus icvContourSecArea( CvSeq * contour, CvSlice slice, double *area
     double x_s, y_s, nx, ny, dx, dy, du, dv;
     double eps = 1.e-5;
     double *p_are1, *p_are2, *p_are;
+    double area = 0;
 
-    assert( contour != NULL );
-
-    if( contour == NULL )
-        return CV_NULLPTR_ERR;
-
-    if( !CV_IS_SEQ_POINT_SET( contour ))
-        return CV_BADFLAG_ERR;
+    CV_Assert( contour != NULL && CV_IS_SEQ_POINT_SET( contour ));
 
     lpt = cvSliceLength( slice, contour );
     /*if( n2 >= n1 )
@@ -594,143 +774,138 @@ static CvStatus icvContourSecArea( CvSeq * contour, CvSlice slice, double *area
     else
         lpt = contour->total - n1 + n2 + 1;*/
 
-    if( contour->total && lpt > 2 )
-    {
-        a00 = x0 = y0 = xi_1 = yi_1 = 0;
-        sk1 = 0;
-        flag = 0;
-        dxy = 0;
-        p_are1 = (double *) cvAlloc( p_max * sizeof( double ));
+    if( contour->total <= 0 || lpt <= 2 )
+        return 0.;
 
-        if( p_are1 == NULL )
-            return CV_OUTOFMEM_ERR;
+    a00 = x0 = y0 = xi_1 = yi_1 = 0;
+    sk1 = 0;
+    flag = 0;
+    dxy = 0;
+    p_are1 = (double *) cvAlloc( p_max * sizeof( double ));
 
-        p_are = p_are1;
-        p_are2 = NULL;
+    p_are = p_are1;
+    p_are2 = NULL;
 
-        cvStartReadSeq( contour, &reader, 0 );
-        cvSetSeqReaderPos( &reader, slice.start_index );
-        CV_READ_SEQ_ELEM( pt_s, reader );
-        p_ind = 0;
-        cvSetSeqReaderPos( &reader, slice.end_index );
-        CV_READ_SEQ_ELEM( pt_e, reader );
+    cvStartReadSeq( contour, &reader, 0 );
+    cvSetSeqReaderPos( &reader, slice.start_index );
+    CV_READ_SEQ_ELEM( pt_s, reader );
+    p_ind = 0;
+    cvSetSeqReaderPos( &reader, slice.end_index );
+    CV_READ_SEQ_ELEM( pt_e, reader );
 
 /*    normal coefficients    */
-        nx = pt_s.y - pt_e.y;
-        ny = pt_e.x - pt_s.x;
-        cvSetSeqReaderPos( &reader, slice.start_index );
+    nx = pt_s.y - pt_e.y;
+    ny = pt_e.x - pt_s.x;
+    cvSetSeqReaderPos( &reader, slice.start_index );
 
-        while( lpt-- > 0 )
-        {
-            CV_READ_SEQ_ELEM( pt, reader );
+    while( lpt-- > 0 )
+    {
+        CV_READ_SEQ_ELEM( pt, reader );
 
-            if( flag == 0 )
-            {
-                xi_1 = (double) pt.x;
-                yi_1 = (double) pt.y;
-                x0 = xi_1;
-                y0 = yi_1;
-                sk1 = 0;
-                flag = 1;
-            }
-            else
-            {
-                xi = (double) pt.x;
-                yi = (double) pt.y;
+        if( flag == 0 )
+        {
+            xi_1 = (double) pt.x;
+            yi_1 = (double) pt.y;
+            x0 = xi_1;
+            y0 = yi_1;
+            sk1 = 0;
+            flag = 1;
+        }
+        else
+        {
+            xi = (double) pt.x;
+            yi = (double) pt.y;
 
 /****************   edges intersection examination   **************************/
-                sk = nx * (xi - pt_s.x) + ny * (yi - pt_s.y);
-                if( (fabs( sk ) < eps && lpt > 0) || sk * sk1 < -eps )
+            sk = nx * (xi - pt_s.x) + ny * (yi - pt_s.y);
+            if( (fabs( sk ) < eps && lpt > 0) || sk * sk1 < -eps )
+            {
+                if( fabs( sk ) < eps )
+                {
+                    dxy = xi_1 * yi - xi * yi_1;
+                    a00 = a00 + dxy;
+                    dxy = xi * y0 - x0 * yi;
+                    a00 = a00 + dxy;
+
+                    if( p_ind >= p_max )
+                        icvMemCopy( &p_are1, &p_are2, &p_are, &p_max );
+
+                    p_are[p_ind] = a00 / 2.;
+                    p_ind++;
+                    a00 = 0;
+                    sk1 = 0;
+                    x0 = xi;
+                    y0 = yi;
+                    dxy = 0;
+                }
+                else
                 {
-                    if( fabs( sk ) < eps )
+/*  define intersection point    */
+                    dv = yi - yi_1;
+                    du = xi - xi_1;
+                    dx = ny;
+                    dy = -nx;
+                    if( fabs( du ) > eps )
+                        t = ((yi_1 - pt_s.y) * du + dv * (pt_s.x - xi_1)) /
+                            (du * dy - dx * dv);
+                    else
+                        t = (xi_1 - pt_s.x) / dx;
+                    if( t > eps && t < 1 - eps )
                     {
-                        dxy = xi_1 * yi - xi * yi_1;
-                        a00 = a00 + dxy;
-                        dxy = xi * y0 - x0 * yi;
-                        a00 = a00 + dxy;
-
+                        x_s = pt_s.x + t * dx;
+                        y_s = pt_s.y + t * dy;
+                        dxy = xi_1 * y_s - x_s * yi_1;
+                        a00 += dxy;
+                        dxy = x_s * y0 - x0 * y_s;
+                        a00 += dxy;
                         if( p_ind >= p_max )
                             icvMemCopy( &p_are1, &p_are2, &p_are, &p_max );
 
                         p_are[p_ind] = a00 / 2.;
                         p_ind++;
+
                         a00 = 0;
                         sk1 = 0;
-                        x0 = xi;
-                        y0 = yi;
-                        dxy = 0;
-                    }
-                    else
-                    {
-/*  define intersection point    */
-                        dv = yi - yi_1;
-                        du = xi - xi_1;
-                        dx = ny;
-                        dy = -nx;
-                        if( fabs( du ) > eps )
-                            t = ((yi_1 - pt_s.y) * du + dv * (pt_s.x - xi_1)) /
-                                (du * dy - dx * dv);
-                        else
-                            t = (xi_1 - pt_s.x) / dx;
-                        if( t > eps && t < 1 - eps )
-                        {
-                            x_s = pt_s.x + t * dx;
-                            y_s = pt_s.y + t * dy;
-                            dxy = xi_1 * y_s - x_s * yi_1;
-                            a00 += dxy;
-                            dxy = x_s * y0 - x0 * y_s;
-                            a00 += dxy;
-                            if( p_ind >= p_max )
-                                icvMemCopy( &p_are1, &p_are2, &p_are, &p_max );
-
-                            p_are[p_ind] = a00 / 2.;
-                            p_ind++;
-
-                            a00 = 0;
-                            sk1 = 0;
-                            x0 = x_s;
-                            y0 = y_s;
-                            dxy = x_s * yi - xi * y_s;
-                        }
+                        x0 = x_s;
+                        y0 = y_s;
+                        dxy = x_s * yi - xi * y_s;
                     }
                 }
-                else
-                    dxy = xi_1 * yi - xi * yi_1;
+            }
+            else
+                dxy = xi_1 * yi - xi * yi_1;
 
-                a00 += dxy;
-                xi_1 = xi;
-                yi_1 = yi;
-                sk1 = sk;
+            a00 += dxy;
+            xi_1 = xi;
+            yi_1 = yi;
+            sk1 = sk;
 
-            }
         }
+    }
 
-        xi = x0;
-        yi = y0;
-        dxy = xi_1 * yi - xi * yi_1;
+    xi = x0;
+    yi = y0;
+    dxy = xi_1 * yi - xi * yi_1;
 
-        a00 += dxy;
+    a00 += dxy;
 
-        if( p_ind >= p_max )
-            icvMemCopy( &p_are1, &p_are2, &p_are, &p_max );
+    if( p_ind >= p_max )
+        icvMemCopy( &p_are1, &p_are2, &p_are, &p_max );
 
-        p_are[p_ind] = a00 / 2.;
-        p_ind++;
+    p_are[p_ind] = a00 / 2.;
+    p_ind++;
 
-/*     common area calculation    */
-        *area = 0;
-        for( i = 0; i < p_ind; i++ )
-            (*area) += fabs( p_are[i] );
+    // common area calculation
+    area = 0;
+    for( i = 0; i < p_ind; i++ )
+        area += fabs( p_are[i] );
 
-        if( p_are1 != NULL )
-            cvFree( &p_are1 );
-        else if( p_are2 != NULL )
-            cvFree( &p_are2 );
+    if( p_are1 != NULL )
+        cvFree( &p_are1 );
+    else if( p_are2 != NULL )
+        cvFree( &p_are2 );
 
-        return CV_OK;
-    }
-    else
-        return CV_BADSIZE_ERR;
+    return area;
 }
 
 
@@ -757,178 +932,115 @@ cvContourArea( const void *array, CvSlice slice, int oriented )
 
     if( cvSliceLength( slice, contour ) == contour->total )
     {
-        IPPI_CALL( icvContourArea( contour, &area ));
-    }
-    else
-    {
-        if( CV_SEQ_ELTYPE( contour ) != CV_32SC2 )
-            CV_Error( CV_StsUnsupportedFormat,
-            "Only curves with integer coordinates are supported in case of contour slice" );
-        IPPI_CALL( icvContourSecArea( contour, slice, &area ));
+        cv::AutoBuffer<double> abuf;
+        cv::Mat points = cv::cvarrToMat(contour, false, false, 0, &abuf);
+        return cv::contourArea( points, oriented !=0 );
     }
 
+    if( CV_SEQ_ELTYPE( contour ) != CV_32SC2 )
+        CV_Error( CV_StsUnsupportedFormat,
+        "Only curves with integer coordinates are supported in case of contour slice" );
+    area = icvContourSecArea( contour, slice );
     return oriented ? area : fabs(area);
 }
 
 
-CV_IMPL CvBox2D
-cvFitEllipse2( const CvArr* array )
+/* calculates length of a curve (e.g. contour perimeter) */
+CV_IMPL  double
+cvArcLength( const void *array, CvSlice slice, int is_closed )
 {
-    CvBox2D box;
-    cv::AutoBuffer<double> Ad, bd;
-    memset( &box, 0, sizeof(box));
+    double perimeter = 0;
 
+    int i, j = 0, count;
+    const int N = 16;
+    float buf[N];
+    CvMat buffer = cvMat( 1, N, CV_32F, buf );
+    CvSeqReader reader;
     CvContour contour_header;
-    CvSeq* ptseq = 0;
+    CvSeq* contour = 0;
     CvSeqBlock block;
-    int n;
 
     if( CV_IS_SEQ( array ))
     {
-        ptseq = (CvSeq*)array;
-        if( !CV_IS_SEQ_POINT_SET( ptseq ))
+        contour = (CvSeq*)array;
+        if( !CV_IS_SEQ_POLYLINE( contour ))
             CV_Error( CV_StsBadArg, "Unsupported sequence type" );
+        if( is_closed < 0 )
+            is_closed = CV_IS_SEQ_CLOSED( contour );
     }
     else
     {
-        ptseq = cvPointSeqFromMat(CV_SEQ_KIND_GENERIC, array, &contour_header, &block);
+        is_closed = is_closed > 0;
+        contour = cvPointSeqFromMat(
+                                    CV_SEQ_KIND_CURVE | (is_closed ? CV_SEQ_FLAG_CLOSED : 0),
+                                    array, &contour_header, &block );
     }
 
-    n = ptseq->total;
-    if( n < 5 )
-        CV_Error( CV_StsBadSize, "Number of points should be >= 5" );
-
-    /*
-     *  New fitellipse algorithm, contributed by Dr. Daniel Weiss
-     */
-    CvPoint2D32f c = {0,0};
-    double gfp[5], rp[5], t;
-    CvMat A, b, x;
-    const double min_eps = 1e-6;
-    int i, is_float;
-    CvSeqReader reader;
+    if( contour->total > 1 )
+    {
+        int is_float = CV_SEQ_ELTYPE( contour ) == CV_32FC2;
 
-    Ad.allocate(n*5);
-    bd.allocate(n);
+        cvStartReadSeq( contour, &reader, 0 );
+        cvSetSeqReaderPos( &reader, slice.start_index );
+        count = cvSliceLength( slice, contour );
 
-    // first fit for parameters A - E
-    A = cvMat( n, 5, CV_64F, Ad );
-    b = cvMat( n, 1, CV_64F, bd );
-    x = cvMat( 5, 1, CV_64F, gfp );
+        count -= !is_closed && count == contour->total;
 
-    cvStartReadSeq( ptseq, &reader );
-    is_float = CV_SEQ_ELTYPE(ptseq) == CV_32FC2;
+        // scroll the reader by 1 point
+        reader.prev_elem = reader.ptr;
+        CV_NEXT_SEQ_ELEM( sizeof(CvPoint), reader );
 
-    for( i = 0; i < n; i++ )
-    {
-        CvPoint2D32f p;
-        if( is_float )
-            p = *(CvPoint2D32f*)(reader.ptr);
-        else
+        for( i = 0; i < count; i++ )
         {
-            p.x = (float)((int*)reader.ptr)[0];
-            p.y = (float)((int*)reader.ptr)[1];
-        }
-        CV_NEXT_SEQ_ELEM( sizeof(p), reader );
-        c.x += p.x;
-        c.y += p.y;
-    }
-    c.x /= n;
-    c.y /= n;
+            float dx, dy;
 
-    for( i = 0; i < n; i++ )
-    {
-        CvPoint2D32f p;
-        if( is_float )
-            p = *(CvPoint2D32f*)(reader.ptr);
-        else
-        {
-            p.x = (float)((int*)reader.ptr)[0];
-            p.y = (float)((int*)reader.ptr)[1];
-        }
-        CV_NEXT_SEQ_ELEM( sizeof(p), reader );
-        p.x -= c.x;
-        p.y -= c.y;
+            if( !is_float )
+            {
+                CvPoint* pt = (CvPoint*)reader.ptr;
+                CvPoint* prev_pt = (CvPoint*)reader.prev_elem;
 
-        bd[i] = 10000.0; // 1.0?
-        Ad[i*5] = -(double)p.x * p.x; // A - C signs inverted as proposed by APP
-        Ad[i*5 + 1] = -(double)p.y * p.y;
-        Ad[i*5 + 2] = -(double)p.x * p.y;
-        Ad[i*5 + 3] = p.x;
-        Ad[i*5 + 4] = p.y;
-    }
+                dx = (float)pt->x - (float)prev_pt->x;
+                dy = (float)pt->y - (float)prev_pt->y;
+            }
+            else
+            {
+                CvPoint2D32f* pt = (CvPoint2D32f*)reader.ptr;
+                CvPoint2D32f* prev_pt = (CvPoint2D32f*)reader.prev_elem;
 
-    cvSolve( &A, &b, &x, CV_SVD );
+                dx = pt->x - prev_pt->x;
+                dy = pt->y - prev_pt->y;
+            }
 
-    // now use general-form parameters A - E to find the ellipse center:
-    // differentiate general form wrt x/y to get two equations for cx and cy
-    A = cvMat( 2, 2, CV_64F, Ad );
-    b = cvMat( 2, 1, CV_64F, bd );
-    x = cvMat( 2, 1, CV_64F, rp );
-    Ad[0] = 2 * gfp[0];
-    Ad[1] = Ad[2] = gfp[2];
-    Ad[3] = 2 * gfp[1];
-    bd[0] = gfp[3];
-    bd[1] = gfp[4];
-    cvSolve( &A, &b, &x, CV_SVD );
+            reader.prev_elem = reader.ptr;
+            CV_NEXT_SEQ_ELEM( contour->elem_size, reader );
+            // Bugfix by Axel at rubico.com 2010-03-22, affects closed slices only
+            // wraparound not handled by CV_NEXT_SEQ_ELEM
+            if( is_closed && i == count - 2 )
+                cvSetSeqReaderPos( &reader, slice.start_index );
 
-    // re-fit for parameters A - C with those center coordinates
-    A = cvMat( n, 3, CV_64F, Ad );
-    b = cvMat( n, 1, CV_64F, bd );
-    x = cvMat( 3, 1, CV_64F, gfp );
-    for( i = 0; i < n; i++ )
-    {
-        CvPoint2D32f p;
-        if( is_float )
-            p = *(CvPoint2D32f*)(reader.ptr);
-        else
-        {
-            p.x = (float)((int*)reader.ptr)[0];
-            p.y = (float)((int*)reader.ptr)[1];
+            buffer.data.fl[j] = dx * dx + dy * dy;
+            if( ++j == N || i == count - 1 )
+            {
+                buffer.cols = j;
+                cvPow( &buffer, &buffer, 0.5 );
+                for( ; j > 0; j-- )
+                    perimeter += buffer.data.fl[j-1];
+            }
         }
-        CV_NEXT_SEQ_ELEM( sizeof(p), reader );
-        p.x -= c.x;
-        p.y -= c.y;
-        bd[i] = 1.0;
-        Ad[i * 3] = (p.x - rp[0]) * (p.x - rp[0]);
-        Ad[i * 3 + 1] = (p.y - rp[1]) * (p.y - rp[1]);
-        Ad[i * 3 + 2] = (p.x - rp[0]) * (p.y - rp[1]);
     }
-    cvSolve(&A, &b, &x, CV_SVD);
-
-    // store angle and radii
-    rp[4] = -0.5 * atan2(gfp[2], gfp[1] - gfp[0]); // convert from APP angle usage
-    t = sin(-2.0 * rp[4]);
-    if( fabs(t) > fabs(gfp[2])*min_eps )
-        t = gfp[2]/t;
-    else
-        t = gfp[1] - gfp[0];
-    rp[2] = fabs(gfp[0] + gfp[1] - t);
-    if( rp[2] > min_eps )
-        rp[2] = sqrt(2.0 / rp[2]);
-    rp[3] = fabs(gfp[0] + gfp[1] + t);
-    if( rp[3] > min_eps )
-        rp[3] = sqrt(2.0 / rp[3]);
+    
+    return perimeter;
+}
 
-    box.center.x = (float)rp[0] + c.x;
-    box.center.y = (float)rp[1] + c.y;
-    box.size.width = (float)(rp[2]*2);
-    box.size.height = (float)(rp[3]*2);
-    if( box.size.width > box.size.height )
-    {
-        float tmp;
-        CV_SWAP( box.size.width, box.size.height, tmp );
-        box.angle = (float)(90 + rp[4]*180/CV_PI);
-    }
-    if( box.angle < -180 )
-        box.angle += 360;
-    if( box.angle > 360 )
-        box.angle -= 360;
 
-    return box;
+CV_IMPL CvBox2D
+cvFitEllipse2( const CvArr* array )
+{
+    cv::AutoBuffer<double> abuf;
+    cv::Mat points = cv::cvarrToMat(array, false, false, 0, &abuf);
+    return cv::fitEllipse(points);
 }
 
-
 /* Calculates bounding rectagnle of a point set or retrieves already calculated */
 CV_IMPL  CvRect
 cvBoundingRect( CvArr* array, int update )
@@ -977,210 +1089,17 @@ cvBoundingRect( CvArr* array, int update )
 
     if( mat )
     {
-        CvSize size = cvGetMatSize(mat);
-        xmin = size.width;
-        ymin = -1;
-
-        for( i = 0; i < size.height; i++ )
-        {
-            uchar* _ptr = mat->data.ptr + i*mat->step;
-            uchar* ptr = (uchar*)cvAlignPtr(_ptr, 4);
-            int have_nz = 0, k_min, offset = (int)(ptr - _ptr);
-            j = 0;
-            offset = MIN(offset, size.width);
-            for( ; j < offset; j++ )
-                if( _ptr[j] )
-                {
-                    have_nz = 1;
-                    break;
-                }
-            if( j < offset )
-            {
-                if( j < xmin )
-                    xmin = j;
-                if( j > xmax )
-                    xmax = j;
-            }
-            if( offset < size.width )
-            {
-                xmin -= offset;
-                xmax -= offset;
-                size.width -= offset;
-                j = 0;
-                for( ; j <= xmin - 4; j += 4 )
-                    if( *((int*)(ptr+j)) )
-                        break;
-                for( ; j < xmin; j++ )
-                    if( ptr[j] )
-                    {
-                        xmin = j;
-                        if( j > xmax )
-                            xmax = j;
-                        have_nz = 1;
-                        break;
-                    }
-                k_min = MAX(j-1, xmax);
-                k = size.width - 1;
-                for( ; k > k_min && (k&3) != 3; k-- )
-                    if( ptr[k] )
-                        break;
-                if( k > k_min && (k&3) == 3 )
-                {
-                    for( ; k > k_min+3; k -= 4 )
-                        if( *((int*)(ptr+k-3)) )
-                            break;
-                }
-                for( ; k > k_min; k-- )
-                    if( ptr[k] )
-                    {
-                        xmax = k;
-                        have_nz = 1;
-                        break;
-                    }
-                if( !have_nz )
-                {
-                    j &= ~3;
-                    for( ; j <= k - 3; j += 4 )
-                        if( *((int*)(ptr+j)) )
-                            break;
-                    for( ; j <= k; j++ )
-                        if( ptr[j] )
-                        {
-                            have_nz = 1;
-                            break;
-                        }
-                }
-                xmin += offset;
-                xmax += offset;
-                size.width += offset;
-            }
-            if( have_nz )
-            {
-                if( ymin < 0 )
-                    ymin = i;
-                ymax = i;
-            }
-        }
-
-        if( xmin >= size.width )
-            xmin = ymin = 0;
+        rect = cv::maskBoundingRect(cv::cvarrToMat(mat));
     }
     else if( ptseq->total )
     {
-        int  is_float = CV_SEQ_ELTYPE(ptseq) == CV_32FC2;
-        cvStartReadSeq( ptseq, &reader, 0 );
-        CvPoint pt;
-        CV_READ_SEQ_ELEM( pt, reader );
-    #if CV_SSE4_2
-        if(cv::checkHardwareSupport(CV_CPU_SSE4_2))
-        {
-            if( !is_float )
-            {
-                __m128i minval, maxval;
-                minval = maxval = _mm_loadl_epi64((const __m128i*)(&pt)); //min[0]=pt.x, min[1]=pt.y
-
-                for( i = 1; i < ptseq->total; i++)
-                {
-                    __m128i ptXY = _mm_loadl_epi64((const __m128i*)(reader.ptr));
-                    CV_NEXT_SEQ_ELEM(sizeof(pt), reader);
-                    minval = _mm_min_epi32(ptXY, minval);
-                    maxval = _mm_max_epi32(ptXY, maxval);
-                }
-                xmin = _mm_cvtsi128_si32(minval);
-                ymin = _mm_cvtsi128_si32(_mm_srli_si128(minval, 4));
-                xmax = _mm_cvtsi128_si32(maxval);
-                ymax = _mm_cvtsi128_si32(_mm_srli_si128(maxval, 4));
-            }
-            else
-            {
-                __m128 minvalf, maxvalf, z = _mm_setzero_ps(), ptXY = _mm_setzero_ps();
-                minvalf = maxvalf = _mm_loadl_pi(z, (const __m64*)(&pt));
-
-                for( i = 1; i < ptseq->total; i++ )
-                {
-                    ptXY = _mm_loadl_pi(ptXY, (const __m64*)reader.ptr);
-                    CV_NEXT_SEQ_ELEM(sizeof(pt), reader);
-
-                    minvalf = _mm_min_ps(minvalf, ptXY);
-                    maxvalf = _mm_max_ps(maxvalf, ptXY);
-                }
-
-                float xyminf[2], xymaxf[2];
-                _mm_storel_pi((__m64*)xyminf, minvalf);
-                _mm_storel_pi((__m64*)xymaxf, maxvalf);
-                xmin = cvFloor(xyminf[0]);
-                ymin = cvFloor(xyminf[1]);
-                xmax = cvFloor(xymaxf[0]);
-                ymax = cvFloor(xymaxf[1]);
-            }
-        }
-        else
-    #endif
-        {
-            if( !is_float )
-            {
-                xmin = xmax = pt.x;
-                ymin = ymax = pt.y;
-
-                for( i = 1; i < ptseq->total; i++ )
-                {
-                    CV_READ_SEQ_ELEM( pt, reader );
-
-                    if( xmin > pt.x )
-                        xmin = pt.x;
-
-                    if( xmax < pt.x )
-                        xmax = pt.x;
-
-                    if( ymin > pt.y )
-                        ymin = pt.y;
-
-                    if( ymax < pt.y )
-                        ymax = pt.y;
-                }
-            }
-            else
-            {
-                Cv32suf v;
-                // init values
-                xmin = xmax = CV_TOGGLE_FLT(pt.x);
-                ymin = ymax = CV_TOGGLE_FLT(pt.y);
-
-                for( i = 1; i < ptseq->total; i++ )
-                {
-                    CV_READ_SEQ_ELEM( pt, reader );
-                    pt.x = CV_TOGGLE_FLT(pt.x);
-                    pt.y = CV_TOGGLE_FLT(pt.y);
-
-                    if( xmin > pt.x )
-                        xmin = pt.x;
-
-                    if( xmax < pt.x )
-                        xmax = pt.x;
-
-                    if( ymin > pt.y )
-                        ymin = pt.y;
-
-                    if( ymax < pt.y )
-                        ymax = pt.y;
-                }
-
-                v.i = CV_TOGGLE_FLT(xmin); xmin = cvFloor(v.f);
-                v.i = CV_TOGGLE_FLT(ymin); ymin = cvFloor(v.f);
-                // because right and bottom sides of the bounding rectangle are not inclusive
-                // (note +1 in width and height calculation below), cvFloor is used here instead of cvCeil
-                v.i = CV_TOGGLE_FLT(xmax); xmax = cvFloor(v.f);
-                v.i = CV_TOGGLE_FLT(ymax); ymax = cvFloor(v.f);
-            }
-        }
-        rect.x = xmin;
-        rect.y = ymin;
-        rect.width = xmax - xmin + 1;
-        rect.height = ymax - ymin + 1;
+        cv::AutoBuffer<double> abuf;
+        rect = cv::pointSetBoundingRect(cv::cvarrToMat(ptseq, false, false, 0, &abuf));
     }
     if( update )
         ((CvContour*)ptseq)->rect = rect;
     return rect;
 }
 
+
 /* End of file. */
index 6056c39..eca5dc1 100644 (file)
@@ -13,7 +13,7 @@ static void help()
             "Random points are generated and then enclosed.\n"
             "Call:\n"
             "./minarea\n"
-            "Using OpenCV version %s\n" << CV_VERSION << "\n" << endl;
+            "Using OpenCV v" << CV_VERSION << "\n" << endl;
 }
 
 int main( int /*argc*/, char** /*argv*/ )