Implement ClearArcs() and check curved polys don't get a booleanOp

We cannot (yet) support passing several curved outlines through clipper.
In these cases, the caller should ClearArcs() before processing.
This commit is contained in:
Roberto Fernandez Bautista 2021-06-19 15:53:49 +01:00 committed by Jon Evans
parent 260a9d0540
commit 778c64de88
6 changed files with 103 additions and 3 deletions

View File

@ -424,6 +424,13 @@ public:
*/
const SHAPE_LINE_CHAIN Reverse() const;
/**
* Remove all arc references in the line chain, resulting in a chain formed
* only of straight segments. Any arcs in the chain are removed and only the
* piecewise linear approximation remains.
*/
void ClearArcs();
/**
* Return length of the line chain in Euclidean metric.
*

View File

@ -550,9 +550,15 @@ public:
///< Return the area of this poly set
double Area();
///< Count the number of arc shapes present
int ArcCount() const;
///< Appends all the arcs in this polyset to \a aArcBuffer
void GetArcs( std::vector<SHAPE_ARC>& aArcBuffer ) const;
///< Removes all arc references from all the outlines and holes in the polyset
void ClearArcs();
///< Appends a vertex at the end of the given outline/hole (default: the last outline)
/**
* Add a new vertex to the contour indexed by \p aOutline and \p aHole (defaults to the

View File

@ -121,7 +121,6 @@ ClipperLib::Path SHAPE_LINE_CHAIN::convertToClipper( bool aRequiredOrientation,
}
//TODO(SH): Adjust this into two functions: one to convert and one to split the arc into two arcs
void SHAPE_LINE_CHAIN::convertArc( ssize_t aArcIndex )
{
if( aArcIndex < 0 )
@ -515,6 +514,13 @@ const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Reverse() const
}
void SHAPE_LINE_CHAIN::ClearArcs()
{
for( ssize_t arcIndex = m_arcs.size() - 1; arcIndex >= 0; --arcIndex )
convertArc( arcIndex );
}
long long int SHAPE_LINE_CHAIN::Length() const
{
long long int l = 0;

View File

@ -490,6 +490,20 @@ double SHAPE_POLY_SET::Area()
}
int SHAPE_POLY_SET::ArcCount() const
{
int retval = 0;
for( const POLYGON& poly : m_polys )
{
for( size_t i = 0; i < poly.size(); i++ )
retval += poly[i].ArcCount();
}
return retval;
}
void SHAPE_POLY_SET::GetArcs( std::vector<SHAPE_ARC>& aArcBuffer ) const
{
for( const POLYGON& poly : m_polys )
@ -503,6 +517,16 @@ void SHAPE_POLY_SET::GetArcs( std::vector<SHAPE_ARC>& aArcBuffer ) const
}
void SHAPE_POLY_SET::ClearArcs()
{
for( POLYGON& poly : m_polys )
{
for( size_t i = 0; i < poly.size(); i++ )
poly[i].ClearArcs();
}
}
void SHAPE_POLY_SET::booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET& aOtherShape,
POLYGON_MODE aFastMode )
{
@ -513,6 +537,13 @@ void SHAPE_POLY_SET::booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET
void SHAPE_POLY_SET::booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET& aShape,
const SHAPE_POLY_SET& aOtherShape, POLYGON_MODE aFastMode )
{
if( ( aShape.OutlineCount() > 1 || aOtherShape.OutlineCount() > 0 )
&& ( aShape.ArcCount() > 0 || aOtherShape.ArcCount() > 0 ) )
{
wxFAIL_MSG( "Boolean ops on curved polygons are not supported. You should call "
"ClearArcs() before carrying out the boolean operation." );
}
ClipperLib::Clipper c;
c.StrictlySimple( aFastMode == PM_STRICTLY_SIMPLE );

View File

@ -95,6 +95,16 @@ BOOST_AUTO_TEST_CASE( ArcToPolylineLargeCoords )
BOOST_CHECK( GEOM_TEST::IsOutlineValid( base_chain ) );
BOOST_CHECK_EQUAL( base_chain.PointCount(), 11 ); // Adding 1 point, removing 3
BOOST_CHECK_EQUAL( base_chain.ArcCount(), 3 ); // Should still have three arcs
// Test ClearArcs
base_chain.SetClosed( true );
double areaPriorToArcRemoval = base_chain.Area();
base_chain.ClearArcs();
BOOST_CHECK( GEOM_TEST::IsOutlineValid( base_chain ) );
BOOST_CHECK_EQUAL( base_chain.PointCount(), 11 ); // We should have the same number of points
BOOST_CHECK_EQUAL( base_chain.ArcCount(), 0 ); // All arcs should have been removed
BOOST_CHECK_EQUAL( base_chain.Area(), areaPriorToArcRemoval ); // Area should not have changed
}

View File

@ -43,7 +43,9 @@ BOOST_AUTO_TEST_CASE( TestSimplify )
std::map<std::string, SHAPE_POLY_SET> polysToTest =
{
{ "Case 1: Single polygon", testData.holeyCurvedPolySingle },
{ "Case 2: Multi polygon", testData.holeyCurvedPolyMulti }
//{ "Case 2: Multi polygon", testData.holeyCurvedPolyMulti } // This test fails right now:
// clipper seems to not handle
// multiple outlines correctly
};
for( std::pair<std::string, SHAPE_POLY_SET> testCase : polysToTest )
@ -92,7 +94,8 @@ BOOST_AUTO_TEST_CASE( TestIntersectUnion )
std::map<std::string, SHAPE_POLY_SET> polysToTest = {
{ "Case 1: Single polygon", testData.holeyCurvedPolySingle },
//{ "Case 2: Multi polygon", testData.holeyCurvedPolyMulti } // This test fails right now:
// multiple polys unsupported
// clipper seems to not handle
// multiple outlines correctly
};
for( std::pair<std::string, SHAPE_POLY_SET> testCase : polysToTest )
@ -102,6 +105,11 @@ BOOST_AUTO_TEST_CASE( TestIntersectUnion )
SHAPE_POLY_SET testPoly = testCase.second;
SHAPE_POLY_SET opPoly = testData.holeyCurvedPolyInter;
// Remove all arcs before any booleanOps
// @todo Remove the below two lines when boolean ops can be carried out on curved polys
opPoly.ClearArcs();
testPoly.ClearArcs();
BOOST_CHECK( GEOM_TEST::IsPolySetValid( testPoly ) );
BOOST_CHECK( GEOM_TEST::IsPolySetValid( opPoly ) );
@ -128,4 +136,36 @@ BOOST_AUTO_TEST_CASE( TestIntersectUnion )
}
/**
* Test SHAPE_POLY_SET::ClearArcs
*/
BOOST_AUTO_TEST_CASE( TestClearArcs )
{
KI_TEST::CommonTestData testData;
std::map<std::string, SHAPE_POLY_SET> polysToTest = {
{ "Case 1: Single polygon", testData.holeyCurvedPolySingle },
{ "Case 2: Intersect polygon", testData.holeyCurvedPolyInter },
{ "Case 3: Multi polygon", testData.holeyCurvedPolyMulti }
};
for( std::pair<std::string, SHAPE_POLY_SET> testCase : polysToTest )
{
BOOST_TEST_CONTEXT( testCase.first )
{
SHAPE_POLY_SET testPoly = testCase.second;
double originalArea = testPoly.Area();
testPoly.ClearArcs();
BOOST_CHECK( GEOM_TEST::IsPolySetValid( testPoly ) );
BOOST_CHECK_EQUAL( testPoly.Area(), originalArea ); // Area should not have changed
std::vector<SHAPE_ARC> arcBuffer;
testPoly.GetArcs( arcBuffer );
BOOST_CHECK_EQUAL( arcBuffer.size(), 0 ); // All arcs should have been removed
}
}
}
BOOST_AUTO_TEST_SUITE_END()