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>
31#include <math/box2.h>
32
33#include <cmath>
34
35namespace PNS {
36
37const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0, const VECTOR2I& aSize,
38 int aClearance, int aChamfer )
39{
41
42 s.SetClosed( true );
43
44 s.Append( aP0.x - aClearance, aP0.y - aClearance + aChamfer );
45
46 if( aChamfer )
47 s.Append( aP0.x - aClearance + aChamfer, aP0.y - aClearance );
48
49 s.Append( aP0.x + aSize.x + aClearance - aChamfer, aP0.y - aClearance );
50
51 if( aChamfer )
52 s.Append( aP0.x + aSize.x + aClearance, aP0.y - aClearance + aChamfer );
53
54 s.Append( aP0.x + aSize.x + aClearance, aP0.y + aSize.y + aClearance - aChamfer );
55
56 if( aChamfer )
57 s.Append( aP0.x + aSize.x + aClearance - aChamfer, aP0.y + aSize.y + aClearance );
58
59 s.Append( aP0.x - aClearance + aChamfer, aP0.y + aSize.y + aClearance );
60
61 if( aChamfer )
62 s.Append( aP0.x - aClearance, aP0.y + aSize.y + aClearance - aChamfer );
63
64 return s;
65}
66
67
68const SHAPE_LINE_CHAIN ArcHull( const SHAPE_ARC& aArc, int aClearance, int aWalkaroundThickness )
69{
70 int cl = aClearance + ( aWalkaroundThickness + 1 ) / 2;
71
72 // If we can't route through the arc, we might as well treat it as a circle
73 if( aArc.GetCentralAngle().AsDegrees() > 180.0 && aArc.GetChord().Length() < cl )
74 {
75 int r = aArc.GetRadius();
76 return OctagonalHull( aArc.GetCenter() - VECTOR2I( r, r ),
77 VECTOR2I( 2 * r, 2 * r ),
78 cl,
79 2.0 * ( 1.0 - M_SQRT1_2 ) * ( r + cl ) );
80 }
81
82 int d = aArc.GetWidth() / 2 + cl + SHAPE_ARC::DefaultAccuracyForPCB();
83 int x = (int) ( 2.0 / ( 1.0 + M_SQRT2 ) * d ) / 2;
84
85 auto line = aArc.ConvertToPolyline( ARC_LOW_DEF );
86
88 s.SetClosed( true );
89 std::vector<VECTOR2I> reverse_line;
90
91 auto seg = line.Segment( 0 );
92 VECTOR2I dir = seg.B - seg.A;
93 VECTOR2I p0 = -dir.Perpendicular().Resize( d );
94 VECTOR2I ds = -dir.Perpendicular().Resize( x );
95 VECTOR2I pd = dir.Resize( x );
96 VECTOR2I dp = dir.Resize( d );
97
98 // Append the first curve
99 s.Append( seg.A + p0 - pd );
100 s.Append( seg.A - dp + ds );
101 s.Append( seg.A - dp - ds );
102 s.Append( seg.A - p0 - pd );
103
104 for( int i = 1; i < line.SegmentCount(); i++ )
105 {
106 // calculate a vertex normal (average of segment normals)
107 auto pp =
108 ( line.CSegment( i - 1 ).B - line.CSegment( i - 1 ).A ).Perpendicular().Resize( d );
109 auto pp2 = ( line.CSegment( i ).B - line.CSegment( i ).A ).Perpendicular().Resize( d );
110
111 auto sa_out = line.CSegment( i - 1 ), sa_in = line.CSegment( i - 1 );
112 auto sb_out = line.CSegment( i ), sb_in = line.CSegment( i );
113
114 sa_out.A += pp;
115 sa_out.B += pp;
116 sb_out.A += pp2;
117 sb_out.B += pp2;
118
119 sa_in.A -= pp;
120 sa_in.B -= pp;
121 sb_in.A -= pp2;
122 sb_in.B -= pp2;
123
124 auto ip_out = sa_out.IntersectLines( sb_out );
125 auto ip_in = sa_in.IntersectLines( sb_in );
126
127 seg = line.CSegment( i );
128 auto lead = ( pp + pp2 ) / 2;
129
130 s.Append( *ip_out );
131 reverse_line.push_back( *ip_in );
132 }
133
134 seg = line.CSegment( -1 );
135 dir = seg.B - seg.A;
136 p0 = -dir.Perpendicular().Resize( d );
137 ds = -dir.Perpendicular().Resize( x );
138 pd = dir.Resize( x );
139 dp = dir.Resize( d );
140 s.Append( seg.B - p0 + pd );
141 s.Append( seg.B + dp - ds );
142 s.Append( seg.B + dp + ds );
143 s.Append( seg.B + p0 + pd );
144
145 for( int i = reverse_line.size() - 1; i >= 0; i-- )
146 s.Append( reverse_line[i] );
147
148 // make sure the hull outline is always clockwise
149 if( s.CSegment( 0 ).Side( line.Segment( 0 ).A ) < 0 )
150 return s.Reverse();
151 else
152 return s;
153}
154
155
156static bool IsSegment45Degree( const SEG& aS )
157{
158 VECTOR2I dir( aS.B - aS.A );
159
160 if( std::abs( dir.x ) <= 1 )
161 return true;
162
163 if( std::abs( dir.y ) <= 1 )
164 return true;
165
166 int delta = std::abs(dir.x) - std::abs(dir.y);
167
168 if( delta >= -1 && delta <= 1)
169 return true;
170
171 return false;
172}
173
174
175template <typename T> int sgn(T val) {
176 return (T(0) < val) - (val < T(0));
177}
178
179
180const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, int aClearance,
181 int aWalkaroundThickness )
182{
183 const int kinkThreshold = aClearance / 10;
184
185 int cl = aClearance + aWalkaroundThickness / 2;
186 double d = (double)aSeg.GetWidth() / 2.0 + cl;
187 double x = 2.0 / ( 1.0 + M_SQRT2 ) * d;
188 int dr = KiROUND( d );
189 int xr = KiROUND( x );
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 default:
523 {
524 wxFAIL_MSG( wxString::Format( wxT( "Unsupported hull shape: %d (%s)." ),
525 aShape->Type(),
526 SHAPE_TYPE_asString( aShape->Type() ) ) );
527 break;
528 }
529 }
530
531 return SHAPE_LINE_CHAIN();
532}
533
534
535void NodeStats( DEBUG_DECORATOR* dbg, wxString label, PNS::NODE *node )
536{
537 NODE::ITEM_VECTOR added, removed;
538 node->GetUpdatedItems( removed, added );
539
540 PNS_DBG( dbg, BeginGroup, wxString::Format( "node:%s this=%p depth=%d added=%d removed=%d",
541 label, node, node->Depth(), (int)added.size(), (int) removed.size() ), 0 );
542
543 for( auto& item : added )
544 PNS_DBG( dbg, AddItem, item, BLUE, 10000, wxT("added-item") );
545 for( auto& item : removed )
546 PNS_DBG( dbg, AddItem, item, RED, 10000, wxString::Format("removed-item") );
547
548 PNS_DBGN( dbg, EndGroup );
549}
550
551
552}
constexpr int ARC_LOW_DEF
Definition: base_units.h:119
std::optional< BOX2I > OPT_BOX2I
Definition: box2.h:926
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
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:113
Base class for PNS router board items.
Definition: pns_item.h:98
bool OfKind(int aKindMask) const
Definition: pns_item.h:179
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
Definition: pns_line.cpp:1215
Keep the router "world" - i.e.
Definition: pns_node.h:231
std::vector< ITEM * > ITEM_VECTOR
Definition: pns_node.h:242
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.
Definition: pns_node.cpp:1446
int Depth() const
Definition: pns_node.h:281
OPT_BOX2I ChangedArea(const VIA *aOther) const
Definition: pns_via.cpp:262
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:333
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
Definition: shape_arc.cpp:864
SEG GetChord() const
Definition: shape_arc.h:242
int GetWidth() const
Definition: shape_arc.h:210
const SHAPE_LINE_CHAIN ConvertToPolyline(double aAccuracy=DefaultAccuracyForPCB(), double *aEffectiveAccuracy=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
Definition: shape_arc.cpp:886
double GetRadius() const
Definition: shape_arc.cpp:880
static double DefaultAccuracyForPCB()
Definition: shape_arc.h:276
const VECTOR2I & GetCenter() const
Definition: shape_arc.cpp:849
SHAPE_TYPE Type() const
Return the type of the shape.
Definition: shape.h:98
int GetRadius() const
Definition: shape_circle.h:118
const VECTOR2I GetCenter() const
Definition: shape_circle.h:123
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:160
const VECTOR2I GetSize() const
Definition: shape_rect.h:168
const SEG & GetSeg() const
int GetWidth() const
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
Definition: shape_simple.h:42
const SHAPE_LINE_CHAIN & Vertices() const
Return the list of vertices defining this simple polygon.
Definition: shape_simple.h:124
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
Definition: shape_simple.h:78
An abstract shape on 2D plane.
Definition: shape.h:126
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)
Definition: pns_utils.cpp:395
const SHAPE_LINE_CHAIN BuildHullForPrimitiveShape(const SHAPE *aShape, int aClearance, int aWalkaroundThickness)
Definition: pns_utils.cpp:478
const SHAPE_LINE_CHAIN OctagonalHull(const VECTOR2I &aP0, const VECTOR2I &aSize, int aClearance, int aChamfer)
Definition: pns_utils.cpp:37
SHAPE_RECT ApproximateSegmentAsRect(const SHAPE_SEGMENT &aSeg)
Definition: pns_utils.cpp:356
const SHAPE_LINE_CHAIN ArcHull(const SHAPE_ARC &aArc, int aClearance, int aWalkaroundThickness)
Various utility functions.
Definition: pns_utils.cpp:68
const SHAPE_LINE_CHAIN ConvexHull(const SHAPE_SIMPLE &aConvex, int aClearance)
Function ConvexHull()
Definition: pns_utils.cpp:300
void NodeStats(DEBUG_DECORATOR *dbg, wxString label, PNS::NODE *node)
Definition: pns_utils.cpp:535
const SHAPE_LINE_CHAIN SegmentHull(const SHAPE_SEGMENT &aSeg, int aClearance, int aWalkaroundThickness)
Definition: pns_utils.cpp:180
static bool IsSegment45Degree(const SEG &aS)
Definition: pns_utils.cpp:156
static void MoveDiagonal(SEG &aDiagonal, const SHAPE_LINE_CHAIN &aVertices, int aClearance)
Definition: pns_utils.cpp:289
OPT_BOX2I ChangedArea(const ITEM *aItemA, const ITEM *aItemB)
Definition: pns_utils.cpp:369
int sgn(T val)
Definition: pns_utils.cpp:175
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:390
#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_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:59
Represent an intersection between two line segments.
bool valid
Auxiliary flag to avoid copying intersection info to intersection refining code, used by the refining...
constexpr int delta
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695