mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
Merge pull request #27641 from Ma-gi-cian:subdiv2d-rect2f-clean
Subdiv2d rect2f clean #27641 Closes https://github.com/opencv/opencv/issues/27623 Changes: - Added Subdiv2D(Rect2f) constructor overload - Added initDelaunay(Rect2f) method overload - No changes to the previous implementation to keep it backward compatible - Added tests for init and testing with edge case of extremely small coordinates - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake See original pull request at : https://github.com/opencv/opencv/pull/27631
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -64,4 +64,57 @@ TEST(Imgproc_Subdiv2D, issue_25696) {
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(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<cv::Vec6f> 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<cv::Vec6f> triangles;
|
||||
|
||||
subdiv_float.getTriangleList(triangles);
|
||||
EXPECT_GT(triangles.size(), 0u);
|
||||
}
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user