KiCad PCB EDA Suite
test_shape_poly_set_distance.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) 2017 CERN
5  * @author Alejandro GarcĂ­a Montoro <alejandro.garciamontoro@gmail.com>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
26 
27 #include <convert_to_biu.h>
28 
30 
33 
35 
37 constexpr static double IU_PER_MM = 1e3;
38 
39 constexpr static inline int Millimeter2iu( double mm )
40 {
41  return (int) ( mm < 0 ? mm * IU_PER_MM - 0.5 : mm * IU_PER_MM + 0.5 );
42 }
43 
44 
48 BOOST_AUTO_TEST_SUITE( SPSDistance )
49 
51 {
52  std::string m_case_name;
53 
56 
60 
63 };
64 
65 static std::vector<SPS_DISTANCE_TO_SEG_CASE> GetSPSSegDistCases()
66 {
67  namespace KT = KI_TEST;
68  std::vector<SPS_DISTANCE_TO_SEG_CASE> cases;
69 
70  // Single 10mm square at origin
71  const SHAPE_POLY_SET square_10mm_0_0 = KT::BuildPolyset( {
73  } );
74 
75  // Double square: 10mm each, one at (0, 0), one at (10, 0)
76  const SHAPE_POLY_SET squares_10mm_0_0_and_20_0 = KT::BuildPolyset( {
79  { Millimeter2iu( 20 ), Millimeter2iu( 0 ) } ),
80  } );
81 
82  // Hollow square: 10mm hole in 20mm square, at origin
83  const SHAPE_POLY_SET hollow_square_20_10_at_0_0 =
85 
86  cases.push_back( {
87  "Square poly -> 1D segment",
88  square_10mm_0_0,
89  KT::BuildHSeg( { Millimeter2iu( 0 ), Millimeter2iu( 15 ) }, Millimeter2iu( 10 ) ),
90  Millimeter2iu( 0 ), // 1-d segment
91  Millimeter2iu( 10 ),
92  } );
93 
94  cases.push_back( {
95  "Square poly -> 2D (thick) segment",
96  square_10mm_0_0,
97  KT::BuildHSeg( { Millimeter2iu( 0 ), Millimeter2iu( 15 ) }, Millimeter2iu( 10 ) ),
98  Millimeter2iu( 2 ), // thick segment
99  Millimeter2iu( 9 ),
100  } );
101 
102  cases.push_back( {
103  "Two Squares poly -> 2D segment (nearest second square)", squares_10mm_0_0_and_20_0,
104  KT::BuildHSeg( { Millimeter2iu( 15 ), Millimeter2iu( 15 ) }, Millimeter2iu( 10 ) ),
105  Millimeter2iu( 2 ), // thick segment
106  Millimeter2iu( 9 ), // from line to second square
107  } );
108 
109  cases.push_back( {
110  "Square poly -> one intersect", square_10mm_0_0,
111  KT::BuildHSeg( { Millimeter2iu( -5 ), Millimeter2iu( 0 ) }, Millimeter2iu( 10 ) ),
112  Millimeter2iu( 0 ), // 1-d segment
113  Millimeter2iu( 0 ), // intersect
114  } );
115 
116  cases.push_back( {
117  "Square poly -> multiple intersection", square_10mm_0_0,
118  KT::BuildHSeg( { Millimeter2iu( -5 ), Millimeter2iu( 0 ) }, Millimeter2iu( 20 ) ),
119  Millimeter2iu( 0 ), // 1-d segment
120  Millimeter2iu( 0 ), // intersect
121  } );
122 
123  cases.push_back( {
124  "Square poly -> 1D seg touching", square_10mm_0_0,
125  // touch left side at (-5, 0)
126  KT::BuildHSeg( { Millimeter2iu( -10 ), Millimeter2iu( 0 ) }, Millimeter2iu( 5 ) ),
127  Millimeter2iu( 0 ), // 2D segment
128  Millimeter2iu( 0 ), // intersect
129  } );
130 
131  cases.push_back( {
132  "Square poly -> 2D seg (end cap is nearest)", square_10mm_0_0,
133  KT::BuildHSeg( { Millimeter2iu( -20 ), Millimeter2iu( 0 ) }, Millimeter2iu( 10 ) ),
134  Millimeter2iu( 2 ), // 2D segment, 1mm cap radius
135  Millimeter2iu( 4 ), // 4mm short, 5mm to wire end, -1mm radius
136  } );
137 
138  return cases;
139 };
140 
144 BOOST_AUTO_TEST_CASE( SegDistance )
145 {
146  for( const auto& c : GetSPSSegDistCases() )
147  {
148  BOOST_TEST_CONTEXT( c.m_case_name )
149  {
150  SHAPE_POLY_SET polyset = c.m_polyset;
151 
152  int dist = sqrt( polyset.SquaredDistance( c.m_seg ) ) - ( c.m_seg_width / 2 );
153 
154  // right answer?
155  BOOST_CHECK_PREDICATE( KI_TEST::IsWithin<int>, ( dist )( c.m_exp_dist )( 1 ) );
156  }
157  }
158 }
159 
160 BOOST_AUTO_TEST_SUITE_END()
SHAPE_POLY_SET BuildHollowSquare(int aOuterSize, int aInnerSize, const VECTOR2I &aCentre)
Build a SHAPE_POLY_SET in the shape of a square outline, with a square hole, both centred at the give...
static constexpr double IU_PER_MM
Mock up a conversion function.
SEG::ecoord SquaredDistance(VECTOR2I aPoint) const
Function SquaredDistance computes the minimum distance squared between aPoint and all the polygons in...
BOOST_AUTO_TEST_CASE(SegDistance)
Check segment distances.
Declares the Boost test suite fixture.
Utilities for creating useful line chain idioms commonly founds in QA utilities and tests.
SHAPE_POLY_SET.
SHAPE_LINE_CHAIN BuildSquareChain(int aSize, const VECTOR2I &aCentre)
Builds a square SHAPE_LINE_CHAIN of a certain size at a certain centre.
#define BOOST_TEST_CONTEXT(A)
Definition: seg.h:39
SHAPE_POLY_SET BuildPolyset(const std::vector< SHAPE_LINE_CHAIN > &aOutlines)
Construct a SHAPE_POLY_SET from a list of points for each of outlines (no holes)
SEG BuildHSeg(const VECTOR2I &aStart, int aLength)
Build a horizontal segment from a point with a length.
static std::vector< SPS_DISTANCE_TO_SEG_CASE > GetSPSSegDistCases()
SHAPE_POLY_SET m_polyset
list of lists of polygon points
SEG m_seg
the segment to check distance to
Utilities for creating useful polygon shapes that are commonly found in QA utilities and tests.
static constexpr int Millimeter2iu(double mm)