Point2f midPoint2 = (pts[0] + pts[2]) / 2.0f;
float c2 = midPoint2.x * v2.x + midPoint2.y * v2.y;
float det = v1.x * v2.y - v1.y * v2.x;
+ if (fabs(det) <= EPS)
+ {
+ // v1 and v2 are colinear, so the longest distance between any 2 points
+ // is the diameter of the minimum enclosing circle.
+ float d1 = normL2Sqr<float>(pts[0] - pts[1]);
+ float d2 = normL2Sqr<float>(pts[0] - pts[2]);
+ float d3 = normL2Sqr<float>(pts[1] - pts[2]);
+ radius = sqrt(std::max(d1, std::max(d2, d3))) * 0.5f + EPS;
+ if (d1 >= d2 && d1 >= d3)
+ {
+ center = (pts[0] + pts[1]) * 0.5f;
+ }
+ else if (d2 >= d1 && d2 >= d3)
+ {
+ center = (pts[0] + pts[2]) * 0.5f;
+ }
+ else
+ {
+ CV_DbgAssert(d3 >= d1 && d3 >= d2);
+ center = (pts[1] + pts[2]) * 0.5f;
+ }
+ return;
+ }
float cx = (c1 * v2.y - c2 * v1.y) / det;
float cy = (v1.x * c2 - v2.x * c1) / det;
center.x = (float)cx;
ptsf[0] = (Point2f)pts[i];
ptsf[1] = (Point2f)pts[j];
ptsf[2] = (Point2f)pts[k];
- findCircle3pts(ptsf, center, radius);
+ Point2f new_center; float new_radius = 0;
+ findCircle3pts(ptsf, new_center, new_radius);
+ if (new_radius > 0)
+ {
+ radius = new_radius;
+ center = new_center;
+ }
}
}
}
}
else
{
- findThirdPoint(pts, i, j, center, radius);
+ Point2f new_center; float new_radius = 0;
+ findThirdPoint(pts, i, j, new_center, new_radius);
+ if (new_radius > 0)
+ {
+ radius = new_radius;
+ center = new_center;
+ }
}
}
}
}
else
{
- findSecondPoint(pts, i, center, radius);
+ Point2f new_center; float new_radius = 0;
+ findSecondPoint(pts, i, new_center, new_radius);
+ if (new_radius > 0)
+ {
+ radius = new_radius;
+ center = new_center;
+ }
}
}
}
}
/****************************************************************************************\
+* minEnclosingCircle Test 3 *
+\****************************************************************************************/
+
+TEST(Imgproc_minEnclosingCircle, basic_test)
+{
+ vector<Point2f> pts;
+ pts.push_back(Point2f(0, 0));
+ pts.push_back(Point2f(10, 0));
+ pts.push_back(Point2f(5, 1));
+ const float EPS = 1.0e-3f;
+ Point2f center;
+ float radius;
+
+ // pts[2] is within the circle with diameter pts[0] - pts[1].
+ // 2
+ // 0 1
+ // NB: The triangle is obtuse, so the only pts[0] and pts[1] are on the circle.
+ minEnclosingCircle(pts, center, radius);
+ EXPECT_NEAR(center.x, 5, EPS);
+ EXPECT_NEAR(center.y, 0, EPS);
+ EXPECT_NEAR(5, radius, EPS);
+
+ // pts[2] is on the circle with diameter pts[0] - pts[1].
+ // 2
+ // 0 1
+ pts[2] = Point2f(5, 5);
+ minEnclosingCircle(pts, center, radius);
+ EXPECT_NEAR(center.x, 5, EPS);
+ EXPECT_NEAR(center.y, 0, EPS);
+ EXPECT_NEAR(5, radius, EPS);
+
+ // pts[2] is outside the circle with diameter pts[0] - pts[1].
+ // 2
+ //
+ //
+ // 0 1
+ // NB: The triangle is acute, so all 3 points are on the circle.
+ pts[2] = Point2f(5, 10);
+ minEnclosingCircle(pts, center, radius);
+ EXPECT_NEAR(center.x, 5, EPS);
+ EXPECT_NEAR(center.y, 3.75, EPS);
+ EXPECT_NEAR(6.25f, radius, EPS);
+
+ // The 3 points are colinear.
+ pts[2] = Point2f(3, 0);
+ minEnclosingCircle(pts, center, radius);
+ EXPECT_NEAR(center.x, 5, EPS);
+ EXPECT_NEAR(center.y, 0, EPS);
+ EXPECT_NEAR(5, radius, EPS);
+
+ // 2 points are the same.
+ pts[2] = pts[1];
+ minEnclosingCircle(pts, center, radius);
+ EXPECT_NEAR(center.x, 5, EPS);
+ EXPECT_NEAR(center.y, 0, EPS);
+ EXPECT_NEAR(5, radius, EPS);
+
+ // 3 points are the same.
+ pts[0] = pts[1];
+ minEnclosingCircle(pts, center, radius);
+ EXPECT_NEAR(center.x, 10, EPS);
+ EXPECT_NEAR(center.y, 0, EPS);
+ EXPECT_NEAR(0, radius, EPS);
+}
+
+TEST(Imgproc_minEnclosingCircle, regression_16051) {
+ vector<Point2f> pts;
+ pts.push_back(Point2f(85, 1415));
+ pts.push_back(Point2f(87, 1415));
+ pts.push_back(Point2f(89, 1414));
+ pts.push_back(Point2f(89, 1414));
+ pts.push_back(Point2f(87, 1412));
+ Point2f center;
+ float radius;
+ minEnclosingCircle(pts, center, radius);
+ EXPECT_NEAR(center.x, 86.9f, 1e-3);
+ EXPECT_NEAR(center.y, 1414.1f, 1e-3);
+ EXPECT_NEAR(2.1024551f, radius, 1e-3);
+}
+
+/****************************************************************************************\
* Perimeter Test *
\****************************************************************************************/