KiCad PCB EDA Suite
Loading...
Searching...
No Matches
drc_creepage_utils.h
Go to the documentation of this file.
1/*
2 * Copyright The KiCad Developers.
3 * Copyright (C) 2024 Fabien Corona f.corona<at>laposte.net
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, you may find one here:
17 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18 * or you may search the http://www.gnu.org website for the version 2 license,
19 * or you may write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23
24#pragma once
25
26#include <unordered_set>
27
28#include <common.h>
29#include <macros.h>
31#include <footprint.h>
32#include <pad.h>
33#include <pcb_track.h>
34#include <pcb_shape.h>
35#include <zone.h>
36#include <advanced_config.h>
37#include <geometry/shape_rect.h>
38#include <geometry/seg.h>
40#include <drc/drc_item.h>
41#include <drc/drc_rule.h>
42#include <board.h>
43
44
46#include <geometry/rtree.h>
47
48
49// Simple wrapper for track segment data in the RTree
55
56using TRACK_RTREE = RTree<CREEPAGE_TRACK_ENTRY*, int, 2, double>;
57
58extern bool SegmentIntersectsBoard( const VECTOR2I& aP1, const VECTOR2I& aP2,
59 const std::vector<BOARD_ITEM*>& aBe,
60 const std::vector<const BOARD_ITEM*>& aDontTestAgainst,
61 int aMinGrooveWidth );
62
63
65{
68 double weight = -1;
69 bool m_show = true;
70
73
74
88 bool isValid( const BOARD& aBoard, PCB_LAYER_ID aLayer,
89 const std::vector<BOARD_ITEM*>& aBoardEdges,
90 const std::vector<const BOARD_ITEM*>& aIgnoreForTest, SHAPE_POLY_SET* aOutline,
91 const std::pair<bool, bool>& aTestLocalConcavity, int aMinGrooveWidth,
92 TRACK_RTREE* aTrackIndex = nullptr ) const
93 {
94 if( !aOutline )
95 return true; // We keep the segment if there is a problem
96
97 if( !SegmentIntersectsBoard( a1, a2, aBoardEdges, aIgnoreForTest, aMinGrooveWidth ) )
98 return false;
99
100 // The mid point should be inside the board.
101 // Tolerance of 100nm.
102
103 VECTOR2I midPoint = ( a1 + a2 ) / 2;
104 int tolerance = 100;
105
106 bool contained = aOutline->Contains( midPoint, -1, tolerance )
107 || aOutline->PointOnEdge( midPoint, tolerance );
108
109 if( !contained )
110 return false;
111
112 if( false && ( aTestLocalConcavity.first || aTestLocalConcavity.second ) )
113 {
114 // Test for local concavity. If it is localy convex, then it will not be a path of interest.
115
116 double extendLine = 1000; // extend line by 1000nm
117 // In some cases, the projected point could be on the board edge
118 // In such cases, we wan to keep the line.
119 // We inflate the polygon to get a small margin for computation/rounding error.
120 // We might keep some unnecessary lines, but it's better than loosing the important ones.
121 double extendPoly = 100; // extend polygon by 10 nm
122
123 VECTOR2D a( double( a1.x ), double( a1.y ) );
124 VECTOR2D b( double( a2.x ), double( a2.y ) );
125
126 VECTOR2D dir( b - a );
127 dir = dir * ( extendLine / dir.SquaredEuclideanNorm() );
128
129 SHAPE_POLY_SET outline2 = *aOutline;
130 outline2.Inflate( extendPoly, CORNER_STRATEGY::ROUND_ALL_CORNERS, 3 );
131
132 if( aTestLocalConcavity.first && !aOutline->Contains( a - dir, -1, 0 ) )
133 return false;
134
135 if( aTestLocalConcavity.second && !aOutline->Contains( b + dir, -1, 0 ) )
136 return false;
137 }
138
139 if( aLayer != Edge_Cuts )
140 {
141 SEG segPath( a1, a2 );
142
143 // Prefer RTree search if available
144 if( aTrackIndex )
145 {
146 // Calculate bounding box of the path segment
147 int minX = std::min( (int) a1.x, (int) a2.x );
148 int minY = std::min( (int) a1.y, (int) a2.y );
149 int maxX = std::max( (int) a1.x, (int) a2.x );
150 int maxY = std::max( (int) a1.y, (int) a2.y );
151
152 int searchMin[2] = { minX, minY };
153 int searchMax[2] = { maxX, maxY };
154
155 bool intersects = false;
156
157 aTrackIndex->Search( searchMin, searchMax,
158 [&]( CREEPAGE_TRACK_ENTRY* entry ) -> bool
159 {
160 if( entry && entry->layer == aLayer )
161 {
162 if( segPath.Intersects( entry->segment ) )
163 {
164 intersects = true;
165 return false; // Stop searching
166 }
167 }
168 return true; // Continue searching
169 } );
170
171 if( intersects )
172 return false;
173 }
174 else
175 {
176 // Fallback to linear search if no index provided
177 for( PCB_TRACK* track : aBoard.Tracks() )
178 {
179 if( !track )
180 continue;
181
182 if( track->Type() == KICAD_T::PCB_TRACE_T && track->IsOnLayer( aLayer ) )
183 {
184 std::shared_ptr<SHAPE> sh = track->GetEffectiveShape();
185
186 if( sh && sh->Type() == SHAPE_TYPE::SH_SEGMENT )
187 {
188 SEG segTrack( track->GetStart(), track->GetEnd() );
189
190 if( segPath.Intersects( segTrack ) )
191 return false;
192 }
193 }
194 }
195 }
196 }
197 return true;
198 }
199};
200
201
202class GRAPH_CONNECTION;
203class GRAPH_NODE;
204class CREEPAGE_GRAPH;
205class CREEP_SHAPE;
206class BE_SHAPE;
207class BE_SHAPE_POINT;
208class BE_SHAPE_ARC;
209class BE_SHAPE_CIRCLE;
210class CU_SHAPE;
211class CU_SHAPE_SEGMENT;
212class CU_SHAPE_CIRCLE;
213class CU_SHAPE_ARC;
214
220{
221public:
222 enum class TYPE
223 {
228 };
229
231 {
232 m_conductive = false;
233 m_parent = nullptr;
234 m_pos = VECTOR2I( 0, 0 );
235 m_type = CREEP_SHAPE::TYPE::UNDEFINED;
236 };
237
238 virtual ~CREEP_SHAPE() {}
239
240 virtual int GetRadius() const { return 0; };
241 virtual EDA_ANGLE GetStartAngle() const { return EDA_ANGLE( 0 ); };
242 virtual EDA_ANGLE GetEndAngle() const { return EDA_ANGLE( 0 ); };
243 virtual VECTOR2I GetStartPoint() const { return VECTOR2I( 0, 0 ); };
244 virtual VECTOR2I GetEndPoint() const { return VECTOR2I( 0, 0 ); };
245 VECTOR2I GetPos() const { return m_pos; };
246 CREEP_SHAPE::TYPE GetType() const { return m_type; };
247 const BOARD_ITEM* GetParent() const { return m_parent; };
248 void SetParent( BOARD_ITEM* aParent ) { m_parent = aParent; };
249
250 virtual void ConnectChildren( std::shared_ptr<GRAPH_NODE>& a1, std::shared_ptr<GRAPH_NODE>& a2,
251 CREEPAGE_GRAPH& aG ) const;
252
253 std::vector<PATH_CONNECTION> ReversePaths( const std::vector<PATH_CONNECTION>& aV ) const
254 {
255 std::vector<PATH_CONNECTION> r;
256 r.reserve( aV.size() );
257
258 for( const auto& pc : aV )
259 {
260 r.emplace_back( pc );
261 std::swap( r.back().a1, r.back().a2 );
262 }
263
264 return r;
265 }
266
267 std::vector<PATH_CONNECTION> Paths( const CREEP_SHAPE& aS2, double aMaxWeight,
268 double aMaxSquaredWeight ) const
269 {
270 std::vector<PATH_CONNECTION> a;
271 return a;
272 };
273
274 virtual std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
275 double aMaxSquaredWeight ) const
276 {
277 std::vector<PATH_CONNECTION> a;
278 return a;
279 };
280
281 virtual std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
282 double aMaxSquaredWeight ) const
283 {
284 std::vector<PATH_CONNECTION> a;
285 return a;
286 };
287
288 virtual std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
289 double aMaxSquaredWeight ) const
290 {
291 std::vector<PATH_CONNECTION> a;
292 return a;
293 };
294
295 virtual std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
296 double aMaxSquaredWeight ) const
297 {
298 std::vector<PATH_CONNECTION> a;
299 return a;
300 };
301
302 virtual std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
303 double aMaxSquaredWeight ) const
304 {
305 std::vector<PATH_CONNECTION> a;
306 return a;
307 };
308
309 virtual std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_ARC& aS2, double aMaxWeight,
310 double aMaxSquaredWeight ) const
311 {
312 std::vector<PATH_CONNECTION> a;
313 return a;
314 };
315
316 //virtual std::vector<PATH_CONNECTION> GetPathsCuToBe( CREEP_SHAPE* aShape ) const{ std::vector<PATH_CONNECTION> a; return a;};
317 bool IsConductive() { return m_conductive; };
318
319protected:
324};
325
326
331class CU_SHAPE : public CREEP_SHAPE
332{
333public:
336 {
337 m_conductive = true;
338 };
339};
340
345class BE_SHAPE : public CREEP_SHAPE
346{
347public:
350 {
351 m_conductive = false;
352 };
353};
354
360{
361public:
362 CU_SHAPE_SEGMENT( VECTOR2I aStart, VECTOR2I aEnd, double aWidth = 0 ) :
363 CU_SHAPE()
364 {
365 m_start = aStart;
366 m_end = aEnd;
367 m_width = aWidth;
368 }
369
370 VECTOR2I GetStart() const { return m_start; };
371 VECTOR2I GetEnd() const { return m_end; };
372 double GetWidth() const { return m_width; };
373
374 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
375 double aMaxSquaredWeight ) const override;
376 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
377 double aMaxSquaredWeight ) const override;
378 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
379 double aMaxSquaredWeight ) const override;
380 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
381 double aMaxSquaredWeight ) const override;
382 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
383 double aMaxSquaredWeight ) const override;
384 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_ARC& aS2, double aMaxWeight,
385 double aMaxSquaredWeight ) const override;
386
387
388private:
391 double m_width = 0;
392};
393
399{
400public:
401 CU_SHAPE_CIRCLE( VECTOR2I aPos, double aRadius = 0 ) :
402 CU_SHAPE()
403 {
404 m_pos = aPos;
405 m_radius = aRadius;
406 }
407
408 VECTOR2I GetPos() const { return m_pos; };
409 int GetRadius() const override { return m_radius; };
410
411 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
412 double aMaxSquaredWeight ) const override;
413 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
414 double aMaxSquaredWeight ) const override;
415 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
416 double aMaxSquaredWeight ) const override;
417 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
418 double aMaxSquaredWeight ) const override
419 {
420 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
421 };
422
423 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
424 double aMaxSquaredWeight ) const override;
425 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_ARC& aS2, double aMaxWeight,
426 double aMaxSquaredWeight ) const override;
427
428protected:
430 double m_radius = 1;
431};
432
438{
439public:
440 CU_SHAPE_ARC( VECTOR2I aPos, double aRadius, EDA_ANGLE aStartAngle, EDA_ANGLE aEndAngle,
441 VECTOR2D aStartPoint, VECTOR2D aEndPoint ) :
442 CU_SHAPE_CIRCLE( aPos, aRadius ),
443 m_startAngle( aStartAngle ),
444 m_endAngle( aEndAngle ),
445 m_startPoint( aStartPoint ),
446 m_endPoint( aEndPoint )
447 {
448 m_type = CREEP_SHAPE::TYPE::ARC;
449 m_width = 0;
450 }
451
452 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
453 double aMaxSquaredWeight ) const override;
454
455 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
456 double aMaxSquaredWeight ) const override;
457
458 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
459 double aMaxSquaredWeight ) const override;
460
461 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
462 double aMaxSquaredWeight ) const override
463 {
464 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
465 };
466
467 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
468 double aMaxSquaredWeight ) const override
469 {
470 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
471 };
472
473 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_ARC& aS2, double aMaxWeight,
474 double aMaxSquaredWeight ) const override;
475
476 EDA_ANGLE GetStartAngle() const override { return m_startAngle; }
477 EDA_ANGLE GetEndAngle() const override { return m_endAngle; }
478 int GetRadius() const override { return m_radius; }
479
480 VECTOR2I GetStartPoint() const override { return m_startPoint; }
481 VECTOR2I GetEndPoint() const override { return m_endPoint; }
482
484 {
485 EDA_ANGLE angle( aPoint - m_pos );
486
487 while( angle < GetStartAngle() )
488 angle += ANGLE_360;
489
490 while( angle > GetEndAngle() + ANGLE_360 )
491 angle -= ANGLE_360;
492
493 return angle;
494 }
495
496 double GetWidth() const { return m_width; };
497 void SetWidth( double aW ) { m_width = aW; };
498
499private:
505};
506
512{
513public:
522
523 GRAPH_NODE( GRAPH_NODE::TYPE aType, CREEP_SHAPE* aParent, const VECTOR2I& aPos = VECTOR2I() ) :
524 m_parent( aParent ),
525 m_pos( aPos ),
526 m_type( aType )
527 {
528 m_node_conns = {};
529 m_virtual = false;
530 m_connectDirectly = true;
531 m_net = -1;
532 };
533
535
536public:
538 std::set<std::shared_ptr<GRAPH_CONNECTION>> m_node_conns;
540
541 // Virtual nodes are connected with a 0 weight connection to equivalent net ( same net or netclass )
544 int m_net;
545
547};
548
554{
555public:
556 GRAPH_CONNECTION( std::shared_ptr<GRAPH_NODE>& aN1, std::shared_ptr<GRAPH_NODE>& aN2,
557 const PATH_CONNECTION& aPc ) :
558 n1( aN1 ),
559 n2( aN2 )
560 {
561 m_path = aPc;
562 m_forceStraightLine = false;
563 };
564
565 void GetShapes( std::vector<PCB_SHAPE>& aShapes );
566
567public:
568 std::shared_ptr<GRAPH_NODE> n1;
569 std::shared_ptr<GRAPH_NODE> n2;
572};
573
574
580{
581public:
583 BE_SHAPE()
584 {
585 m_pos = aPos;
586 m_type = CREEP_SHAPE::TYPE::POINT;
587 }
588
589 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
590 double aMaxSquaredWeight ) const override;
591
592 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
593 double aMaxSquaredWeight ) const override;
594
595 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
596 double aMaxSquaredWeight ) const override;
597
598 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
599 double aMaxSquaredWeight ) const override
600 {
601 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
602 };
603
604 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
605 double aMaxSquaredWeight ) const override
606 {
607 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
608 }
609
610 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_ARC& aS2, double aMaxWeight,
611 double aMaxSquaredWeight ) const override
612 {
613 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
614 };
615
616
617 void ConnectChildren( std::shared_ptr<GRAPH_NODE>& a1, std::shared_ptr<GRAPH_NODE>& a2,
618 CREEPAGE_GRAPH& aG ) const override;
619};
620
626{
627public:
628 BE_SHAPE_CIRCLE( VECTOR2I aPos = VECTOR2I( 0, 0 ), int aRadius = 0 ) :
629 BE_SHAPE()
630 {
631 m_pos = aPos;
632 m_radius = aRadius;
633 m_type = CREEP_SHAPE::TYPE::CIRCLE;
634 }
635
636 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
637 double aMaxSquaredWeight ) const override
638 {
639 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
640 };
641
642 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
643 double aMaxSquaredWeight ) const override;
644
645 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
646 double aMaxSquaredWeight ) const override;
647
648 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
649 double aMaxSquaredWeight ) const override
650 {
651 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
652 };
653
654 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
655 double aMaxSquaredWeight ) const override
656 {
657 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
658 };
659
660
661 int GetRadius() const override { return m_radius; }
662
663 void ConnectChildren( std::shared_ptr<GRAPH_NODE>& a1, std::shared_ptr<GRAPH_NODE>& a2,
664 CREEPAGE_GRAPH& aG ) const override;
665
666 void ShortenChildDueToGV( std::shared_ptr<GRAPH_NODE>& a1, std::shared_ptr<GRAPH_NODE>& a2,
667 CREEPAGE_GRAPH& aG, double aNormalWeight ) const;
668
669
670protected:
672};
673
679{
680public:
681 BE_SHAPE_ARC( VECTOR2I aPos, int aRadius, EDA_ANGLE aStartAngle, EDA_ANGLE aEndAngle,
682 VECTOR2D aStartPoint, VECTOR2D aEndPoint ) :
683 BE_SHAPE_CIRCLE( aPos, aRadius ),
684 m_startAngle( aStartAngle ), m_endAngle( aEndAngle ),
685 m_startPoint( aStartPoint ), m_endPoint( aEndPoint )
686 {
687 m_type = CREEP_SHAPE::TYPE::ARC;
688 }
689
690 void ConnectChildren( std::shared_ptr<GRAPH_NODE>& a1, std::shared_ptr<GRAPH_NODE>& a2,
691 CREEPAGE_GRAPH& aG ) const override;
692
693
694 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
695 double aMaxSquaredWeight ) const override
696 {
697 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
698 };
699 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
700 double aMaxSquaredWeight ) const override
701 {
702 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
703 };
704 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
705 double aMaxSquaredWeight ) const override;
706
707 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
708 double aMaxSquaredWeight ) const override
709 {
710 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
711 };
712 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
713 double aMaxSquaredWeight ) const override
714 {
715 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
716 };
717 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_ARC& aS2, double aMaxWeight,
718 double aMaxSquaredWeight ) const override
719 {
720 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
721 };
722
723 EDA_ANGLE GetStartAngle() const override { return m_startAngle; }
724 EDA_ANGLE GetEndAngle() const override { return m_endAngle; }
725 int GetRadius() const override { return m_radius; }
726
727 VECTOR2I GetStartPoint() const override { return m_startPoint; }
728 VECTOR2I GetEndPoint() const override { return m_endPoint; }
730 {
731 EDA_ANGLE angle( aPoint - m_pos );
732
733 while( angle < m_startAngle )
734 angle += ANGLE_360;
735 while( angle > m_endAngle + ANGLE_360 )
736 angle -= ANGLE_360;
737
738 return angle;
739 }
740
741 std::pair<bool, bool> IsThereATangentPassingThroughPoint( const BE_SHAPE_POINT aPoint ) const;
742
743protected:
748};
749
750
756{
757public:
759 m_board( aBoard )
760 {
761 m_boardOutline = nullptr;
763 m_creepageTarget = -1;
765 };
766
768 {
769 for( CREEP_SHAPE* cs : m_shapeCollection )
770 {
771 if( cs )
772 {
773 delete cs;
774 cs = nullptr;
775 }
776 }
777
778 // Clear out the circular shared pointer references
779 for( std::shared_ptr<GRAPH_NODE>& n : m_nodes )
780 {
781 if( n )
782 {
783 n->m_node_conns.clear();
784 n = nullptr;
785 }
786 }
787
788 for( std::shared_ptr<GRAPH_CONNECTION>& c : m_connections )
789 {
790 if( c )
791 c = nullptr;
792 }
793 };
794
796 void TransformCreepShapesToNodes(std::vector<CREEP_SHAPE*>& aShapes);
798
799 // Add a node to the graph. If an equivalent node exists, returns the pointer of the existing node instead
800 std::shared_ptr<GRAPH_NODE> AddNode( GRAPH_NODE::TYPE aType, CREEP_SHAPE* aParent = nullptr,
801 const VECTOR2I& aPos = VECTOR2I() );
802
803 std::shared_ptr<GRAPH_NODE> AddNodeVirtual();
804
805 std::shared_ptr<GRAPH_CONNECTION> AddConnection( std::shared_ptr<GRAPH_NODE>& aN1,
806 std::shared_ptr<GRAPH_NODE>& aN2,
807 const PATH_CONNECTION& aPc );
808
809 std::shared_ptr<GRAPH_CONNECTION> AddConnection( std::shared_ptr<GRAPH_NODE>& aN1,
810 std::shared_ptr<GRAPH_NODE>& aN2 );
811
812 std::shared_ptr<GRAPH_NODE> FindNode( GRAPH_NODE::TYPE aType, CREEP_SHAPE* aParent,
813 const VECTOR2I& aPos );
814
815 void RemoveConnection( const std::shared_ptr<GRAPH_CONNECTION>&, bool aDelete = false );
816
817 void Trim( double aWeightLimit );
818
819 void Addshape( const SHAPE& aShape, std::shared_ptr<GRAPH_NODE>& aConnectTo,
820 BOARD_ITEM* aParent = nullptr );
821
822 double Solve( std::shared_ptr<GRAPH_NODE>& aFrom, std::shared_ptr<GRAPH_NODE>& aTo,
823 std::vector<std::shared_ptr<GRAPH_CONNECTION>>& aResult );
824
825 void GeneratePaths( double aMaxWeight, PCB_LAYER_ID aLayer );
826
827 std::shared_ptr<GRAPH_NODE> AddNetElements( int aNetCode, PCB_LAYER_ID aLayer, int aMaxCreepage );
828
829 void SetTarget( double aTarget );
830 double GetTarget() { return m_creepageTarget; };
831
833 {
834 std::size_t operator()(const std::shared_ptr<GRAPH_NODE>& node) const
835 {
836 return hash_val(node->m_type, node->m_parent, node->m_pos.x, node->m_pos.y);
837 }
838 };
839
841 {
842 bool operator()(const std::shared_ptr<GRAPH_NODE>& lhs, const std::shared_ptr<GRAPH_NODE>& rhs) const
843 {
844 return lhs->m_type == rhs->m_type && lhs->m_parent == rhs->m_parent && lhs->m_pos == rhs->m_pos;
845 }
846 };
847
848public:
850 std::vector<BOARD_ITEM*> m_boardEdge;
852 std::vector<std::shared_ptr<GRAPH_NODE>> m_nodes;
853 std::vector<std::shared_ptr<GRAPH_CONNECTION>> m_connections;
854 std::vector<CREEP_SHAPE*> m_shapeCollection;
855
856 // This is a duplicate of m_nodes, but it is used to quickly find a node rather than iterating through m_nodes
857 std::unordered_set<std::shared_ptr<GRAPH_NODE>, GraphNodeHash, GraphNodeEqual> m_nodeset;
858
860
861private:
864};
865
Creepage: a board edge arc.
std::pair< bool, bool > IsThereATangentPassingThroughPoint(const BE_SHAPE_POINT aPoint) const
EDA_ANGLE GetStartAngle() const override
int GetRadius() const override
BE_SHAPE_ARC(VECTOR2I aPos, int aRadius, EDA_ANGLE aStartAngle, EDA_ANGLE aEndAngle, VECTOR2D aStartPoint, VECTOR2D aEndPoint)
std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_ARC &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
VECTOR2I GetStartPoint() const override
std::vector< PATH_CONNECTION > Paths(const BE_SHAPE_POINT &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
void ConnectChildren(std::shared_ptr< GRAPH_NODE > &a1, std::shared_ptr< GRAPH_NODE > &a2, CREEPAGE_GRAPH &aG) const override
EDA_ANGLE GetEndAngle() const override
std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_SEGMENT &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
std::vector< PATH_CONNECTION > Paths(const BE_SHAPE_CIRCLE &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_CIRCLE &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
VECTOR2I GetEndPoint() const override
EDA_ANGLE AngleBetweenStartAndEnd(const VECTOR2I aPoint) const
Creepage: a board edge circle.
int GetRadius() const override
BE_SHAPE_CIRCLE(VECTOR2I aPos=VECTOR2I(0, 0), int aRadius=0)
void ShortenChildDueToGV(std::shared_ptr< GRAPH_NODE > &a1, std::shared_ptr< GRAPH_NODE > &a2, CREEPAGE_GRAPH &aG, double aNormalWeight) const
std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_CIRCLE &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_SEGMENT &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
std::vector< PATH_CONNECTION > Paths(const BE_SHAPE_POINT &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
void ConnectChildren(std::shared_ptr< GRAPH_NODE > &a1, std::shared_ptr< GRAPH_NODE > &a2, CREEPAGE_GRAPH &aG) const override
Creepage: a board edge point.
BE_SHAPE_POINT(VECTOR2I aPos)
void ConnectChildren(std::shared_ptr< GRAPH_NODE > &a1, std::shared_ptr< GRAPH_NODE > &a2, CREEPAGE_GRAPH &aG) const override
std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_ARC &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_SEGMENT &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
std::vector< PATH_CONNECTION > Paths(const BE_SHAPE_POINT &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_CIRCLE &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
Creepage: a board edge shape.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:83
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
const TRACKS & Tracks() const
Definition board.h:361
A graph with nodes and connections for creepage calculation.
std::shared_ptr< GRAPH_NODE > AddNode(GRAPH_NODE::TYPE aType, CREEP_SHAPE *aParent=nullptr, const VECTOR2I &aPos=VECTOR2I())
std::shared_ptr< GRAPH_CONNECTION > AddConnection(std::shared_ptr< GRAPH_NODE > &aN1, std::shared_ptr< GRAPH_NODE > &aN2, const PATH_CONNECTION &aPc)
void SetTarget(double aTarget)
double Solve(std::shared_ptr< GRAPH_NODE > &aFrom, std::shared_ptr< GRAPH_NODE > &aTo, std::vector< std::shared_ptr< GRAPH_CONNECTION > > &aResult)
void Addshape(const SHAPE &aShape, std::shared_ptr< GRAPH_NODE > &aConnectTo, BOARD_ITEM *aParent=nullptr)
std::vector< CREEP_SHAPE * > m_shapeCollection
CREEPAGE_GRAPH(BOARD &aBoard)
std::shared_ptr< GRAPH_NODE > AddNodeVirtual()
void TransformCreepShapesToNodes(std::vector< CREEP_SHAPE * > &aShapes)
void Trim(double aWeightLimit)
SHAPE_POLY_SET * m_boardOutline
std::vector< BOARD_ITEM * > m_boardEdge
std::unordered_set< std::shared_ptr< GRAPH_NODE >, GraphNodeHash, GraphNodeEqual > m_nodeset
void GeneratePaths(double aMaxWeight, PCB_LAYER_ID aLayer)
std::vector< std::shared_ptr< GRAPH_NODE > > m_nodes
std::vector< std::shared_ptr< GRAPH_CONNECTION > > m_connections
std::shared_ptr< GRAPH_NODE > AddNetElements(int aNetCode, PCB_LAYER_ID aLayer, int aMaxCreepage)
void RemoveConnection(const std::shared_ptr< GRAPH_CONNECTION > &, bool aDelete=false)
std::shared_ptr< GRAPH_NODE > FindNode(GRAPH_NODE::TYPE aType, CREEP_SHAPE *aParent, const VECTOR2I &aPos)
A class used to represent the shapes for creepage calculation.
VECTOR2I GetPos() const
virtual VECTOR2I GetStartPoint() const
virtual std::vector< PATH_CONNECTION > Paths(const BE_SHAPE_POINT &aS2, double aMaxWeight, double aMaxSquaredWeight) const
virtual std::vector< PATH_CONNECTION > Paths(const BE_SHAPE_ARC &aS2, double aMaxWeight, double aMaxSquaredWeight) const
CREEP_SHAPE::TYPE GetType() const
std::vector< PATH_CONNECTION > Paths(const CREEP_SHAPE &aS2, double aMaxWeight, double aMaxSquaredWeight) const
virtual EDA_ANGLE GetEndAngle() const
void SetParent(BOARD_ITEM *aParent)
CREEP_SHAPE::TYPE m_type
virtual std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_ARC &aS2, double aMaxWeight, double aMaxSquaredWeight) const
virtual std::vector< PATH_CONNECTION > Paths(const BE_SHAPE_CIRCLE &aS2, double aMaxWeight, double aMaxSquaredWeight) const
virtual ~CREEP_SHAPE()
virtual int GetRadius() const
const BOARD_ITEM * GetParent() const
virtual void ConnectChildren(std::shared_ptr< GRAPH_NODE > &a1, std::shared_ptr< GRAPH_NODE > &a2, CREEPAGE_GRAPH &aG) const
BOARD_ITEM * m_parent
virtual std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_CIRCLE &aS2, double aMaxWeight, double aMaxSquaredWeight) const
virtual EDA_ANGLE GetStartAngle() const
virtual VECTOR2I GetEndPoint() const
virtual std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_SEGMENT &aS2, double aMaxWeight, double aMaxSquaredWeight) const
std::vector< PATH_CONNECTION > ReversePaths(const std::vector< PATH_CONNECTION > &aV) const
Creepage: a conductive arc.
VECTOR2I GetStartPoint() const override
void SetWidth(double aW)
EDA_ANGLE AngleBetweenStartAndEnd(const VECTOR2I aPoint) const
VECTOR2I GetEndPoint() const override
std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_CIRCLE &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
EDA_ANGLE GetStartAngle() const override
double GetWidth() const
CU_SHAPE_ARC(VECTOR2I aPos, double aRadius, EDA_ANGLE aStartAngle, EDA_ANGLE aEndAngle, VECTOR2D aStartPoint, VECTOR2D aEndPoint)
int GetRadius() const override
EDA_ANGLE GetEndAngle() const override
std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_SEGMENT &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
std::vector< PATH_CONNECTION > Paths(const BE_SHAPE_POINT &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
Creepage: a conductive circle.
int GetRadius() const override
std::vector< PATH_CONNECTION > Paths(const CU_SHAPE_SEGMENT &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
VECTOR2I GetPos() const
CU_SHAPE_CIRCLE(VECTOR2I aPos, double aRadius=0)
std::vector< PATH_CONNECTION > Paths(const BE_SHAPE_POINT &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
Creepage: a conductive segment.
std::vector< PATH_CONNECTION > Paths(const BE_SHAPE_POINT &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
VECTOR2I GetStart() const
double GetWidth() const
VECTOR2I GetEnd() const
CU_SHAPE_SEGMENT(VECTOR2I aStart, VECTOR2I aEnd, double aWidth=0)
Creepage: a conductive shape.
a connection in a
std::shared_ptr< GRAPH_NODE > n2
PATH_CONNECTION m_path
void GetShapes(std::vector< PCB_SHAPE > &aShapes)
std::shared_ptr< GRAPH_NODE > n1
GRAPH_CONNECTION(std::shared_ptr< GRAPH_NODE > &aN1, std::shared_ptr< GRAPH_NODE > &aN2, const PATH_CONNECTION &aPc)
CREEP_SHAPE * m_parent
std::set< std::shared_ptr< GRAPH_CONNECTION > > m_node_conns
GRAPH_NODE(GRAPH_NODE::TYPE aType, CREEP_SHAPE *aParent, const VECTOR2I &aPos=VECTOR2I())
GRAPH_NODE::TYPE m_type
Definition seg.h:42
bool Intersects(const SEG &aSeg) const
Definition seg.cpp:440
Represent a set of closed polygons.
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
bool PointOnEdge(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of some of the outlines or holes.
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
An abstract shape on 2D plane.
Definition shape.h:126
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
Definition vector2d.h:307
The common library.
@ ROUND_ALL_CORNERS
All angles are rounded.
bool SegmentIntersectsBoard(const VECTOR2I &aP1, const VECTOR2I &aP2, const std::vector< BOARD_ITEM * > &aBe, const std::vector< const BOARD_ITEM * > &aDontTestAgainst, int aMinGrooveWidth)
RTree< CREEPAGE_TRACK_ENTRY *, int, 2, double > TRACK_RTREE
static constexpr EDA_ANGLE ANGLE_360
Definition eda_angle.h:417
static constexpr std::size_t hash_val(const Types &... args)
Definition hash.h:51
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ Edge_Cuts
Definition layer_ids.h:112
This file contains miscellaneous commonly used macros and functions.
@ SH_SEGMENT
line segment
Definition shape.h:48
bool operator()(const std::shared_ptr< GRAPH_NODE > &lhs, const std::shared_ptr< GRAPH_NODE > &rhs) const
std::size_t operator()(const std::shared_ptr< GRAPH_NODE > &node) const
SEG segment
PCB_LAYER_ID layer
bool isValid(const BOARD &aBoard, PCB_LAYER_ID aLayer, const std::vector< BOARD_ITEM * > &aBoardEdges, const std::vector< const BOARD_ITEM * > &aIgnoreForTest, SHAPE_POLY_SET *aOutline, const std::pair< bool, bool > &aTestLocalConcavity, int aMinGrooveWidth, TRACK_RTREE *aTrackIndex=nullptr) const
Test if a path is valid.
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition typeinfo.h:96
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694