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 <memory>
27#include <unordered_set>
28
29#include <common.h>
30#include <macros.h>
32#include <footprint.h>
33#include <pad.h>
34#include <pcb_track.h>
35#include <pcb_shape.h>
36#include <zone.h>
37#include <advanced_config.h>
38#include <geometry/shape_rect.h>
39#include <geometry/seg.h>
41#include <drc/drc_item.h>
42#include <drc/drc_rule.h>
43#include <board.h>
44
45
47#include <geometry/rtree.h>
48
49
50// Simple wrapper for track segment data in the RTree
56
57using TRACK_RTREE = RTree<CREEPAGE_TRACK_ENTRY*, int, 2, double>;
58
59extern bool SegmentIntersectsBoard( const VECTOR2I& aP1, const VECTOR2I& aP2,
60 const std::vector<BOARD_ITEM*>& aBe,
61 const std::vector<const BOARD_ITEM*>& aDontTestAgainst,
62 int aMinGrooveWidth );
63
64
66{
69 double weight = -1;
70 bool m_show = true;
71
74
75
89 bool isValid( const BOARD& aBoard, PCB_LAYER_ID aLayer,
90 const std::vector<BOARD_ITEM*>& aBoardEdges,
91 const std::vector<const BOARD_ITEM*>& aIgnoreForTest, SHAPE_POLY_SET* aOutline,
92 const std::pair<bool, bool>& aTestLocalConcavity, int aMinGrooveWidth,
93 TRACK_RTREE* aTrackIndex = nullptr ) const
94 {
95 if( !aOutline )
96 return true; // We keep the segment if there is a problem
97
98 if( !SegmentIntersectsBoard( a1, a2, aBoardEdges, aIgnoreForTest, aMinGrooveWidth ) )
99 return false;
100
101 // The mid point should be inside the board.
102 // Tolerance of 100nm.
103
104 VECTOR2I midPoint = ( a1 + a2 ) / 2;
105 int tolerance = 100;
106
107 bool contained = aOutline->Contains( midPoint, -1, tolerance )
108 || aOutline->PointOnEdge( midPoint, tolerance );
109
110 if( !contained )
111 return false;
112
113 if( false && ( aTestLocalConcavity.first || aTestLocalConcavity.second ) )
114 {
115 // Test for local concavity. If it is localy convex, then it will not be a path of interest.
116
117 double extendLine = 1000; // extend line by 1000nm
118 // In some cases, the projected point could be on the board edge
119 // In such cases, we wan to keep the line.
120 // We inflate the polygon to get a small margin for computation/rounding error.
121 // We might keep some unnecessary lines, but it's better than loosing the important ones.
122 double extendPoly = 100; // extend polygon by 10 nm
123
124 VECTOR2D a( double( a1.x ), double( a1.y ) );
125 VECTOR2D b( double( a2.x ), double( a2.y ) );
126
127 VECTOR2D dir( b - a );
128 dir = dir * ( extendLine / dir.SquaredEuclideanNorm() );
129
130 SHAPE_POLY_SET outline2 = *aOutline;
131 outline2.Inflate( extendPoly, CORNER_STRATEGY::ROUND_ALL_CORNERS, 3 );
132
133 if( aTestLocalConcavity.first && !aOutline->Contains( a - dir, -1, 0 ) )
134 return false;
135
136 if( aTestLocalConcavity.second && !aOutline->Contains( b + dir, -1, 0 ) )
137 return false;
138 }
139
140 if( aLayer != Edge_Cuts )
141 {
142 SEG segPath( a1, a2 );
143
144 // Prefer RTree search if available
145 if( aTrackIndex )
146 {
147 // Calculate bounding box of the path segment
148 int minX = std::min( (int) a1.x, (int) a2.x );
149 int minY = std::min( (int) a1.y, (int) a2.y );
150 int maxX = std::max( (int) a1.x, (int) a2.x );
151 int maxY = std::max( (int) a1.y, (int) a2.y );
152
153 int searchMin[2] = { minX, minY };
154 int searchMax[2] = { maxX, maxY };
155
156 bool intersects = false;
157
158 aTrackIndex->Search( searchMin, searchMax,
159 [&]( CREEPAGE_TRACK_ENTRY* entry ) -> bool
160 {
161 if( entry && entry->layer == aLayer )
162 {
163 if( segPath.Intersects( entry->segment ) )
164 {
165 intersects = true;
166 return false; // Stop searching
167 }
168 }
169 return true; // Continue searching
170 } );
171
172 if( intersects )
173 return false;
174 }
175 else
176 {
177 // Fallback to linear search if no index provided
178 for( PCB_TRACK* track : aBoard.Tracks() )
179 {
180 if( !track )
181 continue;
182
183 if( track->Type() == KICAD_T::PCB_TRACE_T && track->IsOnLayer( aLayer ) )
184 {
185 std::shared_ptr<SHAPE> sh = track->GetEffectiveShape();
186
187 if( sh && sh->Type() == SHAPE_TYPE::SH_SEGMENT )
188 {
189 SEG segTrack( track->GetStart(), track->GetEnd() );
190
191 if( segPath.Intersects( segTrack ) )
192 return false;
193 }
194 }
195 }
196 }
197 }
198 return true;
199 }
200};
201
202
203class GRAPH_CONNECTION;
204class GRAPH_NODE;
205class CREEPAGE_GRAPH;
206class CREEP_SHAPE;
207class BE_SHAPE;
208class BE_SHAPE_POINT;
209class BE_SHAPE_ARC;
210class BE_SHAPE_CIRCLE;
211class CU_SHAPE;
212class CU_SHAPE_SEGMENT;
213class CU_SHAPE_CIRCLE;
214class CU_SHAPE_ARC;
215
221{
222public:
223 enum class TYPE
224 {
229 };
230
232 {
233 m_conductive = false;
234 m_parent = nullptr;
235 m_pos = VECTOR2I( 0, 0 );
236 m_type = CREEP_SHAPE::TYPE::UNDEFINED;
237 };
238
239 virtual ~CREEP_SHAPE() {}
240
241 virtual int GetRadius() const { return 0; };
242 virtual EDA_ANGLE GetStartAngle() const { return EDA_ANGLE( 0 ); };
243 virtual EDA_ANGLE GetEndAngle() const { return EDA_ANGLE( 0 ); };
244 virtual VECTOR2I GetStartPoint() const { return VECTOR2I( 0, 0 ); };
245 virtual VECTOR2I GetEndPoint() const { return VECTOR2I( 0, 0 ); };
246 VECTOR2I GetPos() const { return m_pos; };
247 CREEP_SHAPE::TYPE GetType() const { return m_type; };
248 const BOARD_ITEM* GetParent() const { return m_parent; };
249 void SetParent( BOARD_ITEM* aParent ) { m_parent = aParent; };
250
251 virtual void ConnectChildren( std::shared_ptr<GRAPH_NODE>& a1, std::shared_ptr<GRAPH_NODE>& a2,
252 CREEPAGE_GRAPH& aG ) const;
253
254 std::vector<PATH_CONNECTION> ReversePaths( const std::vector<PATH_CONNECTION>& aV ) const
255 {
256 std::vector<PATH_CONNECTION> r;
257 r.reserve( aV.size() );
258
259 for( const auto& pc : aV )
260 {
261 r.emplace_back( pc );
262 std::swap( r.back().a1, r.back().a2 );
263 }
264
265 return r;
266 }
267
268 std::vector<PATH_CONNECTION> Paths( const CREEP_SHAPE& aS2, double aMaxWeight,
269 double aMaxSquaredWeight ) const
270 {
271 std::vector<PATH_CONNECTION> a;
272 return a;
273 };
274
275 virtual std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
276 double aMaxSquaredWeight ) const
277 {
278 std::vector<PATH_CONNECTION> a;
279 return a;
280 };
281
282 virtual std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
283 double aMaxSquaredWeight ) const
284 {
285 std::vector<PATH_CONNECTION> a;
286 return a;
287 };
288
289 virtual std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
290 double aMaxSquaredWeight ) const
291 {
292 std::vector<PATH_CONNECTION> a;
293 return a;
294 };
295
296 virtual std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
297 double aMaxSquaredWeight ) const
298 {
299 std::vector<PATH_CONNECTION> a;
300 return a;
301 };
302
303 virtual std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
304 double aMaxSquaredWeight ) const
305 {
306 std::vector<PATH_CONNECTION> a;
307 return a;
308 };
309
310 virtual std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_ARC& aS2, double aMaxWeight,
311 double aMaxSquaredWeight ) const
312 {
313 std::vector<PATH_CONNECTION> a;
314 return a;
315 };
316
317 //virtual std::vector<PATH_CONNECTION> GetPathsCuToBe( CREEP_SHAPE* aShape ) const{ std::vector<PATH_CONNECTION> a; return a;};
318 bool IsConductive() { return m_conductive; };
319
320protected:
325};
326
327
332class CU_SHAPE : public CREEP_SHAPE
333{
334public:
337 {
338 m_conductive = true;
339 };
340};
341
346class BE_SHAPE : public CREEP_SHAPE
347{
348public:
351 {
352 m_conductive = false;
353 };
354};
355
361{
362public:
363 CU_SHAPE_SEGMENT( VECTOR2I aStart, VECTOR2I aEnd, double aWidth = 0 ) :
364 CU_SHAPE()
365 {
366 m_start = aStart;
367 m_end = aEnd;
368 m_width = aWidth;
369 m_pos = ( aStart + aEnd ) / 2;
370 }
371
372 VECTOR2I GetStart() const { return m_start; };
373 VECTOR2I GetEnd() const { return m_end; };
374 double GetWidth() const { return m_width; };
375
376 int GetRadius() const override
377 {
378 return (int) ( ( m_start - m_end ).EuclideanNorm() / 2 ) + (int) ( m_width / 2 );
379 };
380
381 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
382 double aMaxSquaredWeight ) const override;
383 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
384 double aMaxSquaredWeight ) const override;
385 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
386 double aMaxSquaredWeight ) const override;
387 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
388 double aMaxSquaredWeight ) const override;
389 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
390 double aMaxSquaredWeight ) const override;
391 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_ARC& aS2, double aMaxWeight,
392 double aMaxSquaredWeight ) const override;
393
394
395private:
398 double m_width = 0;
399};
400
406{
407public:
408 CU_SHAPE_CIRCLE( VECTOR2I aPos, double aRadius = 0 ) :
409 CU_SHAPE()
410 {
411 m_pos = aPos;
412 m_radius = aRadius;
413 }
414
415 VECTOR2I GetPos() const { return m_pos; };
416 int GetRadius() const override { return m_radius; };
417
418 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
419 double aMaxSquaredWeight ) const override;
420 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
421 double aMaxSquaredWeight ) const override;
422 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
423 double aMaxSquaredWeight ) const override;
424 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
425 double aMaxSquaredWeight ) const override
426 {
427 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
428 };
429
430 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
431 double aMaxSquaredWeight ) const override;
432 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_ARC& aS2, double aMaxWeight,
433 double aMaxSquaredWeight ) const override;
434
435protected:
437 double m_radius = 1;
438};
439
445{
446public:
447 CU_SHAPE_ARC( VECTOR2I aPos, double aRadius, EDA_ANGLE aStartAngle, EDA_ANGLE aEndAngle,
448 VECTOR2D aStartPoint, VECTOR2D aEndPoint ) :
449 CU_SHAPE_CIRCLE( aPos, aRadius ),
450 m_startAngle( aStartAngle ),
451 m_endAngle( aEndAngle ),
452 m_startPoint( aStartPoint ),
453 m_endPoint( aEndPoint )
454 {
455 m_type = CREEP_SHAPE::TYPE::ARC;
456 m_width = 0;
457 }
458
459 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
460 double aMaxSquaredWeight ) const override;
461
462 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
463 double aMaxSquaredWeight ) const override;
464
465 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
466 double aMaxSquaredWeight ) const override;
467
468 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
469 double aMaxSquaredWeight ) const override
470 {
471 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
472 };
473
474 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
475 double aMaxSquaredWeight ) const override
476 {
477 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
478 };
479
480 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_ARC& aS2, double aMaxWeight,
481 double aMaxSquaredWeight ) const override;
482
483 EDA_ANGLE GetStartAngle() const override { return m_startAngle; }
484 EDA_ANGLE GetEndAngle() const override { return m_endAngle; }
485 int GetRadius() const override { return m_radius; }
486
487 VECTOR2I GetStartPoint() const override { return m_startPoint; }
488 VECTOR2I GetEndPoint() const override { return m_endPoint; }
489
491 {
492 EDA_ANGLE angle( aPoint - m_pos );
493
494 while( angle < GetStartAngle() )
495 angle += ANGLE_360;
496
497 while( angle > GetEndAngle() + ANGLE_360 )
498 angle -= ANGLE_360;
499
500 return angle;
501 }
502
503 double GetWidth() const { return m_width; };
504 void SetWidth( double aW ) { m_width = aW; };
505
506private:
512};
513
519{
520public:
529
530 GRAPH_NODE( GRAPH_NODE::TYPE aType, CREEP_SHAPE* aParent, const VECTOR2I& aPos = VECTOR2I() ) :
531 m_parent( aParent ),
532 m_pos( aPos ),
533 m_type( aType )
534 {
535 m_node_conns = {};
536 m_virtual = false;
537 m_connectDirectly = true;
538 m_net = -1;
539 };
540
542
543public:
545 std::set<std::shared_ptr<GRAPH_CONNECTION>> m_node_conns;
547
548 // Virtual nodes are connected with a 0 weight connection to equivalent net ( same net or netclass )
551 int m_net;
552
554};
555
561{
562public:
563 GRAPH_CONNECTION( std::shared_ptr<GRAPH_NODE>& aN1, std::shared_ptr<GRAPH_NODE>& aN2,
564 const PATH_CONNECTION& aPc ) :
565 n1( aN1 ),
566 n2( aN2 )
567 {
568 m_path = aPc;
569 m_forceStraightLine = false;
570 };
571
572 void GetShapes( std::vector<PCB_SHAPE>& aShapes );
573
574public:
575 std::shared_ptr<GRAPH_NODE> n1;
576 std::shared_ptr<GRAPH_NODE> n2;
579};
580
581
587{
588public:
590 BE_SHAPE()
591 {
592 m_pos = aPos;
593 m_type = CREEP_SHAPE::TYPE::POINT;
594 }
595
596 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
597 double aMaxSquaredWeight ) const override;
598
599 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
600 double aMaxSquaredWeight ) const override;
601
602 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
603 double aMaxSquaredWeight ) const override;
604
605 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
606 double aMaxSquaredWeight ) const override
607 {
608 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
609 };
610
611 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
612 double aMaxSquaredWeight ) const override
613 {
614 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
615 }
616
617 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_ARC& aS2, double aMaxWeight,
618 double aMaxSquaredWeight ) const override
619 {
620 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
621 };
622
623
624 void ConnectChildren( std::shared_ptr<GRAPH_NODE>& a1, std::shared_ptr<GRAPH_NODE>& a2,
625 CREEPAGE_GRAPH& aG ) const override;
626};
627
633{
634public:
635 BE_SHAPE_CIRCLE( VECTOR2I aPos = VECTOR2I( 0, 0 ), int aRadius = 0 ) :
636 BE_SHAPE()
637 {
638 m_pos = aPos;
639 m_radius = aRadius;
640 m_type = CREEP_SHAPE::TYPE::CIRCLE;
641 }
642
643 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
644 double aMaxSquaredWeight ) const override
645 {
646 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
647 };
648
649 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
650 double aMaxSquaredWeight ) const override;
651
652 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
653 double aMaxSquaredWeight ) const override;
654
655 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
656 double aMaxSquaredWeight ) const override
657 {
658 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
659 };
660
661 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
662 double aMaxSquaredWeight ) const override
663 {
664 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
665 };
666
667
668 int GetRadius() const override { return m_radius; }
669
670 void ConnectChildren( std::shared_ptr<GRAPH_NODE>& a1, std::shared_ptr<GRAPH_NODE>& a2,
671 CREEPAGE_GRAPH& aG ) const override;
672
673 void ShortenChildDueToGV( std::shared_ptr<GRAPH_NODE>& a1, std::shared_ptr<GRAPH_NODE>& a2,
674 CREEPAGE_GRAPH& aG, double aNormalWeight ) const;
675
676
677protected:
679};
680
686{
687public:
688 BE_SHAPE_ARC( VECTOR2I aPos, int aRadius, EDA_ANGLE aStartAngle, EDA_ANGLE aEndAngle,
689 VECTOR2D aStartPoint, VECTOR2D aEndPoint ) :
690 BE_SHAPE_CIRCLE( aPos, aRadius ),
691 m_startAngle( aStartAngle ), m_endAngle( aEndAngle ),
692 m_startPoint( aStartPoint ), m_endPoint( aEndPoint )
693 {
694 m_type = CREEP_SHAPE::TYPE::ARC;
695 }
696
697 void ConnectChildren( std::shared_ptr<GRAPH_NODE>& a1, std::shared_ptr<GRAPH_NODE>& a2,
698 CREEPAGE_GRAPH& aG ) const override;
699
700
701 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_POINT& aS2, double aMaxWeight,
702 double aMaxSquaredWeight ) const override
703 {
704 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
705 };
706 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_CIRCLE& aS2, double aMaxWeight,
707 double aMaxSquaredWeight ) const override
708 {
709 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
710 };
711 std::vector<PATH_CONNECTION> Paths( const BE_SHAPE_ARC& aS2, double aMaxWeight,
712 double aMaxSquaredWeight ) const override;
713
714 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_SEGMENT& aS2, double aMaxWeight,
715 double aMaxSquaredWeight ) const override
716 {
717 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
718 };
719 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_CIRCLE& aS2, double aMaxWeight,
720 double aMaxSquaredWeight ) const override
721 {
722 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
723 };
724 std::vector<PATH_CONNECTION> Paths( const CU_SHAPE_ARC& aS2, double aMaxWeight,
725 double aMaxSquaredWeight ) const override
726 {
727 return ReversePaths( aS2.Paths( *this, aMaxWeight, aMaxSquaredWeight ) );
728 };
729
730 EDA_ANGLE GetStartAngle() const override { return m_startAngle; }
731 EDA_ANGLE GetEndAngle() const override { return m_endAngle; }
732 int GetRadius() const override { return m_radius; }
733
734 VECTOR2I GetStartPoint() const override { return m_startPoint; }
735 VECTOR2I GetEndPoint() const override { return m_endPoint; }
737 {
738 EDA_ANGLE angle( aPoint - m_pos );
739
740 while( angle < m_startAngle )
741 angle += ANGLE_360;
742 while( angle > m_endAngle + ANGLE_360 )
743 angle -= ANGLE_360;
744
745 return angle;
746 }
747
748 std::pair<bool, bool> IsThereATangentPassingThroughPoint( const BE_SHAPE_POINT aPoint ) const;
749
750protected:
755};
756
757
763{
764public:
766 m_board( aBoard )
767 {
768 m_boardOutline = nullptr;
770 m_creepageTarget = -1;
772 };
773
775 {
776 for( CREEP_SHAPE* cs : m_shapeCollection )
777 {
778 if( cs )
779 {
780 delete cs;
781 cs = nullptr;
782 }
783 }
784
785 // Clear out the circular shared pointer references
786 for( std::shared_ptr<GRAPH_NODE>& n : m_nodes )
787 {
788 if( n )
789 {
790 n->m_node_conns.clear();
791 n = nullptr;
792 }
793 }
794
795 for( std::shared_ptr<GRAPH_CONNECTION>& c : m_connections )
796 {
797 if( c )
798 c = nullptr;
799 }
800 };
801
803 void TransformCreepShapesToNodes(std::vector<CREEP_SHAPE*>& aShapes);
805
806 // Add a node to the graph. If an equivalent node exists, returns the pointer of the existing node instead
807 std::shared_ptr<GRAPH_NODE> AddNode( GRAPH_NODE::TYPE aType, CREEP_SHAPE* aParent = nullptr,
808 const VECTOR2I& aPos = VECTOR2I() );
809
810 std::shared_ptr<GRAPH_NODE> AddNodeVirtual();
811
812 std::shared_ptr<GRAPH_CONNECTION> AddConnection( std::shared_ptr<GRAPH_NODE>& aN1,
813 std::shared_ptr<GRAPH_NODE>& aN2,
814 const PATH_CONNECTION& aPc );
815
816 std::shared_ptr<GRAPH_CONNECTION> AddConnection( std::shared_ptr<GRAPH_NODE>& aN1,
817 std::shared_ptr<GRAPH_NODE>& aN2 );
818
819 std::shared_ptr<GRAPH_NODE> FindNode( GRAPH_NODE::TYPE aType, CREEP_SHAPE* aParent,
820 const VECTOR2I& aPos );
821
822 void RemoveConnection( const std::shared_ptr<GRAPH_CONNECTION>&, bool aDelete = false );
823
824 void Trim( double aWeightLimit );
825
826 void Addshape( const SHAPE& aShape, std::shared_ptr<GRAPH_NODE>& aConnectTo,
827 BOARD_ITEM* aParent = nullptr );
828
829 double Solve( std::shared_ptr<GRAPH_NODE>& aFrom, std::shared_ptr<GRAPH_NODE>& aTo,
830 std::vector<std::shared_ptr<GRAPH_CONNECTION>>& aResult );
831
832 void GeneratePaths( double aMaxWeight, PCB_LAYER_ID aLayer );
833
834 std::shared_ptr<GRAPH_NODE> AddNetElements( int aNetCode, PCB_LAYER_ID aLayer, int aMaxCreepage );
835
836 void SetTarget( double aTarget );
837 double GetTarget() { return m_creepageTarget; };
838
840 {
841 std::size_t operator()(const std::shared_ptr<GRAPH_NODE>& node) const
842 {
843 return hash_val(node->m_type, node->m_parent, node->m_pos.x, node->m_pos.y);
844 }
845 };
846
848 {
849 bool operator()(const std::shared_ptr<GRAPH_NODE>& lhs, const std::shared_ptr<GRAPH_NODE>& rhs) const
850 {
851 return lhs->m_type == rhs->m_type && lhs->m_parent == rhs->m_parent && lhs->m_pos == rhs->m_pos;
852 }
853 };
854
855public:
857 std::vector<BOARD_ITEM*> m_boardEdge;
858 std::vector<std::unique_ptr<PCB_SHAPE>> m_ownedBoardEdges;
860 std::vector<std::shared_ptr<GRAPH_NODE>> m_nodes;
861 std::vector<std::shared_ptr<GRAPH_CONNECTION>> m_connections;
862 std::vector<CREEP_SHAPE*> m_shapeCollection;
863
864 // This is a duplicate of m_nodes, but it is used to quickly find a node rather than iterating through m_nodes
865 std::unordered_set<std::shared_ptr<GRAPH_NODE>, GraphNodeHash, GraphNodeEqual> m_nodeset;
866
868
869private:
872};
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:84
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)
std::vector< std::unique_ptr< PCB_SHAPE > > m_ownedBoardEdges
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
int GetRadius() 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