KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_footprint_courtyard_chaining.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 The KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <board.h>
23#include <footprint.h>
24#include <pcb_shape.h>
25#include <base_units.h>
26
27#include <numeric>
28#include <random>
29
30
31BOOST_AUTO_TEST_SUITE( FootprintCourtyardChaining )
32
33
35{
36 double m_startX;
37 double m_startY;
38 double m_endX;
39 double m_endY;
40};
41
42
44{
45 double m_startX;
46 double m_startY;
47 double m_midX;
48 double m_midY;
49 double m_endX;
50 double m_endY;
51};
52
53
54/*
55 * L5 (Don-Inductor:L_Wuerth_WE-HCI_Flat_1040) from the ticket 2491 board. Four segments are
56 * shorter than the 0.02mm chaining epsilon.
57 */
58static const std::vector<COURTYARD_SEGMENT> l5Segments = {
59 { -6.025, -1.500000, -6.025, 1.500000 },
60 { -5.502647, -2.214616, -5.500000, -2.225000 },
61 { -5.502647, 2.214616, -5.500000, 2.225000 },
62 { -5.500000, -5.250000, -5.500000, -2.225000 },
63 { -5.500000, 5.250000, -5.500000, 2.225000 },
64 { -5.250000, -5.500000, 5.250000, -5.500000 },
65 { -5.250000, 5.500000, 5.250000, 5.500000 },
66 { 5.500000, -5.250000, 5.500000, -2.221321 },
67 { 5.500000, -2.221321, 5.502647, -2.214616 },
68 { 5.500000, 5.250000, 5.500000, 2.225000 },
69 { 5.502647, 2.214616, 5.500000, 2.225000 },
70 { 6.025, 1.500000, 6.025, -1.500000 },
71};
72
73
74static const std::vector<COURTYARD_ARC> l5Arcs = {
75 { -6.025000, -1.500000, -5.880489, -1.942586, -5.502647, -2.214616 },
76 { -5.502647, 2.214616, -5.880490, 1.942586, -6.025000, 1.500000 },
77 { -5.500000, -5.250000, -5.426777, -5.426777, -5.250000, -5.500000 },
78 { -5.250000, 5.500000, -5.426777, 5.426777, -5.500000, 5.250000 },
79 { 5.250000, -5.500000, 5.426777, -5.426777, 5.500000, -5.250000 },
80 { 5.500000, 5.250000, 5.426777, 5.426777, 5.250000, 5.500000 },
81 { 5.502647, -2.214616, 5.880489, -1.942586, 6.025000, -1.500000 },
82 { 6.025000, 1.500000, 5.880490, 1.942586, 5.502647, 2.214616 },
83};
84
85
86static VECTOR2I mmPoint( double aX, double aY )
87{
88 return VECTOR2I( pcbIUScale.mmToIU( aX ), pcbIUScale.mmToIU( aY ) );
89}
90
91
92static void buildShapes( FOOTPRINT& aFootprint, const std::vector<COURTYARD_SEGMENT>& aSegments,
93 const std::vector<COURTYARD_ARC>& aArcs, const std::vector<size_t>& aOrder )
94{
95 std::vector<PCB_SHAPE*> shapes;
96
97 for( const COURTYARD_SEGMENT& seg : aSegments )
98 {
99 PCB_SHAPE* shape = new PCB_SHAPE( &aFootprint, SHAPE_T::SEGMENT );
100 shape->SetLayer( B_CrtYd );
101 shape->SetStart( mmPoint( seg.m_startX, seg.m_startY ) );
102 shape->SetEnd( mmPoint( seg.m_endX, seg.m_endY ) );
103 shape->SetWidth( pcbIUScale.mmToIU( 0.05 ) );
104 shapes.push_back( shape );
105 }
106
107 for( const COURTYARD_ARC& arc : aArcs )
108 {
109 PCB_SHAPE* shape = new PCB_SHAPE( &aFootprint, SHAPE_T::ARC );
110 shape->SetLayer( B_CrtYd );
111 shape->SetArcGeometry( mmPoint( arc.m_startX, arc.m_startY ), mmPoint( arc.m_midX, arc.m_midY ),
112 mmPoint( arc.m_endX, arc.m_endY ) );
113 shape->SetWidth( pcbIUScale.mmToIU( 0.05 ) );
114 shapes.push_back( shape );
115 }
116
117 for( size_t idx : aOrder )
118 aFootprint.Add( shapes[idx] );
119}
120
121
122static void checkCourtyardCloses( const std::vector<COURTYARD_SEGMENT>& aSegments,
123 const std::vector<COURTYARD_ARC>& aArcs,
124 const std::vector<size_t>& aOrder )
125{
126 BOARD board;
127 FOOTPRINT footprint( &board );
128
129 buildShapes( footprint, aSegments, aArcs, aOrder );
130 footprint.BuildCourtyardCaches();
131
134}
135
136
142BOOST_AUTO_TEST_CASE( ClosesFromEverySeedShape )
143{
144 const size_t shapeCount = l5Segments.size() + l5Arcs.size();
145
146 std::vector<size_t> order( shapeCount );
147 std::iota( order.begin(), order.end(), 0 );
148
149 // Each rotation seeds from a different shape
150 for( size_t rotation = 0; rotation < shapeCount; ++rotation )
151 {
152 BOOST_TEST_CONTEXT( "rotation " << rotation )
154
155 std::rotate( order.begin(), order.begin() + 1, order.end() );
156 }
157}
158
159
160BOOST_AUTO_TEST_CASE( ClosesInArbitraryShapeOrder )
161{
162 const size_t shapeCount = l5Segments.size() + l5Arcs.size();
163
164 std::vector<size_t> order( shapeCount );
165 std::iota( order.begin(), order.end(), 0 );
166
167 // Rotations only move the seed, so shuffle the whole list
168 std::mt19937 rng( 42 );
169
170 for( size_t trial = 0; trial < 64; ++trial )
171 {
172 std::shuffle( order.begin(), order.end(), rng );
173
174 BOOST_TEST_CONTEXT( "trial " << trial )
176 }
177}
178
179
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:409
EDA_ITEM_FLAGS GetFlags() const
Definition eda_item.h:167
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
void BuildCourtyardCaches(OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Build complex polygons of the courtyard areas from graphic items on the courtyard layers.
const SHAPE_POLY_SET & GetCourtyard(PCB_LAYER_ID aLayer) const
Used in DRC to test the courtyard area (a complex polygon).
void SetWidth(int aWidth) override
void SetEnd(const VECTOR2I &aEnd) override
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetStart(const VECTOR2I &aStart) override
int OutlineCount() const
Return the number of outlines in the set.
#define MALFORMED_COURTYARDS
@ SEGMENT
Definition eda_shape.h:56
static thread_local boost::mt19937 rng
Definition kiid.cpp:49
@ B_CrtYd
Definition layer_ids.h:111
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
static const std::vector< COURTYARD_SEGMENT > l5Segments
static void checkCourtyardCloses(const std::vector< COURTYARD_SEGMENT > &aSegments, const std::vector< COURTYARD_ARC > &aArcs, const std::vector< size_t > &aOrder)
static void buildShapes(FOOTPRINT &aFootprint, const std::vector< COURTYARD_SEGMENT > &aSegments, const std::vector< COURTYARD_ARC > &aArcs, const std::vector< size_t > &aOrder)
BOOST_AUTO_TEST_CASE(ClosesFromEverySeedShape)
The courtyard closes whatever order its shapes arrive in.
static const std::vector< COURTYARD_ARC > l5Arcs
static VECTOR2I mmPoint(double aX, double aY)
BOOST_AUTO_TEST_SUITE_END()
BOOST_TEST_CONTEXT("Test Clearance")
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683