KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_graphic_extend.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
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <boost/test/unit_test.hpp>
21
22#include <board.h>
23#include <geometry/circle.h>
24#include <geometry/seg.h>
25#include <geometry/shape_arc.h>
26#include <layer_ids.h>
27#include <pcb_shape.h>
28#include <pcb_track.h>
30
31#include <limits>
32
33
34BOOST_AUTO_TEST_SUITE( GraphicExtend )
35
36
37static const GRAPHIC_EDIT_GEOMETRY& planned( const GRAPHIC_EDIT_RESULT& aResult )
38{
39 return aResult.m_Geometry.front();
40}
41
42
43static PCB_SHAPE makeLine( const VECTOR2I& aStart, const VECTOR2I& aEnd, PCB_LAYER_ID aLayer = Dwgs_User )
44{
45 PCB_SHAPE line( nullptr, SHAPE_T::SEGMENT );
46 line.SetStart( aStart );
47 line.SetEnd( aEnd );
48 line.SetLayer( aLayer );
49 return line;
50}
51
52
53static PCB_SHAPE makeArc( const VECTOR2I& aCenter, const VECTOR2I& aStart, double aAngle,
54 PCB_LAYER_ID aLayer = Dwgs_User )
55{
56 SHAPE_ARC geometry( aCenter, aStart, EDA_ANGLE( aAngle, DEGREES_T ) );
57 PCB_SHAPE arc( nullptr, SHAPE_T::ARC );
58 arc.SetArcGeometry( geometry.GetP0(), geometry.GetArcMid(), geometry.GetP1() );
59 arc.SetLayer( aLayer );
60 return arc;
61}
62
63
64BOOST_AUTO_TEST_CASE( ExtendsSelectedLineEndToFiniteLineBoundary )
65{
66 PCB_SHAPE source = makeLine( { 0, 0 }, { 10, 0 } );
67 PCB_SHAPE boundary = makeLine( { 20, -10 }, { 20, 10 } );
68
70
72 BOOST_CHECK_EQUAL( planned( result ).m_Start, VECTOR2I( 0, 0 ) );
73 BOOST_CHECK_EQUAL( planned( result ).m_End, VECTOR2I( 20, 0 ) );
74}
75
76
77BOOST_AUTO_TEST_CASE( ExtendsSelectedLineStartInOppositeDirection )
78{
79 PCB_SHAPE source = makeLine( { 0, 0 }, { 10, 0 } );
80 PCB_SHAPE boundary = makeLine( { -20, -10 }, { -20, 10 } );
81
83
85 BOOST_CHECK_EQUAL( planned( result ).m_Start, VECTOR2I( -20, 0 ) );
86 BOOST_CHECK_EQUAL( planned( result ).m_End, VECTOR2I( 10, 0 ) );
87}
88
89
90BOOST_AUTO_TEST_CASE( ChoosesNearestPositiveIntersection )
91{
92 PCB_SHAPE source = makeLine( { 0, 0 }, { 10, 0 } );
93 PCB_SHAPE nearBoundary = makeLine( { 20, -10 }, { 20, 10 } );
94 PCB_SHAPE farBoundary = makeLine( { 30, -10 }, { 30, 10 } );
95
97 GRAPHIC_EXTEND_PLANNER::Plan( source, GRAPHIC_ENDPOINT::END, { &farBoundary, &nearBoundary } );
98
100 BOOST_CHECK_EQUAL( planned( result ).m_End, VECTOR2I( 20, 0 ) );
101}
102
103
104BOOST_AUTO_TEST_CASE( IgnoresWrongLayerAndNonGraphicItems )
105{
106 PCB_SHAPE source = makeLine( { 0, 0 }, { 10, 0 } );
107 PCB_SHAPE wrongLayer = makeLine( { 20, -10 }, { 20, 10 }, Cmts_User );
108 PCB_TRACK track( nullptr );
109 track.SetStart( { 30, -10 } );
110 track.SetEnd( { 30, 10 } );
111
113
114 BOOST_CHECK( !result );
115 BOOST_CHECK( result.m_Refusal == GRAPHIC_EDIT_REFUSAL::NO_INTERSECTION );
116}
117
118
119BOOST_AUTO_TEST_CASE( RejectsTrackSource )
120{
121 PCB_TRACK source( nullptr );
122 source.SetStart( { 0, 0 } );
123 source.SetEnd( { 10, 0 } );
124 PCB_SHAPE boundary = makeLine( { 20, -10 }, { 20, 10 } );
125
127
128 BOOST_CHECK( !result );
129 BOOST_CHECK( result.m_Refusal == GRAPHIC_EDIT_REFUSAL::UNSUPPORTED_SOURCE );
130}
131
132
133BOOST_AUTO_TEST_CASE( ExtendsLineToFiniteArcBoundary )
134{
135 PCB_SHAPE source = makeLine( { 0, 0 }, { 10, 0 } );
136 PCB_SHAPE boundary = makeArc( { 20, 0 }, { 15, 0 }, 180.0 );
137
139
141 BOOST_CHECK_EQUAL( planned( result ).m_End, VECTOR2I( 15, 0 ) );
142}
143
144
145BOOST_AUTO_TEST_CASE( ExtendsArcEndToFiniteLineBoundary )
146{
147 PCB_SHAPE source = makeArc( { 0, 0 }, { 10, 0 }, 90.0 );
148 SHAPE_ARC extended( { 0, 0 }, { 10, 0 }, EDA_ANGLE( 180.0, DEGREES_T ) );
149 PCB_SHAPE boundary = makeLine( { -20, 0 }, { 20, 0 } );
150
152
154 BOOST_CHECK_EQUAL( planned( result ).m_Start, source.GetStart() );
155 BOOST_CHECK_EQUAL( planned( result ).m_End, extended.GetP1() );
156 SHAPE_ARC resultGeometry( planned( result ).m_Start, planned( result ).m_Mid, planned( result ).m_End, 0 );
157 BOOST_CHECK_CLOSE( resultGeometry.GetCentralAngle().AsDegrees(), 180.0, 0.01 );
158}
159
160
161BOOST_AUTO_TEST_CASE( ExtendsArcStartBackwardAlongCurvature )
162{
163 SHAPE_ARC extended( { 0, 0 }, { 10, 0 }, EDA_ANGLE( 180.0, DEGREES_T ) );
164 PCB_SHAPE source = makeArc( extended.GetCenter(), extended.GetArcMid(), 90.0 );
165 PCB_SHAPE boundary = makeLine( { -20, 0 }, { 20, 0 } );
166
168
170 BOOST_CHECK_EQUAL( planned( result ).m_Start, extended.GetP0() );
171 BOOST_CHECK_EQUAL( planned( result ).m_End, source.GetEnd() );
172}
173
174
175// Millimetre scale. At a few-IU radius two rebuilt circles disagree by a whole IU.
176BOOST_AUTO_TEST_CASE( ExtendsArcToFiniteArcBoundary )
177{
178 PCB_SHAPE source = makeArc( { 0, 0 }, { 10000000, 0 }, 90.0 );
179 SHAPE_ARC expected( { 0, 0 }, { 10000000, 0 }, EDA_ANGLE( 180.0, DEGREES_T ) );
180 PCB_SHAPE boundary = makeArc( expected.GetP1() + VECTOR2I( 0, 5000000 ), expected.GetP1(), 180.0 );
181
183
185 SHAPE_ARC boundaryGeometry( boundary.GetStart(), boundary.GetArcMid(), boundary.GetEnd(), 0 );
186 SHAPE_ARC resultGeometry( planned( result ).m_Start, planned( result ).m_Mid, planned( result ).m_End, 0 );
187 BOOST_CHECK( boundaryGeometry.Collide( planned( result ).m_End ) );
188 BOOST_CHECK_GT( std::abs( resultGeometry.GetCentralAngle().AsDegrees() ), 90.0 );
189 BOOST_CHECK_LT( std::abs( resultGeometry.GetCentralAngle().AsDegrees() ), 180.0 );
190}
191
192
193// A graze is one well-defined place to stop, so the line grows until it touches.
194BOOST_AUTO_TEST_CASE( ExtendsToATangentTouch )
195{
196 PCB_SHAPE source = makeLine( { 0, 10000000 }, { 10000000, 10000000 } );
197 PCB_SHAPE boundary = makeArc( { 20000000, 0 }, { 20000000, 10000000 }, 180.0 );
198
200
202 BOOST_CHECK_LE( planned( result ).m_End.Distance( VECTOR2I( 20000000, 10000000 ) ), 2 );
203}
204
205
206BOOST_AUTO_TEST_CASE( LockedSourceIsRejectedButLockedBoundaryIsEligible )
207{
208 BOARD board;
209 PCB_SHAPE source( &board, SHAPE_T::SEGMENT );
210 source.SetStart( { 0, 0 } );
211 source.SetEnd( { 10, 0 } );
212 source.SetLayer( Dwgs_User );
213 PCB_SHAPE boundary( &board, SHAPE_T::SEGMENT );
214 boundary.SetStart( { 20, -10 } );
215 boundary.SetEnd( { 20, 10 } );
216 boundary.SetLayer( Dwgs_User );
217 boundary.SetLocked( true );
218
219 BOOST_CHECK( GRAPHIC_EXTEND_PLANNER::Plan( source, GRAPHIC_ENDPOINT::END, { &boundary } ) );
220
221 source.SetLocked( true );
223 BOOST_CHECK( !result );
224 BOOST_CHECK( result.m_Refusal == GRAPHIC_EDIT_REFUSAL::LOCKED_SOURCE );
225}
226
227
228BOOST_AUTO_TEST_CASE( PointerChoosesNearestEndpoint )
229{
230 PCB_SHAPE line = makeLine( { 0, 0 }, { 100, 0 } );
231 PCB_SHAPE wide = makeLine( { -1500000000, 0 }, { 0, 0 } );
232
233 BOOST_CHECK( GRAPHIC_EXTEND_PLANNER::NearestEndpoint( line, { 10, 5 } ) == GRAPHIC_ENDPOINT::START );
234 BOOST_CHECK( GRAPHIC_EXTEND_PLANNER::NearestEndpoint( line, { 90, -5 } ) == GRAPHIC_ENDPOINT::END );
235
236 // Distance() must widen before subtracting or this pointer wraps.
237 BOOST_CHECK( GRAPHIC_EXTEND_PLANNER::NearestEndpoint( wide, { 1500000000, 0 } ) == GRAPHIC_ENDPOINT::END );
238}
239
240
241BOOST_AUTO_TEST_CASE( QueryBoundsFollowTheExtensionRay )
242{
243 PCB_SHAPE line = makeLine( { 0, 0 }, { 10, 10 } );
244 BOX2I world( { -100, -100 }, { 200, 200 } );
245
248
249 BOOST_CHECK_EQUAL( endBounds.GetPosition(), VECTOR2I( 10, 10 ) );
250 BOOST_CHECK_EQUAL( endBounds.GetSize(), VECTOR2I( 90, 90 ) );
251 BOOST_CHECK_EQUAL( startBounds.GetPosition(), VECTOR2I( -100, -100 ) );
252 BOOST_CHECK_EQUAL( startBounds.GetSize(), VECTOR2I( 100, 100 ) );
253
254 // Clipping must not overflow on a line spanning most of the range.
255 PCB_SHAPE wide = makeLine( { -1000000000, 0 }, { 800000000, 0 } );
256 BOX2I wideWorld( { 0, -100 }, { 1000000000, 200 } );
257 BOX2I wideBounds = GRAPHIC_EXTEND_PLANNER::QueryBounds( wide, GRAPHIC_ENDPOINT::END, wideWorld );
258
259 BOOST_CHECK_EQUAL( wideBounds.GetPosition(), VECTOR2I( 800000000, 0 ) );
260 BOOST_CHECK_EQUAL( wideBounds.GetSize(), VECTOR2I( 200000000, 0 ) );
261}
262
263
264BOOST_AUTO_TEST_CASE( ExtendsBoardScaleLineForward )
265{
266 PCB_SHAPE source = makeLine( { -1000000000, 0 }, { 800000000, 0 } );
267 PCB_SHAPE boundary = makeLine( { 900000000, -10 }, { 900000000, 10 } );
268
270
272 BOOST_CHECK_EQUAL( planned( result ).m_End, VECTOR2I( 900000000, 0 ) );
273}
274
275
276BOOST_AUTO_TEST_CASE( IgnoresBoundaryBehindTheExtendedEndpoint )
277{
278 PCB_SHAPE source = makeLine( { 0, 0 }, { 10000000, 0 } );
279 PCB_SHAPE behind = makeLine( { 5000000, -1000000 }, { 5000000, 1000000 } );
280 PCB_SHAPE ahead = makeLine( { 20000000, -1000000 }, { 20000000, 1000000 } );
281
282 // The ray is anchored on the fixed end. It covers the shape's own span.
283 BOOST_CHECK( !GRAPHIC_EXTEND_PLANNER::Plan( source, GRAPHIC_ENDPOINT::END, { &behind } ) );
284
286
288 BOOST_CHECK_EQUAL( planned( result ).m_End, VECTOR2I( 20000000, 0 ) );
289}
290
291
294{
295 const GRAPHIC_EDIT_GEOMETRY& geometry = planned( aResult );
296
297 return CIRCLE( geometry.m_Start, geometry.m_Start.Distance( geometry.m_End ) );
298}
299
300
301// Everything the arc could reach is round past the point it closes on itself, so it closes.
302BOOST_AUTO_TEST_CASE( ArcPastAFullTurnClosesIntoACircle )
303{
304 PCB_SHAPE source = makeArc( { 0, 0 }, { 10000000, 0 }, 300.0 );
305 PCB_SHAPE boundary = makeLine( { -15000000, -15000000 }, { 15000000, 15000000 } );
306
308
310 BOOST_REQUIRE_EQUAL( result.m_Geometry.size(), 1 );
311 BOOST_CHECK( planned( result ).m_Shape == SHAPE_T::CIRCLE );
312 BOOST_CHECK_EQUAL( closedCircle( result ).Center, VECTOR2I( 0, 0 ) );
313 BOOST_CHECK_LE( std::abs( closedCircle( result ).Radius - 10000000 ), 2 );
314 BOOST_CHECK( result.m_Boundaries.empty() );
315}
316
317
318// An arc on its own has nothing to stop it, so it goes all the way round.
319BOOST_AUTO_TEST_CASE( ArcWithNothingToReachClosesIntoACircle )
320{
321 PCB_SHAPE source = makeArc( { 0, 0 }, { 10000000, 0 }, 90.0 );
322
324
326 BOOST_CHECK( planned( result ).m_Shape == SHAPE_T::CIRCLE );
327 BOOST_CHECK_EQUAL( closedCircle( result ).Center, VECTOR2I( 0, 0 ) );
328 BOOST_CHECK_LE( std::abs( closedCircle( result ).Radius - 10000000 ), 2 );
329
330 // Which end the pointer picked makes no difference to a closed circle.
332
333 BOOST_REQUIRE( fromStart );
334 BOOST_CHECK_EQUAL( closedCircle( fromStart ).Center, closedCircle( result ).Center );
335 BOOST_CHECK_EQUAL( closedCircle( fromStart ).Radius, closedCircle( result ).Radius );
336}
337
338
339// A boundary within reach still wins. Closing is only what happens when nothing is.
340BOOST_AUTO_TEST_CASE( ReachableBoundaryBeatsClosingTheCircle )
341{
342 PCB_SHAPE source = makeArc( { 0, 0 }, { 10000000, 0 }, 90.0 );
343 PCB_SHAPE boundary = makeLine( { -15000000, 5000000 }, { 15000000, 5000000 } );
344
346
348 BOOST_CHECK( planned( result ).m_Shape == SHAPE_T::ARC );
349 BOOST_CHECK_EQUAL( result.m_Boundaries.size(), 1 );
350}
351
352
353// A line has no end to come back round to, so it still refuses.
354BOOST_AUTO_TEST_CASE( LineWithNothingToReachStillRefuses )
355{
356 PCB_SHAPE source = makeLine( { 0, 0 }, { 10000000, 0 } );
357
359
360 BOOST_CHECK( !result );
361 BOOST_CHECK( result.m_Refusal == GRAPHIC_EDIT_REFUSAL::NO_INTERSECTION );
362}
363
364
365// The shape from the test board that reported "nothing to reach in that direction". Its chord
366// crosses the carrier circle, but only round past where the arc closes on itself.
367BOOST_AUTO_TEST_CASE( WideArcWhoseChordIsOutOfReachCloses )
368{
369 PCB_SHAPE source( nullptr, SHAPE_T::ARC );
370 source.SetArcGeometry( { 25000000, 87000000 }, { 35000000, 70000000 }, { 45000000, 87000000 } );
371 source.SetLayer( Dwgs_User );
372
373 PCB_SHAPE chord = makeLine( { 20000000, 80000000 }, { 50000000, 80000000 } );
374
376
378 BOOST_CHECK( planned( result ).m_Shape == SHAPE_T::CIRCLE );
379 BOOST_CHECK_LE( closedCircle( result ).Center.Distance( VECTOR2I( 35000000, 81441176 ) ), 2 );
380}
381
382
383// Neither gives an unambiguous direction. The radius also overflows the search box.
384BOOST_AUTO_TEST_CASE( DegenerateSourcesReportWhyTheyWereRefused )
385{
386 PCB_SHAPE zeroLength = makeLine( { 1000, 1000 }, { 1000, 1000 } );
387 int radius = std::numeric_limits<int>::max() / 2 + 100;
388 PCB_SHAPE hugeArc = makeArc( { 0, 0 }, { radius, 0 }, 90.0 );
389 BOX2I world( { std::numeric_limits<int>::min() / 2, std::numeric_limits<int>::min() / 2 },
390 { std::numeric_limits<int>::max(), std::numeric_limits<int>::max() } );
391
392 BOOST_CHECK( GRAPHIC_EXTEND_PLANNER::Plan( zeroLength, GRAPHIC_ENDPOINT::END, {} ).m_Refusal
394 BOOST_CHECK( !GRAPHIC_EXTEND_PLANNER::QueryBounds( hugeArc, GRAPHIC_ENDPOINT::END, world ).IsValid() );
395 BOOST_CHECK( !GRAPHIC_EXTEND_PLANNER::Plan( hugeArc, GRAPHIC_ENDPOINT::END, {} ) );
396}
397
398
399// A large arc rebuilt from centre and sweep lands tens of IU off. The intersection is rounded.
400BOOST_AUTO_TEST_CASE( ExtendedLargeArcLandsOnItsBoundary )
401{
402 PCB_SHAPE source = makeArc( { 0, 0 }, { 100000000, 0 }, 10.0 );
403 PCB_SHAPE boundary = makeLine( { 60000000, 60000000 }, { 120000000, 10000000 } );
404
406
408 BOOST_CHECK( SEG( boundary.GetStart(), boundary.GetEnd() ).Contains( planned( result ).m_End ) );
409}
410
411
412BOOST_AUTO_TEST_CASE( CollinearBoundariesAreRejectedInBothEndpointOrders )
413{
414 PCB_SHAPE source = makeLine( { 0, 0 }, { 10, 0 } );
415 PCB_SHAPE forward = makeLine( { 20, 0 }, { 30, 0 } );
416 PCB_SHAPE reversed = makeLine( { 30, 0 }, { 20, 0 } );
417
418 BOOST_CHECK( !GRAPHIC_EXTEND_PLANNER::Plan( source, GRAPHIC_ENDPOINT::END, { &forward } ) );
419 BOOST_CHECK( !GRAPHIC_EXTEND_PLANNER::Plan( source, GRAPHIC_ENDPOINT::END, { &reversed } ) );
420}
421
422
423BOOST_AUTO_TEST_CASE( ExtendsNegativeSweepArc )
424{
425 SHAPE_ARC expected( { 0, 0 }, { 10, 0 }, EDA_ANGLE( -180.0, DEGREES_T ) );
426 PCB_SHAPE source = makeArc( { 0, 0 }, { 10, 0 }, -90.0 );
427 PCB_SHAPE boundary = makeLine( expected.GetP1() - VECTOR2I( 10, 0 ), expected.GetP1() + VECTOR2I( 10, 0 ) );
428
429 BOOST_REQUIRE( source.EndsSwapped() );
431
433 BOOST_CHECK_EQUAL( planned( result ).m_Start, expected.GetP1() );
434 BOOST_CHECK_EQUAL( planned( result ).m_End, source.GetEnd() );
435 SHAPE_ARC resultGeometry( planned( result ).m_Start, planned( result ).m_Mid, planned( result ).m_End, 0 );
436 BOOST_CHECK_CLOSE( resultGeometry.GetCentralAngle().AsDegrees(), 180.0, 0.01 );
437}
438
439
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
void SetLocked(bool aLocked) override
Definition board_item.h:417
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:409
constexpr const Vec & GetPosition() const
Definition box2.h:208
constexpr const SizeVec & GetSize() const
Definition box2.h:203
Represent basic circle geometry with utility geometry functions.
Definition circle.h:33
double AsDegrees() const
Definition eda_angle.h:116
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:275
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
void SetEnd(const VECTOR2I &aEnd)
Definition pcb_track.h:89
void SetStart(const VECTOR2I &aStart)
Definition pcb_track.h:92
Definition seg.h:38
bool Contains(const SEG &aSeg) const
Definition seg.h:320
EDA_ANGLE GetCentralAngle() const
Get the "central angle" of the arc - this is the angle at the point of the "pie slice".
const VECTOR2I & GetArcMid() const
Definition shape_arc.h:116
const VECTOR2I & GetP1() const
Definition shape_arc.h:115
bool Collide(const SEG &aSeg, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the segment aSeg than aClearance,...
const VECTOR2I & GetP0() const
Definition shape_arc.h:114
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
Definition vector2d.h:549
@ DEGREES_T
Definition eda_angle.h:31
@ SEGMENT
Definition eda_shape.h:56
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ Dwgs_User
Definition layer_ids.h:103
@ Cmts_User
Definition layer_ids.h:104
BOX2I QueryBounds(const BOARD_ITEM &aSource, GRAPHIC_ENDPOINT aEndpoint, const BOX2I &aWorldBounds)
GRAPHIC_ENDPOINT NearestEndpoint(const BOARD_ITEM &aSource, const VECTOR2I &aPointer)
GRAPHIC_EDIT_RESULT Plan(const BOARD_ITEM &aSource, GRAPHIC_ENDPOINT aEndpoint, const std::vector< const BOARD_ITEM * > &aBoundaries)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:411
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
static PCB_SHAPE makeArc(const VECTOR2I &aCenter, const VECTOR2I &aStart, double aAngle, PCB_LAYER_ID aLayer=Dwgs_User)
BOOST_AUTO_TEST_CASE(ExtendsSelectedLineEndToFiniteLineBoundary)
static const GRAPHIC_EDIT_GEOMETRY & planned(const GRAPHIC_EDIT_RESULT &aResult)
static CIRCLE closedCircle(const GRAPHIC_EDIT_RESULT &aResult)
The circle an arc closed into, for checking.
static PCB_SHAPE makeLine(const VECTOR2I &aStart, const VECTOR2I &aEnd, PCB_LAYER_ID aLayer=Dwgs_User)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
VECTOR3I expected(15, 30, 45)
int radius
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683