KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_custom_pad_primitive_roundtrip.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 modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
21
22#include <base_units.h>
23#include <board.h>
24#include <footprint.h>
25#include <pad.h>
26#include <pcb_point.h>
27#include <pcb_shape.h>
28#include <geometry/eda_angle.h>
31
33
34#include <filesystem>
35#include <memory>
36
37
38BOOST_AUTO_TEST_SUITE( CustomPadPrimitiveRoundTrip )
39
40
41namespace
42{
43
45class TEMP_FILE_HOLDER
46{
47public:
48 TEMP_FILE_HOLDER( const std::string& aPrefix, const std::string& aSuffix )
49 {
50 std::filesystem::path dir = std::filesystem::temp_directory_path() / aPrefix;
51 std::filesystem::create_directories( dir );
52 m_path = dir / ( "board" + aSuffix );
53 }
54
55 ~TEMP_FILE_HOLDER()
56 {
57 std::error_code ec;
58 std::filesystem::remove( m_path, ec );
59 std::filesystem::remove( m_path.parent_path(), ec );
60 }
61
62 const std::filesystem::path& Path() const { return m_path; }
63
64private:
65 std::filesystem::path m_path;
66};
67
68
69int mm( double aMillimetres )
70{
71 return pcbIUScale.mmToIU( aMillimetres );
72}
73
74
75PCB_SHAPE* findPrimitive( const PAD* aPad, SHAPE_T aShape )
76{
77 for( const std::shared_ptr<PCB_SHAPE>& prim : aPad->GetPrimitives( PADSTACK::ALL_LAYERS ) )
78 {
79 if( prim->GetShape() == aShape )
80 return prim.get();
81 }
82
83 return nullptr;
84}
85
86
87void checkPoly( const SHAPE_POLY_SET& aExpected, const SHAPE_POLY_SET& aGot )
88{
89 BOOST_REQUIRE_EQUAL( aExpected.OutlineCount(), aGot.OutlineCount() );
90
91 const SHAPE_LINE_CHAIN& expOutline = aExpected.COutline( 0 );
92 const SHAPE_LINE_CHAIN& gotOutline = aGot.COutline( 0 );
93
94 BOOST_REQUIRE_EQUAL( expOutline.PointCount(), gotOutline.PointCount() );
95
96 for( int ii = 0; ii < expOutline.PointCount(); ++ii )
97 {
98 BOOST_CHECK_EQUAL( gotOutline.CPoint( ii ).x, expOutline.CPoint( ii ).x );
99 BOOST_CHECK_EQUAL( gotOutline.CPoint( ii ).y, expOutline.CPoint( ii ).y );
100 }
101}
102
103} // namespace
104
105
113BOOST_AUTO_TEST_CASE( BezierAndPolyOnTransformedFootprint )
114{
115 auto board = std::make_unique<BOARD>();
116 auto fp = std::make_unique<FOOTPRINT>( board.get() );
117
118 fp->SetReference( "U1" );
119
120 // A non-cardinal rotation and an anisotropic scale make any spurious transform on
121 // the primitives obvious.
122 fp->SetPosition( VECTOR2I( mm( 50.0 ), mm( 25.0 ) ) );
123 fp->SetOrientation( EDA_ANGLE( 30.0, DEGREES_T ) );
124 fp->SetTransformScale( 2.0, 1.5 );
125
126 auto pad = std::make_unique<PAD>( fp.get() );
127 pad->SetNumber( "1" );
128 pad->SetAttribute( PAD_ATTRIB::SMD );
129 pad->SetLayerSet( LSET( { F_Cu } ) );
130 pad->SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( mm( 1.0 ), mm( 1.0 ) ) );
131 pad->SetAnchorPadShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
133
134 // Bezier primitive with deliberately asymmetric control points.
135 auto* bezier = new PCB_SHAPE( pad.get() );
136 bezier->SetShape( SHAPE_T::BEZIER );
137 bezier->SetStart( VECTOR2I( mm( 0.0 ), mm( 0.0 ) ) );
138 bezier->SetBezierC1( VECTOR2I( mm( 1.0 ), mm( 2.0 ) ) );
139 bezier->SetBezierC2( VECTOR2I( mm( 3.0 ), mm( -1.0 ) ) );
140 bezier->SetEnd( VECTOR2I( mm( 4.0 ), mm( 0.5 ) ) );
141 bezier->SetWidth( mm( 0.1 ) );
142 pad->AddPrimitive( PADSTACK::ALL_LAYERS, bezier );
143
144 // Polygon primitive with an asymmetric (non-rectangular) outline.
146 chain.Append( VECTOR2I( mm( 1.0 ), mm( 0.0 ) ) );
147 chain.Append( VECTOR2I( mm( 3.0 ), mm( 1.0 ) ) );
148 chain.Append( VECTOR2I( mm( 2.0 ), mm( 4.0 ) ) );
149 chain.Append( VECTOR2I( mm( -1.0 ), mm( 2.0 ) ) );
150 chain.SetClosed( true );
151
152 SHAPE_POLY_SET polySet;
153 polySet.AddOutline( chain );
154
155 auto* poly = new PCB_SHAPE( pad.get() );
156 poly->SetShape( SHAPE_T::POLY );
157 poly->SetPolyShape( polySet );
158 poly->SetWidth( mm( 0.1 ) );
159 pad->AddPrimitive( PADSTACK::ALL_LAYERS, poly );
160
161 // Capture the in-memory (pre-save) geometry as the round-trip reference.
162 const VECTOR2I expBezierStart = bezier->GetLibraryStart();
163 const VECTOR2I expBezierC1 = bezier->GetLibraryBezierC1();
164 const VECTOR2I expBezierC2 = bezier->GetLibraryBezierC2();
165 const VECTOR2I expBezierEnd = bezier->GetLibraryEnd();
166 const int expBezierWidth = bezier->GetWidth();
167 const SHAPE_POLY_SET expPoly = poly->GetLibraryPolyShape();
168 const int expPolyWidth = poly->GetWidth();
169
170 fp->Add( pad.release(), ADD_MODE::APPEND, true );
171 board->Add( fp.release(), ADD_MODE::APPEND, true );
172
173 TEMP_FILE_HOLDER tmp( "kicad_qa_custom_pad_primitive_roundtrip", ".kicad_pcb" );
174 KI_TEST::DumpBoardToFile( *board, tmp.Path().string() );
175
176 std::unique_ptr<BOARD> reloaded = KI_TEST::ReadBoardFromFileOrStream( tmp.Path().string() );
177 BOOST_REQUIRE( reloaded );
178
179 FOOTPRINT* fpFound = reloaded->Footprints().empty() ? nullptr : reloaded->Footprints().front();
180 BOOST_REQUIRE_MESSAGE( fpFound, "Footprint not found in reloaded board" );
181 BOOST_REQUIRE_MESSAGE( !fpFound->Pads().empty(), "Pad not found in reloaded footprint" );
182
183 PAD* padFound = fpFound->Pads().front();
184
185 PCB_SHAPE* bezierFound = findPrimitive( padFound, SHAPE_T::BEZIER );
186 BOOST_REQUIRE_MESSAGE( bezierFound, "Bezier primitive not found in reloaded pad" );
187
188 BOOST_CHECK_EQUAL( bezierFound->GetLibraryStart().x, expBezierStart.x );
189 BOOST_CHECK_EQUAL( bezierFound->GetLibraryStart().y, expBezierStart.y );
190 BOOST_CHECK_EQUAL( bezierFound->GetLibraryBezierC1().x, expBezierC1.x );
191 BOOST_CHECK_EQUAL( bezierFound->GetLibraryBezierC1().y, expBezierC1.y );
192 BOOST_CHECK_EQUAL( bezierFound->GetLibraryBezierC2().x, expBezierC2.x );
193 BOOST_CHECK_EQUAL( bezierFound->GetLibraryBezierC2().y, expBezierC2.y );
194 BOOST_CHECK_EQUAL( bezierFound->GetLibraryEnd().x, expBezierEnd.x );
195 BOOST_CHECK_EQUAL( bezierFound->GetLibraryEnd().y, expBezierEnd.y );
196 BOOST_CHECK_EQUAL( bezierFound->GetWidth(), expBezierWidth );
197
198 PCB_SHAPE* polyFound = findPrimitive( padFound, SHAPE_T::POLY );
199 BOOST_REQUIRE_MESSAGE( polyFound, "Polygon primitive not found in reloaded pad" );
200 BOOST_REQUIRE( polyFound->IsPolyShapeValid() );
201
202 checkPoly( expPoly, polyFound->GetLibraryPolyShape() );
203 BOOST_CHECK_EQUAL( polyFound->GetWidth(), expPolyWidth );
204}
205
206
207BOOST_AUTO_TEST_CASE( ScaledFootprintRoundTripStable )
208{
209 auto board = std::make_unique<BOARD>();
210 auto fp = std::make_unique<FOOTPRINT>( board.get() );
211 fp->SetReference( "U1" );
212 fp->SetPosition( VECTOR2I( mm( 50.0 ), mm( 50.0 ) ) );
213 fp->SetTransformScale( 2.0, 1.5 );
214
215 auto pad = std::make_unique<PAD>( fp.get() );
216 pad->SetNumber( "1" );
217 pad->SetAttribute( PAD_ATTRIB::SMD );
218 pad->SetLayerSet( LSET( { F_Cu } ) );
219 pad->SetLibSize( PADSTACK::ALL_LAYERS, VECTOR2I( mm( 1.0 ), mm( 1.0 ) ) );
220 fp->Add( pad.release(), ADD_MODE::APPEND, true );
221 board->Add( fp.release(), ADD_MODE::APPEND, true );
222
223 TEMP_FILE_HOLDER tmp( "kicad_qa_scaled_fp_roundtrip", ".kicad_pcb" );
224 KI_TEST::DumpBoardToFile( *board, tmp.Path().string() );
225 std::unique_ptr<BOARD> reloaded = KI_TEST::ReadBoardFromFileOrStream( tmp.Path().string() );
226 BOOST_REQUIRE( reloaded );
227
228 FOOTPRINT* r = reloaded->Footprints().front();
229 BOOST_CHECK_CLOSE( r->GetScaleX(), 2.0, 1e-6 );
230 BOOST_CHECK_CLOSE( r->GetScaleY(), 1.5, 1e-6 );
231}
232
233
234BOOST_AUTO_TEST_CASE( PadPositionAndOrientationRoundTripStable )
235{
236 auto board = std::make_unique<BOARD>();
237 auto fp = std::make_unique<FOOTPRINT>( board.get() );
238 fp->SetReference( "U1" );
239 fp->SetPosition( VECTOR2I( mm( 50.0 ), mm( 50.0 ) ) );
240 fp->SetOrientation( EDA_ANGLE( 30.0, DEGREES_T ) );
241 fp->SetTransformScale( 2.0, 1.5 );
242
243 auto pad = std::make_unique<PAD>( fp.get() );
244 pad->SetNumber( "1" );
245 pad->SetAttribute( PAD_ATTRIB::SMD );
246 pad->SetLayerSet( LSET( { F_Cu } ) );
248 pad->SetLibSize( PADSTACK::ALL_LAYERS, VECTOR2I( mm( 1.0 ), mm( 0.5 ) ) );
249 pad->SetPosition( VECTOR2I( mm( 53.0 ), mm( 51.0 ) ) );
250 pad->SetOrientation( EDA_ANGLE( 75.0, DEGREES_T ) );
251 PAD* padPtr = pad.get();
252 fp->Add( pad.release(), ADD_MODE::APPEND, true );
253 board->Add( fp.release(), ADD_MODE::APPEND, true );
254
255 const VECTOR2I posBefore = padPtr->GetPosition();
256 const EDA_ANGLE orientBefore = padPtr->GetOrientation();
257
258 TEMP_FILE_HOLDER tmp( "kicad_qa_pad_pos_orient_roundtrip", ".kicad_pcb" );
259 KI_TEST::DumpBoardToFile( *board, tmp.Path().string() );
260 std::unique_ptr<BOARD> reloaded = KI_TEST::ReadBoardFromFileOrStream( tmp.Path().string() );
261 BOOST_REQUIRE( reloaded );
262
263 PAD* r = reloaded->Footprints().front()->Pads().front();
264 BOOST_CHECK_EQUAL( r->GetPosition().x, posBefore.x );
265 BOOST_CHECK_EQUAL( r->GetPosition().y, posBefore.y );
266 BOOST_CHECK_CLOSE( r->GetOrientation().AsDegrees(), orientBefore.AsDegrees(), 1e-6 );
267}
268
269
270BOOST_AUTO_TEST_CASE( PadDeltaRoundTripStable )
271{
272 auto board = std::make_unique<BOARD>();
273 auto fp = std::make_unique<FOOTPRINT>( board.get() );
274 fp->SetReference( "U1" );
275 fp->SetPosition( VECTOR2I( mm( 50.0 ), mm( 50.0 ) ) );
276 fp->SetTransformScale( 2.0, 1.5 );
277
278 auto pad = std::make_unique<PAD>( fp.get() );
279 pad->SetNumber( "1" );
280 pad->SetAttribute( PAD_ATTRIB::SMD );
281 pad->SetLayerSet( LSET( { F_Cu } ) );
283 pad->SetLibSize( PADSTACK::ALL_LAYERS, VECTOR2I( mm( 1.0 ), mm( 1.0 ) ) );
284 pad->SetDelta( PADSTACK::ALL_LAYERS, VECTOR2I( mm( 0.4 ), mm( 0.0 ) ) );
285 PAD* padPtr = pad.get();
286 fp->Add( pad.release(), ADD_MODE::APPEND, true );
287 board->Add( fp.release(), ADD_MODE::APPEND, true );
288
289 const VECTOR2I before = padPtr->GetDelta( PADSTACK::ALL_LAYERS );
290
291 TEMP_FILE_HOLDER tmp( "kicad_qa_pad_delta_roundtrip", ".kicad_pcb" );
292 KI_TEST::DumpBoardToFile( *board, tmp.Path().string() );
293 std::unique_ptr<BOARD> reloaded = KI_TEST::ReadBoardFromFileOrStream( tmp.Path().string() );
294 BOOST_REQUIRE( reloaded );
295
296 PAD* r = reloaded->Footprints().front()->Pads().front();
297 BOOST_TEST_MESSAGE( "delta before: " << before.x << "," << before.y
298 << " after: " << r->GetDelta( PADSTACK::ALL_LAYERS ).x << ","
302}
303
304
305BOOST_AUTO_TEST_CASE( PadOffsetRoundTripStable )
306{
307 auto board = std::make_unique<BOARD>();
308 auto fp = std::make_unique<FOOTPRINT>( board.get() );
309 fp->SetReference( "U1" );
310 fp->SetPosition( VECTOR2I( mm( 50.0 ), mm( 50.0 ) ) );
311 fp->SetTransformScale( 2.0, 1.5 );
312
313 auto pad = std::make_unique<PAD>( fp.get() );
314 pad->SetNumber( "1" );
315 pad->SetAttribute( PAD_ATTRIB::SMD );
316 pad->SetLayerSet( LSET( { F_Cu } ) );
318 pad->SetLibSize( PADSTACK::ALL_LAYERS, VECTOR2I( mm( 1.0 ), mm( 1.0 ) ) );
319 pad->SetLibOffset( PADSTACK::ALL_LAYERS, VECTOR2I( mm( 0.3 ), mm( 0.2 ) ) );
320 PAD* padPtr = pad.get();
321 fp->Add( pad.release(), ADD_MODE::APPEND, true );
322 board->Add( fp.release(), ADD_MODE::APPEND, true );
323
324 const VECTOR2I before = padPtr->GetOffset( PADSTACK::ALL_LAYERS );
325
326 TEMP_FILE_HOLDER tmp( "kicad_qa_pad_offset_roundtrip", ".kicad_pcb" );
327 KI_TEST::DumpBoardToFile( *board, tmp.Path().string() );
328 std::unique_ptr<BOARD> reloaded = KI_TEST::ReadBoardFromFileOrStream( tmp.Path().string() );
329 BOOST_REQUIRE( reloaded );
330
331 PAD* r = reloaded->Footprints().front()->Pads().front();
332 BOOST_TEST_MESSAGE( "offset before: " << before.x << "," << before.y
333 << " after: " << r->GetOffset( PADSTACK::ALL_LAYERS ).x << ","
337}
338
339
340BOOST_AUTO_TEST_CASE( FootprintPointRoundTripStable )
341{
342 auto board = std::make_unique<BOARD>();
343 auto fp = std::make_unique<FOOTPRINT>( board.get() );
344 fp->SetReference( "U1" );
345 fp->SetPosition( VECTOR2I( mm( 50.0 ), mm( 50.0 ) ) );
346 fp->SetOrientation( EDA_ANGLE( 30.0, DEGREES_T ) );
347 fp->SetTransformScale( 2.0, 1.5 );
348
349 auto pt = std::make_unique<PCB_POINT>( fp.get() );
350 pt->SetLayer( F_Cu );
351 pt->SetPosition( VECTOR2I( mm( 55.0 ), mm( 52.0 ) ) );
352 PCB_POINT* ptPtr = pt.get();
353 fp->Add( pt.release(), ADD_MODE::APPEND, true );
354 board->Add( fp.release(), ADD_MODE::APPEND, true );
355
356 const VECTOR2I before = ptPtr->GetPosition();
357
358 TEMP_FILE_HOLDER tmp( "kicad_qa_fp_point_roundtrip", ".kicad_pcb" );
359 KI_TEST::DumpBoardToFile( *board, tmp.Path().string() );
360 std::unique_ptr<BOARD> reloaded = KI_TEST::ReadBoardFromFileOrStream( tmp.Path().string() );
361 BOOST_REQUIRE( reloaded );
362
363 FOOTPRINT* r = reloaded->Footprints().front();
364 BOOST_REQUIRE( !r->Points().empty() );
365 PCB_POINT* rp = r->Points().front();
366 BOOST_TEST_MESSAGE( "point before: " << before.x << "," << before.y << " after: " << rp->GetPosition().x << ","
367 << rp->GetPosition().y );
368 BOOST_CHECK_EQUAL( rp->GetPosition().x, before.x );
369 BOOST_CHECK_EQUAL( rp->GetPosition().y, before.y );
370}
371
372
373BOOST_AUTO_TEST_CASE( RotatedPadSizeRoundTripStable )
374{
375 auto board = std::make_unique<BOARD>();
376 auto fp = std::make_unique<FOOTPRINT>( board.get() );
377 fp->SetReference( "U1" );
378 fp->SetPosition( VECTOR2I( mm( 50.0 ), mm( 50.0 ) ) );
379 fp->SetTransformScale( 2.0, 1.5 );
380
381 auto pad = std::make_unique<PAD>( fp.get() );
382 pad->SetNumber( "1" );
383 pad->SetAttribute( PAD_ATTRIB::SMD );
384 pad->SetLayerSet( LSET( { F_Cu } ) );
386 pad->SetLibSize( PADSTACK::ALL_LAYERS, VECTOR2I( mm( 1.0 ), mm( 0.5 ) ) );
387 pad->SetOrientation( EDA_ANGLE( 90.0, DEGREES_T ) );
388 PAD* padPtr = pad.get();
389 fp->Add( pad.release(), ADD_MODE::APPEND, true );
390 board->Add( fp.release(), ADD_MODE::APPEND, true );
391
392 const VECTOR2I boardSizeBefore = padPtr->GetSize( PADSTACK::ALL_LAYERS );
393
394 TEMP_FILE_HOLDER tmp( "kicad_qa_rotated_pad_roundtrip", ".kicad_pcb" );
395 KI_TEST::DumpBoardToFile( *board, tmp.Path().string() );
396 std::unique_ptr<BOARD> reloaded = KI_TEST::ReadBoardFromFileOrStream( tmp.Path().string() );
397 BOOST_REQUIRE( reloaded );
398
399 PAD* r = reloaded->Footprints().front()->Pads().front();
400 BOOST_CHECK_EQUAL( r->GetSize( PADSTACK::ALL_LAYERS ).x, boardSizeBefore.x );
401 BOOST_CHECK_EQUAL( r->GetSize( PADSTACK::ALL_LAYERS ).y, boardSizeBefore.y );
402}
403
404
405// A footprint X-scale must stretch a pad along the footprint's X axis whatever the pad's
406// own orientation, so the scale is conjugated into the pad frame (a 90deg pad swaps X/Y).
407BOOST_AUTO_TEST_CASE( PadSizeScalesAlongFootprintAxisRegardlessOfPadOrientation )
408{
409 BOARD board;
410 FOOTPRINT* fp = new FOOTPRINT( &board );
411 fp->SetPosition( VECTOR2I( 0, 0 ) );
412 fp->SetOrientation( ANGLE_0 );
413 board.Add( fp );
414
415 auto makePad = [&]( const EDA_ANGLE& aRelOrient )
416 {
417 PAD* pad = new PAD( fp );
418 pad->SetAttribute( PAD_ATTRIB::SMD );
419 pad->SetLayerSet( LSET( { F_Cu } ) );
421 pad->SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( mm( 1.0 ), mm( 0.5 ) ) );
422 pad->SetOrientation( aRelOrient );
423 fp->Add( pad );
424 return pad;
425 };
426
427 PAD* pad0 = makePad( ANGLE_0 );
428 PAD* pad90 = makePad( EDA_ANGLE( 90.0, DEGREES_T ) );
429
430 const int xBefore0 = pad0->GetBoundingBox().GetWidth();
431 const int xBefore90 = pad90->GetBoundingBox().GetWidth();
432
433 fp->SetTransformScale( 2.0, 1.0 );
434
435 BOOST_CHECK_EQUAL( pad0->GetSize( PADSTACK::ALL_LAYERS ).x, mm( 2.0 ) );
436 BOOST_CHECK_EQUAL( pad0->GetSize( PADSTACK::ALL_LAYERS ).y, mm( 0.5 ) );
437 BOOST_CHECK_EQUAL( pad90->GetSize( PADSTACK::ALL_LAYERS ).x, mm( 1.0 ) );
438 BOOST_CHECK_EQUAL( pad90->GetSize( PADSTACK::ALL_LAYERS ).y, mm( 1.0 ) );
439
440 // Both pads double their board-X extent, regardless of orientation.
441 BOOST_CHECK_EQUAL( pad0->GetBoundingBox().GetWidth(), 2 * xBefore0 );
442 BOOST_CHECK_EQUAL( pad90->GetBoundingBox().GetWidth(), 2 * xBefore90 );
443}
444
445
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
General utilities for PCB file IO for QA programs.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1295
constexpr size_type GetWidth() const
Definition box2.h:210
double AsDegrees() const
Definition eda_angle.h:116
bool IsPolyShapeValid() const
void SetPosition(const VECTOR2I &aPos) override
PCB_POINTS & Points()
Definition footprint.h:387
void SetOrientation(const EDA_ANGLE &aNewAngle)
std::deque< PAD * > & Pads()
Definition footprint.h:375
double GetScaleX() const
Definition footprint.h:423
void SetTransformScale(double aScaleX, double aScaleY)
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
double GetScaleY() const
Definition footprint.h:424
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:177
Definition pad.h:61
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives(PCB_LAYER_ID aLayer) const
Accessor to the basic shape list for custom-shaped pads.
Definition pad.h:370
const BOX2I GetBoundingBox() const override
The bounding box is cached, so this will be efficient most of the time.
Definition pad.cpp:1599
const VECTOR2I & GetDelta(PCB_LAYER_ID aLayer) const
Definition pad.h:302
VECTOR2I GetPosition() const override
Definition pad.cpp:245
VECTOR2I GetOffset(PCB_LAYER_ID aLayer) const
Definition pad.cpp:796
VECTOR2I GetSize(PCB_LAYER_ID aLayer) const
Definition pad.cpp:287
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition pad.cpp:1723
A PCB_POINT is a 0-dimensional point that is used to mark a position on a PCB, or more usually a foot...
Definition pcb_point.h:39
VECTOR2I GetPosition() const override
Definition pcb_point.h:60
VECTOR2I GetLibraryBezierC1() const
int GetWidth() const override
VECTOR2I GetLibraryEnd() const
Definition pcb_shape.h:221
VECTOR2I GetLibraryStart() const
Definition pcb_shape.h:220
SHAPE_POLY_SET GetLibraryPolyShape() const
VECTOR2I GetLibraryBezierC2() const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
virtual int GetWidth() const
Definition shape.h:287
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
@ DEGREES_T
Definition eda_angle.h:31
SHAPE_T
Definition eda_shape.h:44
@ F_Cu
Definition layer_ids.h:60
std::unique_ptr< BOARD > ReadBoardFromFileOrStream(const std::string &aFilename, std::istream &aFallback)
Read a board from a file, or another stream, as appropriate.
void DumpBoardToFile(BOARD &board, const std::string &aFilename)
Utility function to simply write a Board out to a file.
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:99
@ TRAPEZOID
Definition padstack.h:56
@ RECTANGLE
Definition padstack.h:54
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_CASE(BezierAndPolyOnTransformedFootprint)
A custom pad's bezier and polygon primitives must survive a save/reload unchanged,...
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_TEST_MESSAGE("\n=== Real-World Polygon PIP Benchmark ===\n"<< formatTable(table))
const SHAPE_LINE_CHAIN chain
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683