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 s.Append( *ip_out );
129 reverse_line.push_back( *ip_in );
130 }
131
132 seg = line.CSegment( -1 );
133 dir = seg.B - seg.A;
134 p0 = -dir.Perpendicular().Resize( d );
135 ds = -dir.Perpendicular().Resize( x );
136 pd = dir.Resize( x );
137 dp = dir.Resize( d );
138 s.Append( seg.B - p0 + pd );
139 s.Append( seg.B + dp - ds );
140 s.Append( seg.B + dp + ds );
141 s.Append( seg.B + p0 + pd );
142
143 for( int i = reverse_line.size() - 1; i >= 0; i-- )
144 s.Append( reverse_line[i] );
145
146 // make sure the hull outline is always clockwise
147 if( s.CSegment( 0 ).Side( line.Segment( 0 ).A ) < 0 )
148 return s.Reverse();
149 else
150 return s;
151}
152
153
154static bool IsSegment45Degree( const SEG& aS )
155{
156 VECTOR2I dir( aS.B - aS.A );
157
158 if( std::abs( dir.x ) <= 1 )
159 return true;
160
161 if( std::abs( dir.y ) <= 1 )
162 return true;
163
164 int delta = std::abs(dir.x) - std::abs(dir.y);
165
166 if( delta >= -1 && delta <= 1)
167 return true;
168
169 return false;
170}
171
172
173template <typename T> int sgn(T val) {
174 return (T(0) < val) - (val < T(0));
175}
176
177
178const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, int aClearance,
179 int aWalkaroundThickness )
180{
181 const int kinkThreshold = aClearance / 10;
182
183 int cl = aClearance + aWalkaroundThickness / 2;
184 double d = (double)aSeg.GetWidth() / 2.0 + cl;
185 double x = 2.0 / ( 1.0 + M_SQRT2 ) * d;
186 int dr = KiROUND( d );
187 int xr2 = KiROUND( x / 2.0 );
188
189 const VECTOR2I a = aSeg.GetSeg().A;
190 VECTOR2I b = aSeg.GetSeg().B;
191 int len = aSeg.GetSeg().Length();
192 int w = b.x - a.x;
193 int h = b.y - a.y;
194
195 /*
196 auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
197
198 if( len < kinkThreshold )
199 {
200 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 ) );
201 }
202 */
203
204 if( a != b )
205 {
206 if ( !IsSegment45Degree( aSeg.GetSeg() ) )
207 {
208 if ( len <= kinkThreshold && len > 0 )
209 {
210 int ll = std::max( std::abs( w ), std::abs( h ) );
211
212 b = a + VECTOR2I( sgn( w ) * ll, sgn( h ) * ll );
213 }
214 }
215 else
216 {
217 if( len <= kinkThreshold )
218 {
219 int delta45 = std::abs( std::abs(w) - std::abs(h) );
220 if( std::abs(w) <= 1 ) // almost vertical
221 {
222 w = 0;
223 cl ++;
224 }
225 else if ( std::abs(h) <= 1 ) // almost horizontal
226 {
227 h = 0;
228 cl ++;
229 }
230 else if ( delta45 <= 2 ) // almost 45 degree
231 {
232 int newW = sgn( w ) * std::max( std::abs(w), std::abs( h ) );
233 int newH = sgn( h ) * std::max( std::abs(w), std::abs( h ) );
234 w = newW;
235 h = newH;
236 cl += 2;
237 //PNS_DBG( dbg, AddShape, &aSeg, CYAN, 10000, wxString::Format( "almostkinky45 45 %d l %d dx %d dy %d", !!IsSegment45Degree( aSeg.GetSeg() ), len, w, h ) );
238
239 }
240
241 b.x = a.x + w;
242 b.y = a.y + h;
243 }
244 }
245 }
246
247 if( a == b )
248 {
249 int xx2 = KiROUND( 2.0 * ( 1.0 - M_SQRT1_2 ) * d );
250
251 auto ohull = OctagonalHull( a - VECTOR2I( aSeg.GetWidth() / 2, aSeg.GetWidth() / 2 ),
252 VECTOR2I( aSeg.GetWidth(), aSeg.GetWidth() ),
253 cl,
254 xx2 );
255
256 return ohull;
257 }
258
259 VECTOR2I dir = b - a;
260 VECTOR2I p0 = dir.Perpendicular().Resize( dr );
261 VECTOR2I ds = dir.Perpendicular().Resize( xr2 );
262 VECTOR2I pd = dir.Resize( xr2 );
263 VECTOR2I dp = dir.Resize( dr );
264
266
267 s.SetClosed( true );
268
269 s.Append( b + p0 + pd );
270 s.Append( b + dp + ds );
271 s.Append( b + dp - ds );
272 s.Append( b - p0 + pd );
273 s.Append( a - p0 - pd );
274 s.Append( a - dp - ds );
275 s.Append( a - dp + ds );
276 s.Append( a + p0 - pd );
277
278 // make sure the hull outline is always clockwise
279 if( s.CSegment( 0 ).Side( a ) < 0 )
280 return s.Reverse();
281 else
282 return s;
283}
284
285
286static void MoveDiagonal( SEG& aDiagonal, const SHAPE_LINE_CHAIN& aVertices, int aClearance )
287{
288 int dist;
289
290 aVertices.NearestPoint( aDiagonal, dist );
291 VECTOR2I moveBy = ( aDiagonal.A - aDiagonal.B ).Perpendicular().Resize( dist - aClearance );
292 aDiagonal.A += moveBy;
293 aDiagonal.B += moveBy;
294}
295
296
297const SHAPE_LINE_CHAIN ConvexHull( const SHAPE_SIMPLE& aConvex, int aClearance )
298{
299 // this defines the horizontal and vertical lines in the hull octagon
300 BOX2I box = aConvex.BBox( aClearance );
301 box.Normalize();
302
303 SEG topline = SEG( VECTOR2I( box.GetX(), box.GetY() + box.GetHeight() ),
304 VECTOR2I( box.GetX() + box.GetWidth(), box.GetY() + box.GetHeight() ) );
305 SEG rightline = SEG( VECTOR2I( box.GetX() + box.GetWidth(), box.GetY() + box.GetHeight() ),
306 VECTOR2I( box.GetX() + box.GetWidth(), box.GetY() ) );
307 SEG bottomline = SEG( VECTOR2I( box.GetX() + box.GetWidth(), box.GetY() ),
308 box.GetOrigin() );
309 SEG leftline = SEG( box.GetOrigin(), VECTOR2I( box.GetX(), box.GetY() + box.GetHeight() ) );
310
311 const SHAPE_LINE_CHAIN& vertices = aConvex.Vertices();
312
313 // top right diagonal
314 VECTOR2I corner = box.GetOrigin() + box.GetSize();
315 SEG toprightline = SEG( corner,
316 corner + VECTOR2I( box.GetHeight(), -box.GetHeight() ) );
317 MoveDiagonal( toprightline, vertices, aClearance );
318
319 // bottom right diagonal
320 corner = box.GetOrigin() + VECTOR2I( box.GetWidth(), 0 );
321 SEG bottomrightline = SEG( corner + VECTOR2I( box.GetHeight(), box.GetHeight() ),
322 corner );
323 MoveDiagonal( bottomrightline, vertices, aClearance );
324
325 // bottom left diagonal
326 corner = box.GetOrigin();
327 SEG bottomleftline = SEG( corner,
328 corner + VECTOR2I( -box.GetHeight(), box.GetHeight() ) );
329 MoveDiagonal( bottomleftline, vertices, aClearance );
330
331 // top left diagonal
332 corner = box.GetOrigin() + VECTOR2I( 0, box.GetHeight() );
333 SEG topleftline = SEG( corner + VECTOR2I( -box.GetHeight(), -box.GetHeight() ),
334 corner );
335 MoveDiagonal( topleftline, vertices, aClearance );
336
337 SHAPE_LINE_CHAIN octagon;
338 octagon.SetClosed( true );
339
340 octagon.Append( *leftline.IntersectLines( bottomleftline ) );
341 octagon.Append( *bottomline.IntersectLines( bottomleftline ) );
342 octagon.Append( *bottomline.IntersectLines( bottomrightline ) );
343 octagon.Append( *rightline.IntersectLines( bottomrightline ) );
344 octagon.Append( *rightline.IntersectLines( toprightline ) );
345 octagon.Append( *topline.IntersectLines( toprightline ) );
346 octagon.Append( *topline.IntersectLines( topleftline ) );
347 octagon.Append( *leftline.IntersectLines( topleftline ) );
348
349 return octagon;
350}
351
352
354{
355 SHAPE_RECT r;
356
357 VECTOR2I delta( aSeg.GetWidth() / 2, aSeg.GetWidth() / 2 );
358 VECTOR2I p0( aSeg.GetSeg().A - delta );
359 VECTOR2I p1( aSeg.GetSeg().B + delta );
360
361 return SHAPE_RECT( std::min( p0.x, p1.x ), std::min( p0.y, p1.y ),
362 std::abs( p1.x - p0.x ), std::abs( p1.y - p0.y ) );
363}
364
365
366OPT_BOX2I ChangedArea( const ITEM* aItemA, const ITEM* aItemB )
367{
368 if( aItemA->OfKind( ITEM::VIA_T ) && aItemB->OfKind( ITEM::VIA_T ) )
369 {
370 const VIA* va = static_cast<const VIA*>( aItemA );
371 const VIA* vb = static_cast<const VIA*>( aItemB );
372
373 return va->ChangedArea( vb );
374 }
375 else if( aItemA->OfKind( ITEM::LINE_T ) && aItemB->OfKind( ITEM::LINE_T ) )
376 {
377 const LINE* la = static_cast<const LINE*> ( aItemA );
378 const LINE* lb = static_cast<const LINE*> ( aItemB );
379
380 return la->ChangedArea( lb );
381 }
382
383 return OPT_BOX2I();
384}
385
386OPT_BOX2I ChangedArea( const LINE& aLineA, const LINE& aLineB )
387{
388 return aLineA.ChangedArea( &aLineB );
389}
390
391
394{
396
397 if( line.PointCount() < 2 )
398 return;
399
400 hull.Intersect( line, ips_raw );
401
402 for( auto& p : ips_raw )
403 {
405
406 SEG d1[2];
407 VECTOR2I d2[2];
408 int d1_idx = 0, d2_idx = 0;
409
410 ipp = p;
411 ipp.valid = false;
412
413 if( !p.is_corner_our && !p.is_corner_their )
414 {
415 ipp.valid = true;
416 ips.push_back( ipp );
417 continue;
418 }
419
420 if( p.index_our >= hull.SegmentCount() )
421 p.index_our -= hull.SegmentCount();
422
423 if( p.is_corner_our )
424 {
425 d1[0] = hull.CSegment( p.index_our );
426 d1[1] = hull.CSegment( p.index_our - 1 );
427 d1_idx = 2;
428 }
429 else
430 {
431 d1[0] = hull.CSegment( p.index_our );
432 d1_idx = 1;
433 }
434
435 if( p.is_corner_their )
436 {
437 if( p.index_their > 0 )
438 {
439 d2[d2_idx++] = line.CSegment( p.index_their - 1 ).A;
440 }
441 if( p.index_their < line.PointCount() - 1 )
442 {
443 d2[d2_idx++] = line.CSegment( p.index_their ).B;
444 }
445 }
446 else
447 {
448 d2[d2_idx++] = line.CSegment( p.index_their ).A;
449 d2[d2_idx++] = line.CSegment( p.index_their ).B;
450 }
451
452 for( int i = 0; i < d1_idx; i++ )
453 {
454 for( int j = 0; j < d2_idx; j++ )
455 {
456 if( d1[i].Side( d2[j] ) > 0 )
457 {
458 ipp.valid = true;
459 }
460 }
461 }
462
463#ifdef TOM_EXTRA_DEBUG
464 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);
465 printf("d1 %d d2 %d\n", d1_idx, d2_idx );
466#endif
467 if( ipp.valid )
468 {
469 ips.push_back( ipp );
470 }
471 }
472}
473
474
475const SHAPE_LINE_CHAIN BuildHullForPrimitiveShape( const SHAPE* aShape, int aClearance,
476 int aWalkaroundThickness )
477{
478 int cl = aClearance + ( aWalkaroundThickness + 1 )/ 2;
479
480 switch( aShape->Type() )
481 {
482 case SH_RECT:
483 {
484 const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>( aShape );
485 return OctagonalHull( rect->GetPosition(),
486 rect->GetSize(),
487 cl,
488 0 );
489 }
490
491 case SH_CIRCLE:
492 {
493 const SHAPE_CIRCLE* circle = static_cast<const SHAPE_CIRCLE*>( aShape );
494 int r = circle->GetRadius();
495 return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ),
496 VECTOR2I( 2 * r, 2 * r ),
497 cl,
498 2.0 * ( 1.0 - M_SQRT1_2 ) * ( r + cl ) );
499 }
500
501 case SH_SEGMENT:
502 {
503 const SHAPE_SEGMENT* seg = static_cast<const SHAPE_SEGMENT*>( aShape );
504 return SegmentHull( *seg, aClearance, aWalkaroundThickness );
505 }
506
507 case SH_ARC:
508 {
509 const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( aShape );
510 return ArcHull( *arc, aClearance, aWalkaroundThickness );
511 }
512
513 case SH_SIMPLE:
514 {
515 const SHAPE_SIMPLE* convex = static_cast<const SHAPE_SIMPLE*>( aShape );
516
517 return ConvexHull( *convex, cl );
518 }
519 default:
520 {
521 wxFAIL_MSG( wxString::Format( wxT( "Unsupported hull shape: %d (%s)." ),
522 aShape->Type(),
523 SHAPE_TYPE_asString( aShape->Type() ) ) );
524 break;
525 }
526 }
527
528 return SHAPE_LINE_CHAIN();
529}
530
531
532void NodeStats( DEBUG_DECORATOR* dbg, wxString label, PNS::NODE *node )
533{
534 NODE::ITEM_VECTOR added, removed;
535 node->GetUpdatedItems( removed, added );
536
537 PNS_DBG( dbg, BeginGroup, wxString::Format( "node:%s this=%p depth=%d added=%d removed=%d",
538 label, node, node->Depth(), (int)added.size(), (int) removed.size() ), 0 );
539
540 for( auto& item : added )
541 PNS_DBG( dbg, AddItem, item, BLUE, 10000, wxT("added-item") );
542 for( auto& item : removed )
543 PNS_DBG( dbg, AddItem, item, RED, 10000, wxString::Format("removed-item") );
544
545 PNS_DBGN( dbg, EndGroup );
546}
547
548
549}
constexpr int ARC_LOW_DEF
Definition base_units.h:128
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 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:290
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:98
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: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)
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:37
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:68
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_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
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:695