KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_topology.cpp
Go to the documentation of this file.
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2015 CERN
5 * Copyright (C) 2016-2021 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_line.h"
23#include "pns_segment.h"
24#include "pns_node.h"
25#include "pns_joint.h"
26#include "pns_solid.h"
27#include "pns_router.h"
28#include "pns_utils.h"
29
30#include "pns_diff_pair.h"
31#include "pns_topology.h"
32
33#include <board.h>
34#include <pad.h>
35
36namespace PNS {
37
39{
40 if( !aLine->IsLinked() || !aLine->SegmentCount() )
41 return false;
42
43 LINKED_ITEM* root = aLine->GetLink( 0 );
44 LINE l = m_world->AssembleLine( root );
45 SHAPE_LINE_CHAIN simplified( l.CLine() );
46
47 simplified.Simplify();
48
49 if( simplified.PointCount() != l.PointCount() )
50 {
51 m_world->Remove( l );
52 LINE lnew( l );
53 lnew.SetShape( simplified );
54 m_world->Add( lnew );
55 return true;
56 }
57
58 return false;
59}
60
61
63{
64 std::deque<const JOINT*> searchQueue;
65 JOINT_SET processed;
66
67 searchQueue.push_back( aStart );
68 processed.insert( aStart );
69
70 while( !searchQueue.empty() )
71 {
72 const JOINT* current = searchQueue.front();
73 searchQueue.pop_front();
74
75 for( ITEM* item : current->LinkList() )
76 {
77 if( item->OfKind( ITEM::SEGMENT_T ) )
78 {
79 const JOINT* a = m_world->FindJoint( item->Anchor( 0 ), item );;
80 const JOINT* b = m_world->FindJoint( item->Anchor( 1 ), item );;
81 const JOINT* next = ( *a == *current ) ? b : a;
82
83 if( processed.find( next ) == processed.end() )
84 {
85 processed.insert( next );
86 searchQueue.push_back( next );
87 }
88 }
89 }
90 }
91
92 return processed;
93}
94
95
97 LAYER_RANGE& aLayers, ITEM*& aItem )
98{
99 LINE track( *aTrack );
100 VECTOR2I end;
101
102 if( !track.PointCount() )
103 return false;
104
105 std::unique_ptr<NODE> tmpNode( m_world->Branch() );
106 tmpNode->Add( track );
107
108 const JOINT* jt = tmpNode->FindJoint( track.CPoint( -1 ), &track );
109
110 if( !jt || jt->Net() <= 0 )
111 return false;
112
113 if( ( !track.EndsWithVia() && jt->LinkCount() >= 2 )
114 || ( track.EndsWithVia() && jt->LinkCount() >= 3 ) ) // we got something connected
115 {
116 end = jt->Pos();
117 aLayers = jt->Layers();
118 aItem = jt->LinkList()[0];
119 }
120 else
121 {
122 int anchor;
123
124 TOPOLOGY topo( tmpNode.get() );
125 ITEM* it = topo.NearestUnconnectedItem( jt, &anchor );
126
127 if( !it )
128 return false;
129
130 end = it->Anchor( anchor );
131 aLayers = it->Layers();
132 aItem = it;
133 }
134
135 aPoint = end;
136 return true;
137}
138
139
140bool TOPOLOGY::LeadingRatLine( const LINE* aTrack, SHAPE_LINE_CHAIN& aRatLine )
141{
142 VECTOR2I end;
143 // Ratline doesn't care about the layer
144 LAYER_RANGE layers;
145 ITEM* unusedItem;
146
147 if( !NearestUnconnectedAnchorPoint( aTrack, end, layers, unusedItem ) )
148 return false;
149
150 aRatLine.Clear();
151 aRatLine.Append( aTrack->CPoint( -1 ) );
152 aRatLine.Append( end );
153 return true;
154}
155
156
157ITEM* TOPOLOGY::NearestUnconnectedItem( const JOINT* aStart, int* aAnchor, int aKindMask )
158{
159 std::set<ITEM*> disconnected;
160
161 m_world->AllItemsInNet( aStart->Net(), disconnected );
162
163 for( const JOINT* jt : ConnectedJoints( aStart ) )
164 {
165 for( ITEM* link : jt->LinkList() )
166 {
167 if( disconnected.find( link ) != disconnected.end() )
168 disconnected.erase( link );
169 }
170 }
171
172 int best_dist = INT_MAX;
173 ITEM* best = nullptr;
174
175 for( ITEM* item : disconnected )
176 {
177 if( item->OfKind( aKindMask ) )
178 {
179 for( int i = 0; i < item->AnchorCount(); i++ )
180 {
181 VECTOR2I p = item->Anchor( i );
182 int d = ( p - aStart->Pos() ).EuclideanNorm();
183
184 if( d < best_dist )
185 {
186 best_dist = d;
187 best = item;
188
189 if( aAnchor )
190 *aAnchor = i;
191 }
192 }
193 }
194 }
195
196 return best;
197}
198
199
200bool TOPOLOGY::followTrivialPath( LINE* aLine, bool aLeft, ITEM_SET& aSet,
201 std::set<ITEM*>& aVisited, const JOINT** aTerminalJoint )
202{
203 assert( aLine->IsLinked() );
204
205 VECTOR2I anchor = aLeft ? aLine->CPoint( 0 ) : aLine->CPoint( -1 );
206 LINKED_ITEM* last = aLeft ? aLine->Links().front() : aLine->Links().back();
207 const JOINT* jt = m_world->FindJoint( anchor, aLine );
208
209 assert( jt != nullptr );
210
211 aVisited.insert( last );
212
213 if( jt->IsNonFanoutVia() || jt->IsTraceWidthChange() )
214 {
215 ITEM* via = nullptr;
216 SEGMENT* next_seg = nullptr;
217
218 ITEM_SET links( jt->CLinks() );
219
220 for( ITEM* link : links )
221 {
222 if( link->OfKind( ITEM::VIA_T ) )
223 via = link;
224 else if( aVisited.find( link ) == aVisited.end() )
225 next_seg = static_cast<SEGMENT*>( link );
226 }
227
228 if( !next_seg )
229 {
230 if( aTerminalJoint )
231 *aTerminalJoint = jt;
232
233 return false;
234 }
235
236 LINE l = m_world->AssembleLine( next_seg );
237
238 VECTOR2I nextAnchor = ( aLeft ? l.CLine().CPoint( -1 ) : l.CLine().CPoint( 0 ) );
239
240 if( nextAnchor != anchor )
241 {
242 l.Reverse();
243 }
244
245 if( aLeft )
246 {
247 if( via )
248 aSet.Prepend( via );
249
250 aSet.Prepend( l );
251 }
252 else
253 {
254 if( via )
255 aSet.Add( via );
256
257 aSet.Add( l );
258 }
259
260 return followTrivialPath( &l, aLeft, aSet, aVisited, aTerminalJoint );
261 }
262
263 if( aTerminalJoint )
264 *aTerminalJoint = jt;
265
266 return false;
267}
268
269
271 std::pair<const JOINT*, const JOINT*>* aTerminalJoints,
272 bool aFollowLockedSegments )
273{
275 std::set<ITEM*> visited;
276 LINKED_ITEM* seg = nullptr;
277
278 if( aStart->Kind() == ITEM::VIA_T )
279 {
280 VIA* via = static_cast<VIA*>( aStart );
281 const JOINT* jt = m_world->FindJoint( via->Pos(), via );
282
283 if( !jt->IsNonFanoutVia() )
284 return ITEM_SET();
285
286 ITEM_SET links( jt->CLinks() );
287
288 for( ITEM* item : links )
289 {
290 if( item->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
291 {
292 seg = static_cast<LINKED_ITEM*>( item );
293 break;
294 }
295 }
296 }
297 else if( aStart->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
298 {
299 seg = static_cast<LINKED_ITEM*>( aStart );
300 }
301
302 if( !seg )
303 return ITEM_SET();
304
305 // Assemble a line following through locked segments
306 // TODO: consider if we want to allow tuning lines with different widths in the future
307 LINE l = m_world->AssembleLine( seg, nullptr, false, true );
308
309 path.Add( l );
310
311 const JOINT* jointA = nullptr;
312 const JOINT* jointB = nullptr;
313
314 followTrivialPath( &l, false, path, visited, &jointB );
315 followTrivialPath( &l, true, path, visited, &jointA );
316
317 if( aTerminalJoints )
318 {
319 wxASSERT( jointA && jointB );
320 *aTerminalJoints = std::make_pair( jointA, jointB );
321 }
322
323 return path;
324}
325
326
327const ITEM_SET TOPOLOGY::AssembleTuningPath( ITEM* aStart, SOLID** aStartPad, SOLID** aEndPad )
328{
329 std::pair<const JOINT*, const JOINT*> joints;
330 ITEM_SET initialPath = AssembleTrivialPath( aStart, &joints, true );
331
332 PAD* padA = nullptr;
333 PAD* padB = nullptr;
334
335 auto getPadFromJoint =
336 []( const JOINT* aJoint, PAD** aTargetPad, SOLID** aTargetSolid )
337 {
338 for( ITEM* item : aJoint->LinkList() )
339 {
340 if( item->OfKind( ITEM::SOLID_T ) )
341 {
342 BOARD_ITEM* bi = static_cast<SOLID*>( item )->Parent();
343
344 if( bi->Type() == PCB_PAD_T )
345 {
346 *aTargetPad = static_cast<PAD*>( bi );
347
348 if( aTargetSolid )
349 *aTargetSolid = static_cast<SOLID*>( item );
350 }
351
352 break;
353 }
354 }
355 };
356
357 if( joints.first )
358 getPadFromJoint( joints.first, &padA, aStartPad );
359
360 if( joints.second )
361 getPadFromJoint( joints.second, &padB, aEndPad );
362
363 if( !padA && !padB )
364 return initialPath;
365
366 auto clipLineToPad =
367 []( SHAPE_LINE_CHAIN& aLine, PAD* aPad, bool aForward = true )
368 {
369 const std::shared_ptr<SHAPE_POLY_SET>& shape = aPad->GetEffectivePolygon();
370
371 int start = aForward ? 0 : aLine.PointCount() - 1;
372 int delta = aForward ? 1 : -1;
373
374 // Skip the "first" (or last) vertex, we already know it's contained in the pad
375 int clip = start;
376
377 for( int vertex = start + delta;
378 aForward ? vertex < aLine.PointCount() : vertex >= 0;
379 vertex += delta )
380 {
381 SEG seg( aLine.GetPoint( vertex ), aLine.GetPoint( vertex - delta ) );
382
383 bool containsA = shape->Contains( seg.A );
384 bool containsB = shape->Contains( seg.B );
385
386 if( containsA && containsB )
387 {
388 // Whole segment is inside: clip out this segment
389 clip = vertex;
390 }
391 else if( containsB )
392 {
393 // Only one point inside: Find the intersection
394 VECTOR2I loc;
395
396 if( shape->Collide( seg, 0, nullptr, &loc ) )
397 {
398 aLine.Replace( vertex - delta, vertex - delta, loc );
399 }
400 }
401 }
402
403 if( !aForward && clip < start )
404 aLine.Remove( clip + 1, start );
405 else if( clip > start )
406 aLine.Remove( start, clip - 1 );
407
408 // Now connect the dots
409 aLine.Insert( aForward ? 0 : aLine.PointCount(), aPad->GetPosition() );
410 };
411
412 auto processPad =
413 [&]( const JOINT* aJoint, PAD* aPad )
414 {
415 const std::shared_ptr<SHAPE_POLY_SET>& shape = aPad->GetEffectivePolygon();
416
417 for( int idx = 0; idx < initialPath.Size(); idx++ )
418 {
419 if( initialPath[idx]->Kind() != ITEM::LINE_T )
420 continue;
421
422 LINE* line = static_cast<LINE*>( initialPath[idx] );
423
424 if( !aPad->FlashLayer( line->Layer() ) )
425 continue;
426
427 const std::vector<VECTOR2I>& points = line->CLine().CPoints();
428
429 if( points.front() != aJoint->Pos() && points.back() != aJoint->Pos() )
430 continue;
431
432 SHAPE_LINE_CHAIN& slc = line->Line();
433
434 if( shape->Contains( slc.CPoint( 0 ) ) )
435 clipLineToPad( slc, aPad, true );
436 else if( shape->Contains( slc.CPoint( -1 ) ) )
437 clipLineToPad( slc, aPad, false );
438 }
439 };
440
441 if( padA )
442 processPad( joints.first, padA );
443
444 if( padB )
445 processPad( joints.second, padB );
446
447 return initialPath;
448}
449
450
451const ITEM_SET TOPOLOGY::ConnectedItems( const JOINT* aStart, int aKindMask )
452{
453 return ITEM_SET();
454}
455
456
457const ITEM_SET TOPOLOGY::ConnectedItems( ITEM* aStart, int aKindMask )
458{
459 return ITEM_SET();
460}
461
462
463bool commonParallelProjection( SEG p, SEG n, SEG &pClip, SEG& nClip );
464
465
467{
468 int refNet = aStart->Net();
469 int coupledNet = m_world->GetRuleResolver()->DpCoupledNet( refNet );
470
471 if( coupledNet < 0 )
472 return false;
473
474 std::set<ITEM*> coupledItems;
475
476 m_world->AllItemsInNet( coupledNet, coupledItems );
477
478 SEGMENT* coupledSeg = nullptr, *refSeg;
479 int minDist = std::numeric_limits<int>::max();
480
481 if( ( refSeg = dyn_cast<SEGMENT*>( aStart ) ) != nullptr )
482 {
483 for( ITEM* item : coupledItems )
484 {
485 if( SEGMENT* s = dyn_cast<SEGMENT*>( item ) )
486 {
487 if( s->Layers().Start() == refSeg->Layers().Start() &&
488 s->Width() == refSeg->Width() )
489 {
490 int dist = s->Seg().Distance( refSeg->Seg() );
491 bool isParallel = refSeg->Seg().ApproxParallel( s->Seg(), DP_PARALLELITY_THRESHOLD );
492 SEG p_clip, n_clip;
493
494 bool isCoupled = commonParallelProjection( refSeg->Seg(), s->Seg(), p_clip,
495 n_clip );
496
497 if( isParallel && isCoupled && dist < minDist )
498 {
499 minDist = dist;
500 coupledSeg = s;
501 }
502 }
503 }
504 }
505 }
506 else
507 {
508 return false;
509 }
510
511 if( !coupledSeg )
512 return false;
513
514 LINE lp = m_world->AssembleLine( refSeg );
515 LINE ln = m_world->AssembleLine( coupledSeg );
516
517 if( m_world->GetRuleResolver()->DpNetPolarity( refNet ) < 0 )
518 {
519 std::swap( lp, ln );
520 }
521
522 int gap = -1;
523
524 if( refSeg->Seg().ApproxParallel( coupledSeg->Seg(), DP_PARALLELITY_THRESHOLD ) )
525 {
526 // Segments are parallel -> compute pair gap
527 const VECTOR2I refDir = refSeg->Anchor( 1 ) - refSeg->Anchor( 0 );
528 const VECTOR2I displacement = refSeg->Anchor( 1 ) - coupledSeg->Anchor( 1 );
529 gap = (int) std::abs( refDir.Cross( displacement ) / refDir.EuclideanNorm() ) - lp.Width();
530 }
531
532 aPair = DIFF_PAIR( lp, ln );
533 aPair.SetWidth( lp.Width() );
534 aPair.SetLayers( lp.Layers() );
535 aPair.SetGap( gap );
536
537 return true;
538}
539
540const std::set<ITEM*> TOPOLOGY::AssembleCluster( ITEM* aStart, int aLayer )
541{
542 std::set<ITEM*> visited;
543 std::deque<ITEM*> pending;
544
546
547 opts.m_differentNetsOnly = false;
548 opts.m_overrideClearance = 0;
549
550 pending.push_back( aStart );
551
552 while( !pending.empty() )
553 {
554 NODE::OBSTACLES obstacles;
555 ITEM* top = pending.front();
556
557 pending.pop_front();
558
559 visited.insert( top );
560
561 m_world->QueryColliding( top, obstacles, opts ); // only query touching objects
562
563 for( const OBSTACLE& obs : obstacles )
564 {
565 bool trackOnTrack = ( obs.m_item->Net() != top->Net() ) && obs.m_item->OfKind( ITEM::SEGMENT_T ) && top->OfKind( ITEM::SEGMENT_T );
566
567 if( trackOnTrack )
568 continue;
569
570 if( visited.find( obs.m_item ) == visited.end() &&
571 obs.m_item->Layers().Overlaps( aLayer ) && !( obs.m_item->Marker() & MK_HEAD ) )
572 {
573 visited.insert( obs.m_item );
574 pending.push_back( obs.m_item );
575 }
576 }
577 }
578
579 return visited;
580}
581
582}
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:71
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
Represent a contiguous set of PCB layers.
Definition: pns_layerset.h:32
Definition: pad.h:59
Basic class for a differential pair.
void SetGap(int aGap)
void SetWidth(int aWidth)
int Size() const
Definition: pns_itemset.h:112
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
void Prepend(const LINE &aLine)
Definition: pns_itemset.cpp:40
Base class for PNS router board items.
Definition: pns_item.h:91
void SetLayers(const LAYER_RANGE &aLayers)
Definition: pns_item.h:192
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:162
virtual int Layer() const
Definition: pns_item.h:195
virtual int Net() const
Definition: pns_item.h:189
@ SOLID_T
Definition: pns_item.h:98
@ LINE_T
Definition: pns_item.h:99
@ SEGMENT_T
Definition: pns_item.h:101
const LAYER_RANGE & Layers() const
Definition: pns_item.h:191
bool OfKind(int aKindMask) const
Definition: pns_item.h:170
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:232
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
const std::vector< ITEM * > & LinkList() const
Definition: pns_joint.h:239
int LinkCount(int aMask=-1) const
Definition: pns_joint.h:254
bool IsNonFanoutVia() const
Definition: pns_joint.h:156
int Net() const override
Definition: pns_joint.h:234
bool IsTraceWidthChange() const
Link the joint to a given board item (when it's added to the NODE).
Definition: pns_joint.h:170
const ITEM_SET & CLinks() const
Definition: pns_joint.h:244
const VECTOR2I & Pos() const
Definition: pns_joint.h:229
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:61
const VECTOR2I & CPoint(int aIdx) const
Definition: pns_line.h:144
void SetShape(const SHAPE_LINE_CHAIN &aLine)
Return the shape of the line.
Definition: pns_line.h:125
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:136
SHAPE_LINE_CHAIN & Line()
Definition: pns_line.h:135
void Reverse()
Clip the line to the nearest obstacle, traversing from the line's start vertex (0).
Definition: pns_line.cpp:1049
int SegmentCount() const
Definition: pns_line.h:138
int PointCount() const
Definition: pns_line.h:139
bool EndsWithVia() const
Definition: pns_line.h:188
int Width() const
Return true if the line is geometrically identical as line aOther.
Definition: pns_line.h:155
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
Definition: pns_node.cpp:127
void AllItemsInNet(int aNet, std::set< ITEM * > &aItems, int aKindMask=-1)
Definition: pns_node.cpp:1428
RULE_RESOLVER * GetRuleResolver() const
Return the number of joints.
Definition: pns_node.h:236
std::set< OBSTACLE > OBSTACLES
Definition: pns_node.h:210
int QueryColliding(const ITEM *aItem, OBSTACLES &aObstacles, const COLLISION_SEARCH_OPTIONS &aOpts=COLLISION_SEARCH_OPTIONS()) const
Find items colliding (closer than clearance) with the item aItem.
Definition: pns_node.cpp:236
bool Add(std::unique_ptr< SEGMENT > &&aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:615
const JOINT * FindJoint(const VECTOR2I &aPos, int aLayer, int aNet) const
Search for a joint at a given position, layer and belonging to given net.
Definition: pns_node.cpp:1153
void Remove(ARC *aArc)
Remove an item from this branch.
Definition: pns_node.cpp:831
const LINE AssembleLine(LINKED_ITEM *aSeg, int *aOriginSegmentIndex=nullptr, bool aStopAtLockedJoints=false, bool aFollowLockedSegments=false)
Follow the joint map to assemble a line connecting two non-trivial joints starting from segment aSeg.
Definition: pns_node.cpp:955
virtual int DpNetPolarity(int aNet)=0
virtual int DpCoupledNet(int aNet)=0
const SEG & Seg() const
Definition: pns_segment.h:84
virtual VECTOR2I Anchor(int n) const override
Definition: pns_segment.h:107
ITEM * NearestUnconnectedItem(const JOINT *aStart, int *aAnchor=nullptr, int aKindMask=ITEM::ANY_T)
std::set< const JOINT * > JOINT_SET
Definition: pns_topology.h:42
bool LeadingRatLine(const LINE *aTrack, SHAPE_LINE_CHAIN &aRatLine)
const DIFF_PAIR AssembleDiffPair(SEGMENT *aStart)
bool NearestUnconnectedAnchorPoint(const LINE *aTrack, VECTOR2I &aPoint, LAYER_RANGE &aLayers, ITEM *&aItem)
const ITEM_SET ConnectedItems(const JOINT *aStart, int aKindMask=ITEM::ANY_T)
const JOINT_SET ConnectedJoints(const JOINT *aStart)
const int DP_PARALLELITY_THRESHOLD
Definition: pns_topology.h:96
const ITEM_SET AssembleTrivialPath(ITEM *aStart, std::pair< const JOINT *, const JOINT * > *aTerminalJoints=nullptr, bool aFollowLockedSegments=false)
Assemble a trivial path between two joints given a starting item.
bool followTrivialPath(LINE *aLine, bool aLeft, ITEM_SET &aSet, std::set< ITEM * > &aVisited, const JOINT **aTerminalJoint=nullptr)
const std::set< ITEM * > AssembleCluster(ITEM *aStart, int aLayer)
bool SimplifyLine(LINE *aLine)
const ITEM_SET AssembleTuningPath(ITEM *aStart, SOLID **aStartPad=nullptr, SOLID **aEndPad=nullptr)
Like AssembleTrivialPath, but follows the track length algorithm, which discards segments that are fu...
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
SHAPE_LINE_CHAIN & Simplify(bool aRemoveColinear=true)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
virtual const VECTOR2I GetPoint(int aIndex) const override
int PointCount() const
Return the number of points (vertices) in this line chain.
void Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Replace points with indices in range [start_index, end_index] with a single point aP.
void Clear()
Remove all points from the line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
void Insert(size_t aVertex, const VECTOR2I &aP)
const std::vector< VECTOR2I > & CPoints() const
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:265
extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
Definition: vector2d.h:457
Push and Shove diff pair dimensions (gap) settings dialog.
bool commonParallelProjection(SEG p, SEG n, SEG &pClip, SEG &nClip)
@ MK_HEAD
Definition: pns_item.h:42
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:418
CITER next(CITER it)
Definition: ptree.cpp:126
Hold an object colliding with another object, along with some useful data about the collision.
Definition: pns_node.h:84
constexpr int delta
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87