KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_shape_poly_set_arcs.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2021 Roberto Fernandez Bautista <[email protected]>
5 * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <string>
22#include <tuple>
24
27
28#include "fixtures_geometry.h"
29#include "geom_test_utils.h"
30
31
32BOOST_AUTO_TEST_SUITE( CurvedPolys )
33
34
35
39BOOST_AUTO_TEST_CASE( TestSimplify )
40{
42
43 std::map<std::string, SHAPE_POLY_SET> polysToTest =
44 {
45 { "Case 1: Single polygon", testData.holeyCurvedPolySingle },
46 { "Case 2: Wraparound polygon", testData.curvedPolyWrapRound },
47 //{ "Case 3: Multi polygon", testData.holeyCurvedPolyMulti } // This test fails right now:
48 // clipper seems to not handle
49 // multiple outlines correctly
50 };
51
52 for( std::pair<std::string, SHAPE_POLY_SET> testCase : polysToTest )
53 {
54 BOOST_TEST_CONTEXT( testCase.first )
55 {
56 SHAPE_POLY_SET testPoly = testCase.second;
57
58 double originalArea = testPoly.Area();
59
60 std::vector<SHAPE_ARC> originalArcs;
61 testPoly.GetArcs( originalArcs );
62
63 for( int i = 1; i <= 3; i++ )
64 {
65 BOOST_TEST_CONTEXT( "Simplify Iteration " << i )
66 {
67 testPoly.Simplify();
68
69 std::vector<SHAPE_ARC> foundArcs;
70 testPoly.GetArcs( foundArcs );
71
72 BOOST_CHECK( GEOM_TEST::IsPolySetValid( testPoly ) );
73 BOOST_CHECK_EQUAL( testPoly.Area(), originalArea );
74 BOOST_CHECK_EQUAL( originalArcs.size(), foundArcs.size() );
75 KI_TEST::CheckUnorderedMatches( originalArcs, foundArcs,
76 []( const SHAPE_ARC& aA, const SHAPE_ARC& aB ) -> bool
77 {
78 // We accept that the arcs could be reversed after Simplify
79 return aA == aB || aA.Reversed() == aB;
80 } );
81
82 }
83 }
84 }
85 }
86}
87
88
92BOOST_AUTO_TEST_CASE( TestIntersectUnion )
93{
95
96 std::map<std::string, SHAPE_POLY_SET> polysToTest = {
97 { "Case 1: Single polygon", testData.holeyCurvedPolySingle },
98 //{ "Case 2: Multi polygon", testData.holeyCurvedPolyMulti } // This test fails right now:
99 // clipper seems to not handle
100 // multiple outlines correctly
101 };
102
103 for( std::pair<std::string, SHAPE_POLY_SET> testCase : polysToTest )
104 {
105 BOOST_TEST_CONTEXT( testCase.first )
106 {
107 SHAPE_POLY_SET testPoly = testCase.second;
108 SHAPE_POLY_SET opPoly = testData.holeyCurvedPolyInter;
109
110 // Remove all arcs before any booleanOps
111 // @todo Remove the below two lines when boolean ops can be carried out on curved polys
112 opPoly.ClearArcs();
113 testPoly.ClearArcs();
114
115 BOOST_CHECK( GEOM_TEST::IsPolySetValid( testPoly ) );
116 BOOST_CHECK( GEOM_TEST::IsPolySetValid( opPoly ) );
117
118 double testPolyArea = testPoly.Area();
119 double opPolyArea = opPoly.Area();
120
121 SHAPE_POLY_SET intersectionPoly = testPoly;
122 intersectionPoly.BooleanIntersection( opPoly );
123 double intersectArea = intersectionPoly.Area();
124
125 BOOST_CHECK( GEOM_TEST::IsPolySetValid( intersectionPoly ) );
126
127
128 SHAPE_POLY_SET unionPoly = testPoly;
129 unionPoly.BooleanAdd( opPoly );
130 double unionArea = unionPoly.Area();
131
132 BOOST_CHECK( GEOM_TEST::IsPolySetValid( unionPoly ) );
133
134 // Acceptable error of 0.01% (fails at 0.001% for some - this is a Clipper limitation)
135 BOOST_CHECK_CLOSE( testPolyArea + opPolyArea - intersectArea, unionArea, 0.01 );
136 }
137 }
138}
139
140
144BOOST_AUTO_TEST_CASE( TestClearArcs )
145{
147
148 std::map<std::string, SHAPE_POLY_SET> polysToTest = {
149 { "Case 1: Single polygon", testData.holeyCurvedPolySingle },
150 { "Case 2: Intersect polygon", testData.holeyCurvedPolyInter },
151 { "Case 3: Multi polygon", testData.holeyCurvedPolyMulti }
152 };
153
154 for( std::pair<std::string, SHAPE_POLY_SET> testCase : polysToTest )
155 {
156 BOOST_TEST_CONTEXT( testCase.first )
157 {
158 SHAPE_POLY_SET testPoly = testCase.second;
159 double originalArea = testPoly.Area();
160 testPoly.ClearArcs();
161
162 BOOST_CHECK( GEOM_TEST::IsPolySetValid( testPoly ) );
163 BOOST_CHECK_EQUAL( testPoly.Area(), originalArea ); // Area should not have changed
164
165 std::vector<SHAPE_ARC> arcBuffer;
166 testPoly.GetArcs( arcBuffer );
167
168 BOOST_CHECK_EQUAL( arcBuffer.size(), 0 ); // All arcs should have been removed
169 }
170 }
171}
172
SHAPE_ARC Reversed() const
Definition: shape_arc.cpp:680
Represent a set of closed polygons.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
void ClearArcs()
Removes all arc references from all the outlines and holes in the polyset.
double Area()
Return the area of this poly set.
void GetArcs(std::vector< SHAPE_ARC > &aArcBuffer) const
Appends all the arcs in this polyset to aArcBuffer.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
void BooleanIntersection(const SHAPE_POLY_SET &b)
Perform boolean polyset intersection.
bool IsPolySetValid(const SHAPE_POLY_SET &aSet)
Verify that a SHAPE_POLY_SET has been assembled correctly by verifying each of the outlines and holes...
void CheckUnorderedMatches(const EXP_CONT &aExpected, const FOUND_CONT &aFound, MATCH_PRED aMatchPredicate)
Check that a container of "found" objects matches a container of "expected" objects.
Common data for some of the SHAPE_POLY_SET tests:
SHAPE_POLY_SET holeyCurvedPolySingle
Polygon with a single outline + multiple holes.
SHAPE_POLY_SET holeyCurvedPolyInter
Polygon with a single outlines + multiple holes.
SHAPE_POLY_SET curvedPolyWrapRound
Causes arc wraparound when reloading from Clipper see https://gitlab.com/kicad/code/kicad/-/issues/96...
SHAPE_POLY_SET holeyCurvedPolyMulti
Polygon with a multiple outlines + multiple holes.
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(TestSimplify)
Simplify the polygon a large number of times and check that the area does not change and also that th...