diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 76e165fa82..69413772d3 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -1112,13 +1112,27 @@ public: */ CV_WRAP Subdiv2D(Rect rect); - /** @brief Creates a new empty Delaunay subdivision + /** @overload */ + CV_WRAP Subdiv2D(Rect2f rect); + + /** @overload + + @brief Creates a new empty Delaunay subdivision @param rect Rectangle that includes all of the 2D points that are to be added to the subdivision. */ CV_WRAP void initDelaunay(Rect rect); + /** @overload + + @brief Creates a new empty Delaunay subdivision + + @param rect Rectangle that includes all of the 2d points that are to be added to the subdivision. + + */ + CV_WRAP void initDelaunay(Rect2f rect); + /** @brief Insert a single point into a Delaunay triangulation. @param pt Point to insert. diff --git a/modules/imgproc/src/subdivision2d.cpp b/modules/imgproc/src/subdivision2d.cpp index 86a0f72852..671430ffb5 100644 --- a/modules/imgproc/src/subdivision2d.cpp +++ b/modules/imgproc/src/subdivision2d.cpp @@ -118,6 +118,16 @@ Subdiv2D::Subdiv2D(Rect rect) initDelaunay(rect); } +Subdiv2D::Subdiv2D(Rect2f rect) +{ + validGeometry = false; + freeQEdge = 0; + freePoint = 0; + recentEdge = 0; + + initDelaunay(rect); +} + Subdiv2D::QuadEdge::QuadEdge() { @@ -535,6 +545,52 @@ void Subdiv2D::initDelaunay( Rect rect ) recentEdge = edge_AB; } +void Subdiv2D::initDelaunay( Rect2f rect ) +{ + CV_INSTRUMENT_REGION(); + + float big_coord = 6.f * MAX( rect.width, rect.height ); + float rx = rect.x; + float ry = rect.y; + + vtx.clear(); + qedges.clear(); + + recentEdge = 0; + validGeometry = false; + + topLeft = Point2f( rx, ry ); + bottomRight = Point2f( rx + rect.width, ry + rect.height ); + + Point2f ppA( rx + big_coord, ry ); + Point2f ppB( rx, ry + big_coord ); + Point2f ppC( rx - big_coord, ry - big_coord ); + + vtx.push_back(Vertex()); + qedges.push_back(QuadEdge()); + + freeQEdge = 0; + freePoint = 0; + + int pA = newPoint(ppA, false); + int pB = newPoint(ppB, false); + int pC = newPoint(ppC, false); + + int edge_AB = newEdge(); + int edge_BC = newEdge(); + int edge_CA = newEdge(); + + setEdgePoints( edge_AB, pA, pB ); + setEdgePoints( edge_BC, pB, pC ); + setEdgePoints( edge_CA, pC, pA ); + + splice( edge_AB, symEdge( edge_CA )); + splice( edge_BC, symEdge( edge_AB )); + splice( edge_CA, symEdge( edge_BC )); + + recentEdge = edge_AB; +} + void Subdiv2D::clearVoronoi() { diff --git a/modules/imgproc/test/test_subdivision2d.cpp b/modules/imgproc/test/test_subdivision2d.cpp index a940adfc55..052715c7a6 100644 --- a/modules/imgproc/test/test_subdivision2d.cpp +++ b/modules/imgproc/test/test_subdivision2d.cpp @@ -64,4 +64,57 @@ TEST(Imgproc_Subdiv2D, issue_25696) { ASSERT_EQ(static_cast(2), triangles.size()); } + +// Initialization test +TEST(Imgproc_Subdiv2D, rect2f_constructor_and_init) +{ + cv::Rect2f rect_f(0.5f, 1.5f, 100.7f, 200.3f); + cv::Subdiv2D subdiv_f(rect_f); + + cv::Point2f pt1(50.2f, 80.1f); + cv::Point2f pt2(75.8f, 120.9f); + cv::Point2f pt3(25.5f, 150.3f); + + EXPECT_NO_THROW(subdiv_f.insert(pt1)); + EXPECT_NO_THROW(subdiv_f.insert(pt2)); + EXPECT_NO_THROW(subdiv_f.insert(pt3)); + + cv::Subdiv2D subdiv_init; + + EXPECT_NO_THROW(subdiv_init.initDelaunay(rect_f)); + EXPECT_NO_THROW(subdiv_init.insert(pt1)); + EXPECT_NO_THROW(subdiv_init.insert(pt2)); + EXPECT_NO_THROW(subdiv_init.insert(pt3)); + + std::vector triangles; + + EXPECT_NO_THROW(subdiv_f.getTriangleList(triangles)); + EXPECT_GT(triangles.size(), 0u); +} + +// test with small coordinates +TEST(Imgproc_Subdiv2D, rect2f_edge_cases) +{ + cv::Rect2f small_rect(0.0f, 0.0f, 0.1f, 0.1f); + cv::Subdiv2D subdiv_small(small_rect); + + cv::Point2f small_pt(0.05f, 0.05f); + EXPECT_NO_THROW(subdiv_small.insert(small_pt)); + cv::Rect2f float_rect(10.25f, 20.75f, 50.5f, 30.25f); + + cv::Subdiv2D subdiv_float(float_rect); + + cv::Point2f float_pt1(35.125f, 35.875f); + cv::Point2f float_pt2(45.375f, 25.625f); + cv::Point2f float_pt3(55.750f, 45.125f); + + EXPECT_NO_THROW(subdiv_float.insert(float_pt1)); + EXPECT_NO_THROW(subdiv_float.insert(float_pt2)); + EXPECT_NO_THROW(subdiv_float.insert(float_pt3)); + + std::vector triangles; + + subdiv_float.getTriangleList(triangles); + EXPECT_GT(triangles.size(), 0u); +} }}