KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_utils.cpp
Go to the documentation of this file.
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2014 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * Author: Tomasz Wlostowski <[email protected]>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22#include "pns_utils.h"
23#include "pns_line.h"
24#include "pns_via.h"
25#include "pns_router.h"
26#include "pns_debug_decorator.h"
27#include "pns_arc.h"
28#include "pns_node.h"
29
30#include <core/minoptmax.h>
31
32#include <geometry/shape_arc.h>
37#include <math/box2.h>
38
39#include <cmath>
40
41namespace PNS {
42
43const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0, const VECTOR2I& aSize,
44 int aClearance, int aChamfer )
45{
47
48 s.SetClosed( true );
49
50 s.Append( aP0.x - aClearance, aP0.y - aClearance + aChamfer );
51
52 if( aChamfer )
53 s.Append( aP0.x - aClearance + aChamfer, aP0.y - aClearance );
54
55 s.Append( aP0.x + aSize.x + aClearance - aChamfer, aP0.y - aClearance );
56
57 if( aChamfer )
58 s.Append( aP0.x + aSize.x + aClearance, aP0.y - aClearance + aChamfer );
59
60 s.Append( aP0.x + aSize.x + aClearance, aP0.y + aSize.y + aClearance - aChamfer );
61
62 if( aChamfer )
63 s.Append( aP0.x + aSize.x + aClearance - aChamfer, aP0.y + aSize.y + aClearance );
64
65 s.Append( aP0.x - aClearance + aChamfer, aP0.y + aSize.y + aClearance );
66
67 if( aChamfer )
68 s.Append( aP0.x - aClearance, aP0.y + aSize.y + aClearance - aChamfer );
69
70 return s;
71}
72
73
74const SHAPE_LINE_CHAIN ArcHull( const SHAPE_ARC& aArc, int aClearance, int aWalkaroundThickness )
75{
76 int cl = aClearance + ( aWalkaroundThickness + 1 ) / 2;
77
78 // If we can't route through the arc, we might as well treat it as a circle
79 if( aArc.GetCentralAngle().AsDegrees() > 180.0 && aArc.GetChord().Length() < cl )
80 {
81 int r = aArc.GetRadius();
82 return OctagonalHull( aArc.GetCenter() - VECTOR2I( r, r ),
83 VECTOR2I( 2 * r, 2 * r ),
84 cl,
85 2.0 * ( 1.0 - M_SQRT1_2 ) * ( r + cl ) );
86 }
87
88 int d = aArc.GetWidth() / 2 + cl + SHAPE_ARC::DefaultAccuracyForPCB();
89 int x = (int) ( 2.0 / ( 1.0 + M_SQRT2 ) * d ) / 2;
90
91 auto line = aArc.ConvertToPolyline( ARC_LOW_DEF );
92
94 s.SetClosed( true );
95 std::vector<VECTOR2I> reverse_line;
96
97 auto seg = line.Segment( 0 );
98 VECTOR2I dir = seg.B - seg.A;
99 VECTOR2I p0 = -dir.Perpendicular().Resize( d );
100 VECTOR2I ds = -dir.Perpendicular().Resize( x );
101 VECTOR2I pd = dir.Resize( x );
102 VECTOR2I dp = dir.Resize( d );
103
104 // Append the first curve
105 s.Append( seg.A + p0 - pd );
106 s.Append( seg.A - dp + ds );
107 s.Append( seg.A - dp - ds );
108 s.Append( seg.A - p0 - pd );
109
110 for( int i = 1; i < line.SegmentCount(); i++ )
111 {
112 // calculate a vertex normal (average of segment normals)
113 auto pp =
114 ( line.CSegment( i - 1 ).B - line.CSegment( i - 1 ).A ).Perpendicular().Resize( d );
115 auto pp2 = ( line.CSegment( i ).B - line.CSegment( i ).A ).Perpendicular().Resize( d );
116
117 auto sa_out = line.CSegment( i - 1 ), sa_in = line.CSegment( i - 1 );
118 auto sb_out = line.CSegment( i ), sb_in = line.CSegment( i );
119
120 sa_out.A += pp;
121 sa_out.B += pp;
122 sb_out.A += pp2;
123 sb_out.B += pp2;
124
125 sa_in.A -= pp;
126 sa_in.B -= pp;
127 sb_in.A -= pp2;
128 sb_in.B -= pp2;
129
130 auto ip_out = sa_out.IntersectLines( sb_out );
131 auto ip_in = sa_in.IntersectLines( sb_in );
132
133 seg = line.CSegment( i );
134 s.Append( *ip_out );
135 reverse_line.push_back( *ip_in );
136 }
137
138 seg = line.CSegment( -1 );
139 dir = seg.B - seg.A;
140 p0 = -dir.Perpendicular().Resize( d );
141 ds = -dir.Perpendicular().Resize( x );
142 pd = dir.Resize( x );
143 dp = dir.Resize( d );
144 s.Append( seg.B - p0 + pd );
145 s.Append( seg.B + dp - ds );
146 s.Append( seg.B + dp + ds );
147 s.Append( seg.B + p0 + pd );
148
149 for( int i = reverse_line.size() - 1; i >= 0; i-- )
150 s.Append( reverse_line[i] );
151
152 // make sure the hull outline is always clockwise
153 if( s.CSegment( 0 ).Side( line.Segment( 0 ).A ) < 0 )
154 return s.Reverse();
155 else
156 return s;
157}
158
159
160static bool IsSegment45Degree( const SEG& aS )
161{
162 VECTOR2I dir( aS.B - aS.A );
163
164 if( std::abs( dir.x ) <= 1 )
165 return true;
166
167 if( std::abs( dir.y ) <= 1 )
168 return true;
169
170 int delta = std::abs(dir.x) - std::abs(dir.y);
171
172 if( delta >= -1 && delta <= 1)
173 return true;
174
175 return false;
176}
177
178
179template <typename T> int sgn(T val) {
180 return (T(0) < val) - (val < T(0));
181}
182
183
184const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, int aClearance,
185 int aWalkaroundThickness )
186{
187 const int kinkThreshold = aClearance / 10;
188
189 int cl = aClearance + aWalkaroundThickness / 2;
190 double d = (double)aSeg.GetWidth() / 2.0 + cl;
191 double x = 2.0 / ( 1.0 + M_SQRT2 ) * d;
192 int dr = KiROUND( d );
193 int xr2 = KiROUND( x / 2.0 );
194
195 const VECTOR2I a = aSeg.GetSeg().A;
196 VECTOR2I b = aSeg.GetSeg().B;
197 int len = aSeg.GetSeg().Length();
198 int w = b.x - a.x;
199 int h = b.y - a.y;
200
201 /*
202 auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
203
204 if( len < kinkThreshold )
205 {
206 PNS_DBG( dbg, AddShape, &aSeg, CYAN, 10000, wxString::Format( "kinky-seg 45 %d l %d dx %d dy %d", !!IsSegment45Degree( aSeg.GetSeg() ), len, w, h ) );
207 }
208 */
209
210 if( a != b )
211 {
212 if ( !IsSegment45Degree( aSeg.GetSeg() ) )
213 {
214 if ( len <= kinkThreshold && len > 0 )
215 {
216 int ll = std::max( std::abs( w ), std::abs( h ) );
217
218 b = a + VECTOR2I( sgn( w ) * ll, sgn( h ) * ll );
219 }
220 }
221 else
222 {
223 if( len <= kinkThreshold )
224 {
225 int delta45 = std::abs( std::abs(w) - std::abs(h) );
226 if( std::abs(w) <= 1 ) // almost vertical
227 {
228 w = 0;
229 cl ++;
230 }
231 else if ( std::abs(h) <= 1 ) // almost horizontal
232 {
233 h = 0;
234 cl ++;
235 }
236 else if ( delta45 <= 2 ) // almost 45 degree
237 {
238 int newW = sgn( w ) * std::max( std::abs(w), std::abs( h ) );
239 int newH = sgn( h ) * std::max( std::abs(w), std::abs( h ) );
240 w = newW;
241 h = newH;
242 cl += 2;
243 //PNS_DBG( dbg, AddShape, &aSeg, CYAN, 10000, wxString::Format( "almostkinky45 45 %d l %d dx %d dy %d", !!IsSegment45Degree( aSeg.GetSeg() ), len, w, h ) );
244
245 }
246
247 b.x = a.x + w;
248 b.y = a.y + h;
249 }
250 }
251 }
252
253 if( a == b )
254 {
255 int xx2 = KiROUND( 2.0 * ( 1.0 - M_SQRT1_2 ) * d );
256
257 auto ohull = OctagonalHull( a - VECTOR2I( aSeg.GetWidth() / 2, aSeg.GetWidth() / 2 ),
258 VECTOR2I( aSeg.GetWidth(), aSeg.GetWidth() ),
259 cl,
260 xx2 );
261
262 return ohull;
263 }
264
265 VECTOR2I dir = b - a;
266 VECTOR2I p0 = dir.Perpendicular().Resize( dr );
267 VECTOR2I ds = dir.Perpendicular().Resize( xr2 );
268 VECTOR2I pd = dir.Resize( xr2 );
269 VECTOR2I dp = dir.Resize( dr );
270
272
273 s.SetClosed( true );
274
275 s.Append( b + p0 + pd );
276 s.Append( b + dp + ds );
277 s.Append( b + dp - ds );
278 s.Append( b - p0 + pd );
279 s.Append( a - p0 - pd );
280 s.Append( a - dp - ds );
281 s.Append( a - dp + ds );
282 s.Append( a + p0 - pd );
283
284 // make sure the hull outline is always clockwise
285 if( s.CSegment( 0 ).Side( a ) < 0 )
286 return s.Reverse();
287 else
288 return s;
289}
290
291
292static void MoveDiagonal( SEG& aDiagonal, const SHAPE_LINE_CHAIN& aVertices, int aClearance )
293{
294 int dist;
295
296 aVertices.NearestPoint( aDiagonal, dist );
297 VECTOR2I moveBy = ( aDiagonal.A - aDiagonal.B ).Perpendicular().Resize( dist - aClearance );
298 aDiagonal.A += moveBy;
299 aDiagonal.B += moveBy;
300}
301
302
303const SHAPE_LINE_CHAIN ConvexHull( const SHAPE_SIMPLE& aConvex, int aClearance )
304{
305 // this defines the horizontal and vertical lines in the hull octagon
306 BOX2I box = aConvex.BBox( aClearance );
307 box.Normalize();
308
309 SEG topline = SEG( VECTOR2I( box.GetX(), box.GetY() + box.GetHeight() ),
310 VECTOR2I( box.GetX() + box.GetWidth(), box.GetY() + box.GetHeight() ) );
311 SEG rightline = SEG( VECTOR2I( box.GetX() + box.GetWidth(), box.GetY() + box.GetHeight() ),
312 VECTOR2I( box.GetX() + box.GetWidth(), box.GetY() ) );
313 SEG bottomline = SEG( VECTOR2I( box.GetX() + box.GetWidth(), box.GetY() ),
314 box.GetOrigin() );
315 SEG leftline = SEG( box.GetOrigin(), VECTOR2I( box.GetX(), box.GetY() + box.GetHeight() ) );
316
317 const SHAPE_LINE_CHAIN& vertices = aConvex.Vertices();
318
319 // top right diagonal
320 VECTOR2I corner = box.GetOrigin() + box.GetSize();
321 SEG toprightline = SEG( corner,
322 corner + VECTOR2I( box.GetHeight(), -box.GetHeight() ) );
323 MoveDiagonal( toprightline, vertices, aClearance );
324
325 // bottom right diagonal
326 corner = box.GetOrigin() + VECTOR2I( box.GetWidth(), 0 );
327 SEG bottomrightline = SEG( corner + VECTOR2I( box.GetHeight(), box.GetHeight() ),
328 corner );
329 MoveDiagonal( bottomrightline, vertices, aClearance );
330
331 // bottom left diagonal
332 corner = box.GetOrigin();
333 SEG bottomleftline = SEG( corner,
334 corner + VECTOR2I( -box.GetHeight(), box.GetHeight() ) );
335 MoveDiagonal( bottomleftline, vertices, aClearance );
336
337 // top left diagonal
338 corner = box.GetOrigin() + VECTOR2I( 0, box.GetHeight() );
339 SEG topleftline = SEG( corner + VECTOR2I( -box.GetHeight(), -box.GetHeight() ),
340 corner );
341 MoveDiagonal( topleftline, vertices, aClearance );
342
343 SHAPE_LINE_CHAIN octagon;
344 octagon.SetClosed( true );
345
346 octagon.Append( *leftline.IntersectLines( bottomleftline ) );
347 octagon.Append( *bottomline.IntersectLines( bottomleftline ) );
348 octagon.Append( *bottomline.IntersectLines( bottomrightline ) );
349 octagon.Append( *rightline.IntersectLines( bottomrightline ) );
350 octagon.Append( *rightline.IntersectLines( toprightline ) );
351 octagon.Append( *topline.IntersectLines( toprightline ) );
352 octagon.Append( *topline.IntersectLines( topleftline ) );
353 octagon.Append( *leftline.IntersectLines( topleftline ) );
354
355 return octagon;
356}
357
358
360{
361 SHAPE_RECT r;
362
363 VECTOR2I delta( aSeg.GetWidth() / 2, aSeg.GetWidth() / 2 );
364 VECTOR2I p0( aSeg.GetSeg().A - delta );
365 VECTOR2I p1( aSeg.GetSeg().B + delta );
366
367 return SHAPE_RECT( std::min( p0.x, p1.x ), std::min( p0.y, p1.y ),
368 std::abs( p1.x - p0.x ), std::abs( p1.y - p0.y ) );
369}
370
371
372OPT_BOX2I ChangedArea( const ITEM* aItemA, const ITEM* aItemB )
373{
374 if( aItemA->OfKind( ITEM::VIA_T ) && aItemB->OfKind( ITEM::VIA_T ) )
375 {
376 const VIA* va = static_cast<const VIA*>( aItemA );
377 const VIA* vb = static_cast<const VIA*>( aItemB );
378
379 return va->ChangedArea( vb );
380 }
381 else if( aItemA->OfKind( ITEM::LINE_T ) && aItemB->OfKind( ITEM::LINE_T ) )
382 {
383 const LINE* la = static_cast<const LINE*> ( aItemA );
384 const LINE* lb = static_cast<const LINE*> ( aItemB );
385
386 return la->ChangedArea( lb );
387 }
388
389 return OPT_BOX2I();
390}
391
392OPT_BOX2I ChangedArea( const LINE& aLineA, const LINE& aLineB )
393{
394 return aLineA.ChangedArea( &aLineB );
395}
396
397
400{
402
403 if( line.PointCount() < 2 )
404 return;
405
406 hull.Intersect( line, ips_raw );
407
408 for( auto& p : ips_raw )
409 {
411
412 SEG d1[2];
413 VECTOR2I d2[2];
414 int d1_idx = 0, d2_idx = 0;
415
416 ipp = p;
417 ipp.valid = false;
418
419 if( !p.is_corner_our && !p.is_corner_their )
420 {
421 ipp.valid = true;
422 ips.push_back( ipp );
423 continue;
424 }
425
426 if( p.index_our >= hull.SegmentCount() )
427 p.index_our -= hull.SegmentCount();
428
429 if( p.is_corner_our )
430 {
431 d1[0] = hull.CSegment( p.index_our );
432 d1[1] = hull.CSegment( p.index_our - 1 );
433 d1_idx = 2;
434 }
435 else
436 {
437 d1[0] = hull.CSegment( p.index_our );
438 d1_idx = 1;
439 }
440
441 if( p.is_corner_their )
442 {
443 if( p.index_their > 0 )
444 {
445 d2[d2_idx++] = line.CSegment( p.index_their - 1 ).A;
446 }
447 if( p.index_their < line.PointCount() - 1 )
448 {
449 d2[d2_idx++] = line.CSegment( p.index_their ).B;
450 }
451 }
452 else
453 {
454 d2[d2_idx++] = line.CSegment( p.index_their ).A;
455 d2[d2_idx++] = line.CSegment( p.index_their ).B;
456 }
457
458 for( int i = 0; i < d1_idx; i++ )
459 {
460 for( int j = 0; j < d2_idx; j++ )
461 {
462 if( d1[i].Side( d2[j] ) > 0 )
463 {
464 ipp.valid = true;
465 }
466 }
467 }
468
469#ifdef TOM_EXTRA_DEBUG
470 printf("p %d %d hi %d their %d co %d ct %d ipv %d\n", p.p.x, p.p.y, p.index_our, p.index_their, p.is_corner_our?1:0, p.is_corner_their?1:0, ipp.valid ?1:0);
471 printf("d1 %d d2 %d\n", d1_idx, d2_idx );
472#endif
473 if( ipp.valid )
474 {
475 ips.push_back( ipp );
476 }
477 }
478}
479
480
481const SHAPE_LINE_CHAIN BuildHullForPrimitiveShape( const SHAPE* aShape, int aClearance,
482 int aWalkaroundThickness )
483{
484 int cl = aClearance + ( aWalkaroundThickness + 1 )/ 2;
485
486 switch( aShape->Type() )
487 {
488 case SH_RECT:
489 {
490 const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>( aShape );
491 return OctagonalHull( rect->GetPosition(),
492 rect->GetSize(),
493 cl,
494 0 );
495 }
496
497 case SH_CIRCLE:
498 {
499 const SHAPE_CIRCLE* circle = static_cast<const SHAPE_CIRCLE*>( aShape );
500 int r = circle->GetRadius();
501 return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ),
502 VECTOR2I( 2 * r, 2 * r ),
503 cl,
504 2.0 * ( 1.0 - M_SQRT1_2 ) * ( r + cl ) );
505 }
506
507 case SH_SEGMENT:
508 {
509 const SHAPE_SEGMENT* seg = static_cast<const SHAPE_SEGMENT*>( aShape );
510 return SegmentHull( *seg, aClearance, aWalkaroundThickness );
511 }
512
513 case SH_ARC:
514 {
515 const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( aShape );
516 return ArcHull( *arc, aClearance, aWalkaroundThickness );
517 }
518
519 case SH_SIMPLE:
520 {
521 const SHAPE_SIMPLE* convex = static_cast<const SHAPE_SIMPLE*>( aShape );
522
523 return ConvexHull( *convex, cl );
524 }
525
526 case SH_ELLIPSE:
527 {
528 const SHAPE_ELLIPSE* ellipse = static_cast<const SHAPE_ELLIPSE*>( aShape );
529 const BOX2I bbox = ellipse->BBox();
530
531 return OctagonalHull( bbox.GetPosition(), bbox.GetSize(), cl, 0 );
532 }
533
534 default:
535 {
536 wxFAIL_MSG( wxString::Format( wxT( "Unsupported hull shape: %d (%s)." ),
537 aShape->Type(),
538 SHAPE_TYPE_asString( aShape->Type() ) ) );
539 break;
540 }
541 }
542
543 return SHAPE_LINE_CHAIN();
544}
545
546
547void NodeStats( DEBUG_DECORATOR* dbg, wxString label, PNS::NODE *node )
548{
549 NODE::ITEM_VECTOR added, removed;
550 node->GetUpdatedItems( removed, added );
551
552 PNS_DBG( dbg, BeginGroup, wxString::Format( "node:%s this=%p depth=%d added=%d removed=%d",
553 label, node, node->Depth(), (int)added.size(), (int) removed.size() ), 0 );
554
555 for( auto& item : added )
556 PNS_DBG( dbg, AddItem, item, BLUE, 10000, wxT("added-item") );
557 for( auto& item : removed )
558 PNS_DBG( dbg, AddItem, item, RED, 10000, wxString::Format("removed-item") );
559
560 PNS_DBGN( dbg, EndGroup );
561}
562
563
564bool SplitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I& aP )
565{
566 if( !aSeg )
567 return false;
568
569 if( !aSeg->OfKind( ITEM::SEGMENT_T ) )
570 return false;
571
572 const JOINT* jt = aNode->FindJoint( aP, aSeg );
573
574 if( jt && jt->LinkCount() >= 1 )
575 {
576 return false;
577 }
578
579 SEGMENT* s_old = static_cast<SEGMENT*>( aSeg );
580
581 if( s_old->Seg().Distance( aP ) > 100 )
582 return false;
583
584 aNode->Remove( s_old );
585
586 if( s_old->Seg().B != aP )
587 {
588 std::unique_ptr<SEGMENT> s_new ( Clone( *s_old ) );
589 s_new->SetEnds( s_old->Seg().A, aP );
590 s_new->Unmark();
591 aNode->Add( std::move( s_new ), true );
592 }
593
594 if( s_old->Seg().A != aP )
595 {
596 std::unique_ptr<SEGMENT> s_new ( Clone( *s_old ) );
597 s_new->SetEnds( aP, s_old->Seg().B );
598 s_new->Unmark();
599 aNode->Add( std::move( s_new ), true );
600 }
601
602 return true;
603}
604
605
606bool SplitAdjacentArcs( NODE* aNode, ITEM* aArc, const VECTOR2I& aP )
607{
608 if( !aArc )
609 return false;
610
611 if( !aArc->OfKind( ITEM::ARC_T ) )
612 return false;
613
614 const JOINT* jt = aNode->FindJoint( aP, aArc );
615
616 if( jt && jt->LinkCount() >= 1 )
617 return false;
618
619 ARC* a_old = static_cast<ARC*>( aArc );
620 const SHAPE_ARC& o_arc = a_old->Arc();
621
622 std::unique_ptr<ARC> a_new[2] = { Clone( *a_old ), Clone( *a_old ) };
623
624 a_new[0]->Arc().ConstructFromStartEndCenter( o_arc.GetP0(), aP, o_arc.GetCenter(),
625 o_arc.IsClockwise(), o_arc.GetWidth() );
626
627 a_new[1]->Arc().ConstructFromStartEndCenter( aP, o_arc.GetP1(), o_arc.GetCenter(),
628 o_arc.IsClockwise(), o_arc.GetWidth() );
629
630 aNode->Remove( a_old );
631 aNode->Add( std::move( a_new[0] ), true );
632 aNode->Add( std::move( a_new[1] ), true );
633
634 return true;
635}
636
637const wxString Format( const MINOPTMAX<int> x )
638{
639 wxString ret;
640
641 ret = wxT( "min:" );
642 if( x.HasMin() )
643 ret.Append( wxString::Format( wxT( "%d" ), x.Min() ) );
644 else
645 ret.Append( wxT( "none" ) );
646
647 ret.Append( wxT( " max:" ) );
648 if( x.HasMax() )
649 ret.Append( wxString::Format( wxT( "%d" ), x.Max() ) );
650 else
651 ret.Append( wxT( "none" ) );
652
653 ret.Append( wxT( " opt:" ) );
654 if( x.HasOpt() )
655 ret.Append( wxString::Format( wxT( "%d" ), x.Opt() ) );
656 else
657 ret.Append( wxT( "none" ) );
658
659 return ret;
660}
661}
constexpr int ARC_LOW_DEF
Definition base_units.h:136
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
std::optional< BOX2I > OPT_BOX2I
Definition box2.h:931
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:995
constexpr const Vec & GetPosition() const
Definition box2.h:208
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:143
constexpr coord_type GetY() const
Definition box2.h:205
constexpr size_type GetWidth() const
Definition box2.h:211
constexpr coord_type GetX() const
Definition box2.h:204
constexpr size_type GetHeight() const
Definition box2.h:212
constexpr const Vec & GetOrigin() const
Definition box2.h:207
constexpr const SizeVec & GetSize() const
Definition box2.h:203
double AsDegrees() const
Definition eda_angle.h:116
T Min() const
Definition minoptmax.h:29
bool HasMax() const
Definition minoptmax.h:35
bool HasMin() const
Definition minoptmax.h:34
T Max() const
Definition minoptmax.h:30
T Opt() const
Definition minoptmax.h:31
bool HasOpt() const
Definition minoptmax.h:36
SHAPE_ARC & Arc()
Definition pns_arc.h:115
Base class for PNS router board items.
Definition pns_item.h:98
bool OfKind(int aKindMask) const
Definition pns_item.h:181
A 2D point on a given set of layers and belonging to a certain net, that links together a number of b...
Definition pns_joint.h:43
int LinkCount(int aMask=-1) const
Definition pns_joint.h:318
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition pns_line.h:62
OPT_BOX2I ChangedArea(const LINE *aOther) const
Keep the router "world" - i.e.
Definition pns_node.h:243
std::vector< ITEM * > ITEM_VECTOR
Definition pns_node.h:254
void GetUpdatedItems(ITEM_VECTOR &aRemoved, ITEM_VECTOR &aAdded)
Return the list of items removed and added in this branch with respect to the root branch.
const JOINT * FindJoint(const VECTOR2I &aPos, int aLayer, NET_HANDLE aNet) const
Search for a joint at a given position, layer and belonging to given net.
int Depth() const
Definition pns_node.h:304
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition pns_node.cpp:747
void Remove(ARC *aArc)
Remove an item from this branch.
Definition pns_node.cpp:991
const SEG & Seg() const
OPT_BOX2I ChangedArea(const VIA *aOther) const
Definition pns_via.cpp:291
Definition seg.h:38
VECTOR2I A
Definition seg.h:45
VECTOR2I B
Definition seg.h:46
int Length() const
Return the length (this).
Definition seg.h:339
OPT_VECTOR2I IntersectLines(const SEG &aSeg) const
Compute the intersection point of lines passing through ends of (this) and aSeg.
Definition seg.h:216
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
Definition seg.cpp:709
int Side(const VECTOR2I &aP) const
Determine on which side of directed line passing via segment ends point aP lies.
Definition seg.h:139
EDA_ANGLE GetCentralAngle() const
Get the "central angle" of the arc - this is the angle at the point of the "pie slice".
SEG GetChord() const
Definition shape_arc.h:243
bool IsClockwise() const
Definition shape_arc.h:319
int GetWidth() const override
Definition shape_arc.h:211
const SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError=DefaultAccuracyForPCB(), int *aActualError=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
const VECTOR2I & GetP1() const
Definition shape_arc.h:115
static int DefaultAccuracyForPCB()
Definition shape_arc.h:279
double GetRadius() const
const VECTOR2I & GetP0() const
Definition shape_arc.h:114
const VECTOR2I & GetCenter() const
SHAPE_TYPE Type() const
Return the type of the shape.
Definition shape.h:96
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
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 SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Find all intersection points between our line chain and the segment aSeg.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
int SegmentCount() const
Return the number of segments in this line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
std::vector< INTERSECTION > INTERSECTIONS
const VECTOR2I & GetPosition() const
Definition shape_rect.h:165
const VECTOR2I GetSize() const
Definition shape_rect.h:173
const SEG & GetSeg() const
int GetWidth() const override
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
const SHAPE_LINE_CHAIN & Vertices() const
Return the list of vertices defining this simple polygon.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
An abstract shape on 2D plane.
Definition shape.h:124
constexpr VECTOR2< T > Perpendicular() const
Compute the perpendicular vector.
Definition vector2d.h:310
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition vector2d.h:381
@ BLUE
Definition color4d.h:52
@ RED
Definition color4d.h:55
Push and Shove diff pair dimensions (gap) settings dialog.
void HullIntersection(const SHAPE_LINE_CHAIN &hull, const SHAPE_LINE_CHAIN &line, SHAPE_LINE_CHAIN::INTERSECTIONS &ips)
const wxString Format(const MINOPTMAX< int > x)
bool SplitAdjacentSegments(NODE *aNode, ITEM *aSeg, const VECTOR2I &aP)
Snaps the point aP to segment aSeg.
const SHAPE_LINE_CHAIN BuildHullForPrimitiveShape(const SHAPE *aShape, int aClearance, int aWalkaroundThickness)
const SHAPE_LINE_CHAIN OctagonalHull(const VECTOR2I &aP0, const VECTOR2I &aSize, int aClearance, int aChamfer)
Definition pns_utils.cpp:43
SHAPE_RECT ApproximateSegmentAsRect(const SHAPE_SEGMENT &aSeg)
bool SplitAdjacentArcs(NODE *aNode, ITEM *aArc, const VECTOR2I &aP)
Snaps the point aP to arc aArc.
const SHAPE_LINE_CHAIN ArcHull(const SHAPE_ARC &aArc, int aClearance, int aWalkaroundThickness)
Various utility functions.
Definition pns_utils.cpp:74
const SHAPE_LINE_CHAIN ConvexHull(const SHAPE_SIMPLE &aConvex, int aClearance)
Function ConvexHull()
void NodeStats(DEBUG_DECORATOR *dbg, wxString label, PNS::NODE *node)
const SHAPE_LINE_CHAIN SegmentHull(const SHAPE_SEGMENT &aSeg, int aClearance, int aWalkaroundThickness)
static bool IsSegment45Degree(const SEG &aS)
static void MoveDiagonal(SEG &aDiagonal, const SHAPE_LINE_CHAIN &aVertices, int aClearance)
OPT_BOX2I ChangedArea(const ITEM *aItemA, const ITEM *aItemB)
int sgn(T val)
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition pns_item.h:344
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:411
#define PNS_DBG(dbg, method,...)
#define PNS_DBGN(dbg, method)
@ SH_RECT
axis-aligned rectangle
Definition shape.h:43
@ SH_CIRCLE
circle
Definition shape.h:46
@ SH_SIMPLE
simple polygon
Definition shape.h:47
@ SH_ELLIPSE
ellipse or elliptical arc
Definition shape.h:53
@ SH_SEGMENT
line segment
Definition shape.h:44
@ SH_ARC
circular arc
Definition shape.h:50
static wxString SHAPE_TYPE_asString(SHAPE_TYPE a)
Definition shape.h:56
A(const A &)=default
Represent an intersection between two line segments.
bool valid
Auxiliary flag to avoid copying intersection info to intersection refining code, used by the refining...
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
int delta
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683