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 along
19 * with this program. If not, see <http://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_node.h"
28
29#include <geometry/shape_arc.h>
34#include <math/box2.h>
35
36#include <cmath>
37
38namespace PNS {
39
40const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0, const VECTOR2I& aSize,
41 int aClearance, int aChamfer )
42{
44
45 s.SetClosed( true );
46
47 s.Append( aP0.x - aClearance, aP0.y - aClearance + aChamfer );
48
49 if( aChamfer )
50 s.Append( aP0.x - aClearance + aChamfer, aP0.y - aClearance );
51
52 s.Append( aP0.x + aSize.x + aClearance - aChamfer, aP0.y - aClearance );
53
54 if( aChamfer )
55 s.Append( aP0.x + aSize.x + aClearance, aP0.y - aClearance + aChamfer );
56
57 s.Append( aP0.x + aSize.x + aClearance, aP0.y + aSize.y + aClearance - aChamfer );
58
59 if( aChamfer )
60 s.Append( aP0.x + aSize.x + aClearance - aChamfer, aP0.y + aSize.y + aClearance );
61
62 s.Append( aP0.x - aClearance + aChamfer, aP0.y + aSize.y + aClearance );
63
64 if( aChamfer )
65 s.Append( aP0.x - aClearance, aP0.y + aSize.y + aClearance - aChamfer );
66
67 return s;
68}
69
70
71const SHAPE_LINE_CHAIN ArcHull( const SHAPE_ARC& aArc, int aClearance, int aWalkaroundThickness )
72{
73 int cl = aClearance + ( aWalkaroundThickness + 1 ) / 2;
74
75 // If we can't route through the arc, we might as well treat it as a circle
76 if( aArc.GetCentralAngle().AsDegrees() > 180.0 && aArc.GetChord().Length() < cl )
77 {
78 int r = aArc.GetRadius();
79 return OctagonalHull( aArc.GetCenter() - VECTOR2I( r, r ),
80 VECTOR2I( 2 * r, 2 * r ),
81 cl,
82 2.0 * ( 1.0 - M_SQRT1_2 ) * ( r + cl ) );
83 }
84
85 int d = aArc.GetWidth() / 2 + cl + SHAPE_ARC::DefaultAccuracyForPCB();
86 int x = (int) ( 2.0 / ( 1.0 + M_SQRT2 ) * d ) / 2;
87
88 auto line = aArc.ConvertToPolyline( ARC_LOW_DEF );
89
91 s.SetClosed( true );
92 std::vector<VECTOR2I> reverse_line;
93
94 auto seg = line.Segment( 0 );
95 VECTOR2I dir = seg.B - seg.A;
96 VECTOR2I p0 = -dir.Perpendicular().Resize( d );
97 VECTOR2I ds = -dir.Perpendicular().Resize( x );
98 VECTOR2I pd = dir.Resize( x );
99 VECTOR2I dp = dir.Resize( d );
100
101 // Append the first curve
102 s.Append( seg.A + p0 - pd );
103 s.Append( seg.A - dp + ds );
104 s.Append( seg.A - dp - ds );
105 s.Append( seg.A - p0 - pd );
106
107 for( int i = 1; i < line.SegmentCount(); i++ )
108 {
109 // calculate a vertex normal (average of segment normals)
110 auto pp =
111 ( line.CSegment( i - 1 ).B - line.CSegment( i - 1 ).A ).Perpendicular().Resize( d );
112 auto pp2 = ( line.CSegment( i ).B - line.CSegment( i ).A ).Perpendicular().Resize( d );
113
114 auto sa_out = line.CSegment( i - 1 ), sa_in = line.CSegment( i - 1 );
115 auto sb_out = line.CSegment( i ), sb_in = line.CSegment( i );
116
117 sa_out.A += pp;
118 sa_out.B += pp;
119 sb_out.A += pp2;
120 sb_out.B += pp2;
121
122 sa_in.A -= pp;
123 sa_in.B -= pp;
124 sb_in.A -= pp2;
125 sb_in.B -= pp2;
126
127 auto ip_out = sa_out.IntersectLines( sb_out );
128 auto ip_in = sa_in.IntersectLines( sb_in );
129
130 seg = line.CSegment( i );
131 s.Append( *ip_out );
132 reverse_line.push_back( *ip_in );
133 }
134
135 seg = line.CSegment( -1 );
136 dir = seg.B - seg.A;
137 p0 = -dir.Perpendicular().Resize( d );
138 ds = -dir.Perpendicular().Resize( x );
139 pd = dir.Resize( x );
140 dp = dir.Resize( d );
141 s.Append( seg.B - p0 + pd );
142 s.Append( seg.B + dp - ds );
143 s.Append( seg.B + dp + ds );
144 s.Append( seg.B + p0 + pd );
145
146 for( int i = reverse_line.size() - 1; i >= 0; i-- )
147 s.Append( reverse_line[i] );
148
149 // make sure the hull outline is always clockwise
150 if( s.CSegment( 0 ).Side( line.Segment( 0 ).A ) < 0 )
151 return s.Reverse();
152 else
153 return s;
154}
155
156
157static bool IsSegment45Degree( const SEG& aS )
158{
159 VECTOR2I dir( aS.B - aS.A );
160
161 if( std::abs( dir.x ) <= 1 )
162 return true;
163
164 if( std::abs( dir.y ) <= 1 )
165 return true;
166
167 int delta = std::abs(dir.x) - std::abs(dir.y);
168
169 if( delta >= -1 && delta <= 1)
170 return true;
171
172 return false;
173}
174
175
176template <typename T> int sgn(T val) {
177 return (T(0) < val) - (val < T(0));
178}
179
180
181const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, int aClearance,
182 int aWalkaroundThickness )
183{
184 const int kinkThreshold = aClearance / 10;
185
186 int cl = aClearance + aWalkaroundThickness / 2;
187 double d = (double)aSeg.GetWidth() / 2.0 + cl;
188 double x = 2.0 / ( 1.0 + M_SQRT2 ) * d;
189 int dr = KiROUND( d );
190 int xr2 = KiROUND( x / 2.0 );
191
192 const VECTOR2I a = aSeg.GetSeg().A;
193 VECTOR2I b = aSeg.GetSeg().B;
194 int len = aSeg.GetSeg().Length();
195 int w = b.x - a.x;
196 int h = b.y - a.y;
197
198 /*
199 auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
200
201 if( len < kinkThreshold )
202 {
203 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 ) );
204 }
205 */
206
207 if( a != b )
208 {
209 if ( !IsSegment45Degree( aSeg.GetSeg() ) )
210 {
211 if ( len <= kinkThreshold && len > 0 )
212 {
213 int ll = std::max( std::abs( w ), std::abs( h ) );
214
215 b = a + VECTOR2I( sgn( w ) * ll, sgn( h ) * ll );
216 }
217 }
218 else
219 {
220 if( len <= kinkThreshold )
221 {
222 int delta45 = std::abs( std::abs(w) - std::abs(h) );
223 if( std::abs(w) <= 1 ) // almost vertical
224 {
225 w = 0;
226 cl ++;
227 }
228 else if ( std::abs(h) <= 1 ) // almost horizontal
229 {
230 h = 0;
231 cl ++;
232 }
233 else if ( delta45 <= 2 ) // almost 45 degree
234 {
235 int newW = sgn( w ) * std::max( std::abs(w), std::abs( h ) );
236 int newH = sgn( h ) * std::max( std::abs(w), std::abs( h ) );
237 w = newW;
238 h = newH;
239 cl += 2;
240 //PNS_DBG( dbg, AddShape, &aSeg, CYAN, 10000, wxString::Format( "almostkinky45 45 %d l %d dx %d dy %d", !!IsSegment45Degree( aSeg.GetSeg() ), len, w, h ) );
241
242 }
243
244 b.x = a.x + w;
245 b.y = a.y + h;
246 }
247 }
248 }
249
250 if( a == b )
251 {
252 int xx2 = KiROUND( 2.0 * ( 1.0 - M_SQRT1_2 ) * d );
253
254 auto ohull = OctagonalHull( a - VECTOR2I( aSeg.GetWidth() / 2, aSeg.GetWidth() / 2 ),
255 VECTOR2I( aSeg.GetWidth(), aSeg.GetWidth() ),
256 cl,
257 xx2 );
258
259 return ohull;
260 }
261
262 VECTOR2I dir = b - a;
263 VECTOR2I p0 = dir.Perpendicular().Resize( dr );
264 VECTOR2I ds = dir.Perpendicular().Resize( xr2 );
265 VECTOR2I pd = dir.Resize( xr2 );
266 VECTOR2I dp = dir.Resize( dr );
267
269
270 s.SetClosed( true );
271
272 s.Append( b + p0 + pd );
273 s.Append( b + dp + ds );
274 s.Append( b + dp - ds );
275 s.Append( b - p0 + pd );
276 s.Append( a - p0 - pd );
277 s.Append( a - dp - ds );
278 s.Append( a - dp + ds );
279 s.Append( a + p0 - pd );
280
281 // make sure the hull outline is always clockwise
282 if( s.CSegment( 0 ).Side( a ) < 0 )
283 return s.Reverse();
284 else
285 return s;
286}
287
288
289static void MoveDiagonal( SEG& aDiagonal, const SHAPE_LINE_CHAIN& aVertices, int aClearance )
290{
291 int dist;
292
293 aVertices.NearestPoint( aDiagonal, dist );
294 VECTOR2I moveBy = ( aDiagonal.A - aDiagonal.B ).Perpendicular().Resize( dist - aClearance );
295 aDiagonal.A += moveBy;
296 aDiagonal.B += moveBy;
297}
298
299
300const SHAPE_LINE_CHAIN ConvexHull( const SHAPE_SIMPLE& aConvex, int aClearance )
301{
302 // this defines the horizontal and vertical lines in the hull octagon
303 BOX2I box = aConvex.BBox( aClearance );
304 box.Normalize();
305
306 SEG topline = SEG( VECTOR2I( box.GetX(), box.GetY() + box.GetHeight() ),
307 VECTOR2I( box.GetX() + box.GetWidth(), box.GetY() + box.GetHeight() ) );
308 SEG rightline = SEG( VECTOR2I( box.GetX() + box.GetWidth(), box.GetY() + box.GetHeight() ),
309 VECTOR2I( box.GetX() + box.GetWidth(), box.GetY() ) );
310 SEG bottomline = SEG( VECTOR2I( box.GetX() + box.GetWidth(), box.GetY() ),
311 box.GetOrigin() );
312 SEG leftline = SEG( box.GetOrigin(), VECTOR2I( box.GetX(), box.GetY() + box.GetHeight() ) );
313
314 const SHAPE_LINE_CHAIN& vertices = aConvex.Vertices();
315
316 // top right diagonal
317 VECTOR2I corner = box.GetOrigin() + box.GetSize();
318 SEG toprightline = SEG( corner,
319 corner + VECTOR2I( box.GetHeight(), -box.GetHeight() ) );
320 MoveDiagonal( toprightline, vertices, aClearance );
321
322 // bottom right diagonal
323 corner = box.GetOrigin() + VECTOR2I( box.GetWidth(), 0 );
324 SEG bottomrightline = SEG( corner + VECTOR2I( box.GetHeight(), box.GetHeight() ),
325 corner );
326 MoveDiagonal( bottomrightline, vertices, aClearance );
327
328 // bottom left diagonal
329 corner = box.GetOrigin();
330 SEG bottomleftline = SEG( corner,
331 corner + VECTOR2I( -box.GetHeight(), box.GetHeight() ) );
332 MoveDiagonal( bottomleftline, vertices, aClearance );
333
334 // top left diagonal
335 corner = box.GetOrigin() + VECTOR2I( 0, box.GetHeight() );
336 SEG topleftline = SEG( corner + VECTOR2I( -box.GetHeight(), -box.GetHeight() ),
337 corner );
338 MoveDiagonal( topleftline, vertices, aClearance );
339
340 SHAPE_LINE_CHAIN octagon;
341 octagon.SetClosed( true );
342
343 octagon.Append( *leftline.IntersectLines( bottomleftline ) );
344 octagon.Append( *bottomline.IntersectLines( bottomleftline ) );
345 octagon.Append( *bottomline.IntersectLines( bottomrightline ) );
346 octagon.Append( *rightline.IntersectLines( bottomrightline ) );
347 octagon.Append( *rightline.IntersectLines( toprightline ) );
348 octagon.Append( *topline.IntersectLines( toprightline ) );
349 octagon.Append( *topline.IntersectLines( topleftline ) );
350 octagon.Append( *leftline.IntersectLines( topleftline ) );
351
352 return octagon;
353}
354
355
357{
358 SHAPE_RECT r;
359
360 VECTOR2I delta( aSeg.GetWidth() / 2, aSeg.GetWidth() / 2 );
361 VECTOR2I p0( aSeg.GetSeg().A - delta );
362 VECTOR2I p1( aSeg.GetSeg().B + delta );
363
364 return SHAPE_RECT( std::min( p0.x, p1.x ), std::min( p0.y, p1.y ),
365 std::abs( p1.x - p0.x ), std::abs( p1.y - p0.y ) );
366}
367
368
369OPT_BOX2I ChangedArea( const ITEM* aItemA, const ITEM* aItemB )
370{
371 if( aItemA->OfKind( ITEM::VIA_T ) && aItemB->OfKind( ITEM::VIA_T ) )
372 {
373 const VIA* va = static_cast<const VIA*>( aItemA );
374 const VIA* vb = static_cast<const VIA*>( aItemB );
375
376 return va->ChangedArea( vb );
377 }
378 else if( aItemA->OfKind( ITEM::LINE_T ) && aItemB->OfKind( ITEM::LINE_T ) )
379 {
380 const LINE* la = static_cast<const LINE*> ( aItemA );
381 const LINE* lb = static_cast<const LINE*> ( aItemB );
382
383 return la->ChangedArea( lb );
384 }
385
386 return OPT_BOX2I();
387}
388
389OPT_BOX2I ChangedArea( const LINE& aLineA, const LINE& aLineB )
390{
391 return aLineA.ChangedArea( &aLineB );
392}
393
394
397{
399
400 if( line.PointCount() < 2 )
401 return;
402
403 hull.Intersect( line, ips_raw );
404
405 for( auto& p : ips_raw )
406 {
408
409 SEG d1[2];
410 VECTOR2I d2[2];
411 int d1_idx = 0, d2_idx = 0;
412
413 ipp = p;
414 ipp.valid = false;
415
416 if( !p.is_corner_our && !p.is_corner_their )
417 {
418 ipp.valid = true;
419 ips.push_back( ipp );
420 continue;
421 }
422
423 if( p.index_our >= hull.SegmentCount() )
424 p.index_our -= hull.SegmentCount();
425
426 if( p.is_corner_our )
427 {
428 d1[0] = hull.CSegment( p.index_our );
429 d1[1] = hull.CSegment( p.index_our - 1 );
430 d1_idx = 2;
431 }
432 else
433 {
434 d1[0] = hull.CSegment( p.index_our );
435 d1_idx = 1;
436 }
437
438 if( p.is_corner_their )
439 {
440 if( p.index_their > 0 )
441 {
442 d2[d2_idx++] = line.CSegment( p.index_their - 1 ).A;
443 }
444 if( p.index_their < line.PointCount() - 1 )
445 {
446 d2[d2_idx++] = line.CSegment( p.index_their ).B;
447 }
448 }
449 else
450 {
451 d2[d2_idx++] = line.CSegment( p.index_their ).A;
452 d2[d2_idx++] = line.CSegment( p.index_their ).B;
453 }
454
455 for( int i = 0; i < d1_idx; i++ )
456 {
457 for( int j = 0; j < d2_idx; j++ )
458 {
459 if( d1[i].Side( d2[j] ) > 0 )
460 {
461 ipp.valid = true;
462 }
463 }
464 }
465
466#ifdef TOM_EXTRA_DEBUG
467 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);
468 printf("d1 %d d2 %d\n", d1_idx, d2_idx );
469#endif
470 if( ipp.valid )
471 {
472 ips.push_back( ipp );
473 }
474 }
475}
476
477
478const SHAPE_LINE_CHAIN BuildHullForPrimitiveShape( const SHAPE* aShape, int aClearance,
479 int aWalkaroundThickness )
480{
481 int cl = aClearance + ( aWalkaroundThickness + 1 )/ 2;
482
483 switch( aShape->Type() )
484 {
485 case SH_RECT:
486 {
487 const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>( aShape );
488 return OctagonalHull( rect->GetPosition(),
489 rect->GetSize(),
490 cl,
491 0 );
492 }
493
494 case SH_CIRCLE:
495 {
496 const SHAPE_CIRCLE* circle = static_cast<const SHAPE_CIRCLE*>( aShape );
497 int r = circle->GetRadius();
498 return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ),
499 VECTOR2I( 2 * r, 2 * r ),
500 cl,
501 2.0 * ( 1.0 - M_SQRT1_2 ) * ( r + cl ) );
502 }
503
504 case SH_SEGMENT:
505 {
506 const SHAPE_SEGMENT* seg = static_cast<const SHAPE_SEGMENT*>( aShape );
507 return SegmentHull( *seg, aClearance, aWalkaroundThickness );
508 }
509
510 case SH_ARC:
511 {
512 const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( aShape );
513 return ArcHull( *arc, aClearance, aWalkaroundThickness );
514 }
515
516 case SH_SIMPLE:
517 {
518 const SHAPE_SIMPLE* convex = static_cast<const SHAPE_SIMPLE*>( aShape );
519
520 return ConvexHull( *convex, cl );
521 }
522
523 case SH_ELLIPSE:
524 {
525 const SHAPE_ELLIPSE* ellipse = static_cast<const SHAPE_ELLIPSE*>( aShape );
526 const BOX2I bbox = ellipse->BBox();
527
528 return OctagonalHull( bbox.GetPosition(), bbox.GetSize(), cl, 0 );
529 }
530
531 default:
532 {
533 wxFAIL_MSG( wxString::Format( wxT( "Unsupported hull shape: %d (%s)." ),
534 aShape->Type(),
535 SHAPE_TYPE_asString( aShape->Type() ) ) );
536 break;
537 }
538 }
539
540 return SHAPE_LINE_CHAIN();
541}
542
543
544void NodeStats( DEBUG_DECORATOR* dbg, wxString label, PNS::NODE *node )
545{
546 NODE::ITEM_VECTOR added, removed;
547 node->GetUpdatedItems( removed, added );
548
549 PNS_DBG( dbg, BeginGroup, wxString::Format( "node:%s this=%p depth=%d added=%d removed=%d",
550 label, node, node->Depth(), (int)added.size(), (int) removed.size() ), 0 );
551
552 for( auto& item : added )
553 PNS_DBG( dbg, AddItem, item, BLUE, 10000, wxT("added-item") );
554 for( auto& item : removed )
555 PNS_DBG( dbg, AddItem, item, RED, 10000, wxString::Format("removed-item") );
556
557 PNS_DBGN( dbg, EndGroup );
558}
559
560
561}
constexpr int ARC_LOW_DEF
Definition base_units.h:140
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
std::optional< BOX2I > OPT_BOX2I
Definition box2.h:926
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
constexpr const Vec & GetPosition() const
Definition box2.h:211
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:146
constexpr coord_type GetY() const
Definition box2.h:208
constexpr size_type GetWidth() const
Definition box2.h:214
constexpr coord_type GetX() const
Definition box2.h:207
constexpr size_type GetHeight() const
Definition box2.h:215
constexpr const Vec & GetOrigin() const
Definition box2.h:210
constexpr const SizeVec & GetSize() const
Definition box2.h:206
double AsDegrees() const
Definition eda_angle.h:116
Base class for PNS router board items.
Definition pns_item.h:98
bool OfKind(int aKindMask) const
Definition pns_item.h:181
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:240
std::vector< ITEM * > ITEM_VECTOR
Definition pns_node.h:251
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.
int Depth() const
Definition pns_node.h:301
OPT_BOX2I ChangedArea(const VIA *aOther) const
Definition pns_via.cpp:291
Definition seg.h:42
VECTOR2I A
Definition seg.h:49
VECTOR2I B
Definition seg.h:50
int Length() const
Return the length (this).
Definition seg.h:343
OPT_VECTOR2I IntersectLines(const SEG &aSeg) const
Compute the intersection point of lines passing through ends of (this) and aSeg.
Definition seg.h:220
int Side(const VECTOR2I &aP) const
Determine on which side of directed line passing via segment ends point aP lies.
Definition seg.h:143
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:247
int GetWidth() const override
Definition shape_arc.h:215
const SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError=DefaultAccuracyForPCB(), int *aActualError=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
static int DefaultAccuracyForPCB()
Definition shape_arc.h:283
double GetRadius() const
const VECTOR2I & GetCenter() const
SHAPE_TYPE Type() const
Return the type of the shape.
Definition shape.h:100
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:169
const VECTOR2I GetSize() const
Definition shape_rect.h:177
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:128
constexpr VECTOR2< T > Perpendicular() const
Compute the perpendicular vector.
Definition vector2d.h:314
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition vector2d.h:385
@ BLUE
Definition color4d.h:56
@ RED
Definition color4d.h:59
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 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:40
SHAPE_RECT ApproximateSegmentAsRect(const SHAPE_SEGMENT &aSeg)
const SHAPE_LINE_CHAIN ArcHull(const SHAPE_ARC &aArc, int aClearance, int aWalkaroundThickness)
Various utility functions.
Definition pns_utils.cpp:71
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)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
#define PNS_DBG(dbg, method,...)
#define PNS_DBGN(dbg, method)
@ SH_RECT
axis-aligned rectangle
Definition shape.h:47
@ SH_CIRCLE
circle
Definition shape.h:50
@ SH_SIMPLE
simple polygon
Definition shape.h:51
@ SH_ELLIPSE
ellipse or elliptical arc
Definition shape.h:57
@ SH_SEGMENT
line segment
Definition shape.h:48
@ SH_ARC
circular arc
Definition shape.h:54
static wxString SHAPE_TYPE_asString(SHAPE_TYPE a)
Definition shape.h:60
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:687