KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_clip_line_to_via.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#include <board.h>
22#include <footprint.h>
23#include <pad.h>
24#include <pcb_track.h>
26#include <geometry/shape_arc.h>
28
29
31{
36
37 // A circular via at aCenter, big enough that a centre endpoint lands well
38 // inside the pad.
39 std::unique_ptr<PCB_VIA> MakeVia( const VECTOR2I& aCenter )
40 {
41 std::unique_ptr<PCB_VIA> via = std::make_unique<PCB_VIA>( &m_board );
42 via->SetPadstackMode( PADSTACK::MODE::NORMAL );
43 via->SetPosition( aCenter );
44 via->SetLayerPair( F_Cu, B_Cu );
45 via->SetDrill( 400000 ); // 0.4 mm
46 via->SetWidth( PADSTACK::ALL_LAYERS, 1270000 ); // 1.27 mm -> radius 0.635 mm
47 return via;
48 }
49
50 // A circular pad the same size as the via. OptimiseTraceInPad is arc-aware,
51 // so it is the reference.
52 std::unique_ptr<PAD> MakeCircularPad( const VECTOR2I& aCenter )
53 {
54 std::unique_ptr<PAD> pad = std::make_unique<PAD>( &m_footprint );
55 pad->SetPadstackMode( PADSTACK::MODE::NORMAL );
56 pad->SetAttribute( PAD_ATTRIB::PTH );
58 pad->SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( 1270000, 1270000 ) );
59 pad->SetPosition( aCenter );
60 pad->SetLayerSet( LSET( { F_Cu } ) );
61 return pad;
62 }
63
66};
67
68
69BOOST_FIXTURE_TEST_SUITE( ClipLineToVia, CLIP_LINE_TO_VIA_FIXTURE )
70
71
72// Control with no arc. Clipping a straight trace forwards and backwards must
73// give the same length. Proves the harness is sound.
74BOOST_AUTO_TEST_CASE( StraightTrace_ForwardBackwardAgree )
75{
76 const VECTOR2I viaCenter( 189190000, 46760000 );
77 auto via = MakeVia( viaCenter );
78
80 chain.Append( viaCenter ); // inside via
81 chain.Append( VECTOR2I( 189190000 + 5000000, 46760000 ) ); // 5 mm away
82
83 SHAPE_LINE_CHAIN chainForward = chain;
84 SHAPE_LINE_CHAIN chainBackward = chain;
85 chainBackward.Reverse();
86
87 BOOST_REQUIRE_EQUAL( chainForward.Length(), chainBackward.Length() );
88
91
92 BOOST_CHECK_CLOSE( static_cast<double>( chainForward.Length() ), static_cast<double>( chainBackward.Length() ),
93 0.5 );
94}
95
96
97// An arc starts at the via centre and exits the pad. The via clip and the
98// arc-aware pad clip use the same circle, so they must report the same length.
99// A gap means the via clip mishandles the arc.
100BOOST_AUTO_TEST_CASE( ArcAtViaCenter_ViaClipMatchesPadClip )
101{
102 const VECTOR2I arcStart( 189190000, 46760000 );
103 const VECTOR2I arcMid( 190382763, 46815467 );
104 const VECTOR2I arcEnd( 189758445, 47833301 );
105
106 SHAPE_LINE_CHAIN baseChain;
107 baseChain.Append( arcStart );
108 SHAPE_ARC arc( arcStart, arcMid, arcEnd, 0 );
109 baseChain.Append( arc );
110
111 const double fullArcLen = static_cast<double>( baseChain.Length() );
112
113 SHAPE_LINE_CHAIN viaChain = baseChain;
114 SHAPE_LINE_CHAIN padChain = baseChain;
115
116 auto via = MakeVia( arcStart );
117 auto pad = MakeCircularPad( arcStart );
118
121
122 const double viaLen = static_cast<double>( viaChain.Length() );
123 const double padLen = static_cast<double>( padChain.Length() );
124
125 BOOST_TEST_MESSAGE( "full arc length (no clip) (mm): " << fullArcLen / 1000000.0 );
126 BOOST_TEST_MESSAGE( "via-clip length (mm): " << viaLen / 1000000.0 );
127 BOOST_TEST_MESSAGE( "pad-clip length (arc-aware)(mm): " << padLen / 1000000.0 );
128 BOOST_TEST_MESSAGE( "via vs pad gap (um): " << ( viaLen - padLen ) / 1000.0 );
129
130 // Via clip should agree with the arc-aware pad clip on identical geometry.
131 BOOST_CHECK_CLOSE( viaLen, padLen, 0.5 );
132}
133
134
135// Merge a straight line joined to an arc and check the total length is kept.
136// Guards the arc-aware merge. An arc that bends into a segment must join one
137// chain, not leave the segment ending at the bend.
138BOOST_AUTO_TEST_CASE( Merge_DoesNotDropArcLength )
139{
140 const VECTOR2I a( 0, 0 );
141 const VECTOR2I b( 5000000, 0 );
142 const VECTOR2I arcMid( 6000000, 1000000 );
143 const VECTOR2I arcEnd( 7000000, 0 );
144
145 SHAPE_LINE_CHAIN straight;
146 straight.Append( a );
147 straight.Append( b );
148
149 SHAPE_LINE_CHAIN arcChain;
150 arcChain.Append( b );
151 SHAPE_ARC arc( b, arcMid, arcEnd, 0 );
152 arcChain.Append( arc );
153
154 const double expected = static_cast<double>( straight.Length() + arcChain.Length() );
155
156 auto makeItems = [&]()
157 {
158 std::vector<LENGTH_DELAY_CALCULATION_ITEM> items;
159
161 s.SetLine( straight );
162 s.SetLayers( F_Cu );
163 s.SetWidth( 200000 );
164
166 c.SetLine( arcChain );
167 c.SetLayers( F_Cu );
168 c.SetWidth( 200000 );
169
170 items.push_back( s );
171 items.push_back( c );
172 return items;
173 };
174
175 LENGTH_DELAY_CALCULATION calc( &m_board );
176
177 constexpr PATH_OPTIMISATIONS noMerge = {
178 .OptimiseVias = false, .MergeTracks = false, .OptimiseTracesInPads = false, .InferViaInPad = false
179 };
180 constexpr PATH_OPTIMISATIONS merge = {
181 .OptimiseVias = false, .MergeTracks = true, .OptimiseTracesInPads = false, .InferViaInPad = false
182 };
183
184 auto i1 = makeItems();
185 auto i2 = makeItems();
186
187 const double lenNoMerge = static_cast<double>( calc.CalculateLength( i1, noMerge, nullptr, nullptr ) );
188 const double lenMerge = static_cast<double>( calc.CalculateLength( i2, merge, nullptr, nullptr ) );
189
190 BOOST_TEST_MESSAGE( "expected (mm): " << expected / 1000000.0 );
191 BOOST_TEST_MESSAGE( "no-merge (mm): " << lenNoMerge / 1000000.0 );
192 BOOST_TEST_MESSAGE( "merge (mm): " << lenMerge / 1000000.0 );
193
194 BOOST_CHECK_CLOSE( lenNoMerge, expected, 0.01 );
195 BOOST_CHECK_CLOSE( lenMerge, lenNoMerge, 0.01 );
196}
197
198
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:409
Lightweight class which holds a pad, via, or a routed trace outline.
void SetLine(const SHAPE_LINE_CHAIN &aLine)
Sets the source SHAPE_LINE_CHAIN of this item.
void SetWidth(const int aWidth)
Sets the line width.
void SetLayers(const PCB_LAYER_ID aStart, const PCB_LAYER_ID aEnd=PCB_LAYER_ID::UNDEFINED_LAYER)
Sets the first and last layers associated with this item.
Class which calculates lengths (and associated routing statistics) in a BOARD context.
int64_t CalculateLength(std::vector< LENGTH_DELAY_CALCULATION_ITEM > &aItems, PATH_OPTIMISATIONS aOptimisations, const PAD *aStartPad=nullptr, const PAD *aEndPad=nullptr) const
Calculates the electrical length of the given items.
static void OptimiseTraceInVia(SHAPE_LINE_CHAIN &aLine, const PCB_VIA *aVia, PCB_LAYER_ID aLayer)
Clips trace portions inside a VIA pad and replaces them with a straight-line segment from the VIA edg...
static void OptimiseTraceInPad(SHAPE_LINE_CHAIN &aLine, const PAD *aPad, PCB_LAYER_ID aPcbLayer)
Optimises the given trace / line to minimise the electrical path length within the given pad.
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:170
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
Definition padstack.h:179
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
long long int Length() const
Return length of the line chain in Euclidean metric.
@ B_Cu
Definition layer_ids.h:61
@ F_Cu
Definition layer_ids.h:60
@ PTH
Plated through hole pad.
Definition padstack.h:97
std::unique_ptr< PAD > MakeCircularPad(const VECTOR2I &aCenter)
std::unique_ptr< PCB_VIA > MakeVia(const VECTOR2I &aCenter)
Struct to control which optimisations the length calculation code runs on the given path objects.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_CASE(StraightTrace_ForwardBackwardAgree)
BOOST_AUTO_TEST_SUITE_END()
VECTOR3I expected(15, 30, 45)
const SHAPE_LINE_CHAIN chain
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683