32 std::vector<VECTOR2I>* aIntersectionPoints =
nullptr )
34 SEG segment( p1, p2 );
44 std::vector<VECTOR2I> rawPoints;
46 std::visit( visitor, geom1 );
50 std::vector<VECTOR2I> filtered;
64 return ( a - b ).SquaredEuclideanNorm() <= toleranceSq;
67 for(
const VECTOR2I& ip : rawPoints )
69 bool atSharedEndpoint = ( coincident( ip, arcStart ) || coincident( ip, arcEnd ) )
70 && ( coincident( ip, p1 ) || coincident( ip, p2 ) );
72 if( !atSharedEndpoint )
73 filtered.push_back( ip );
76 if( aIntersectionPoints )
79 aIntersectionPoints->push_back( ip );
82 return !filtered.empty();
89 std::vector<VECTOR2I>& aIntersectionPoints )
91 if( p1 == p2 || p1 == q2 || q1 == p2 || q1 == q2 )
94 SEG segment1( p1, q1 );
95 SEG segment2( p2, q2 );
100 size_t startCount = aIntersectionPoints.size();
103 std::visit( visitor, geom1 );
105 return aIntersectionPoints.size() > startCount;
120 if( a->
GetType() == CREEP_SHAPE::TYPE::UNDEFINED )
126 if( a->
GetType() == CREEP_SHAPE::TYPE::CIRCLE )
144 if( a->
GetType() == CREEP_SHAPE::TYPE::POINT )
147 if( a->
GetType() == CREEP_SHAPE::TYPE::CIRCLE )
155 double aMaxSquaredWeight )
const
157 std::vector<PATH_CONNECTION>
result;
159 double weight = ( this->
GetPos() - aS2.
GetPos() ).SquaredEuclideanNorm();
161 if( weight > aMaxSquaredWeight )
167 pc.
weight = sqrt( weight );
175 double aMaxSquaredWeight )
const
177 std::vector<PATH_CONNECTION>
result;
185 double pointToCenterDistanceSquared = ( pointPos - circleCenter ).SquaredEuclideanNorm();
186 double weightSquared = pointToCenterDistanceSquared - (float)
radius * (
float)
radius;
188 if( weightSquared > aMaxSquaredWeight )
192 direction1 = direction1.
Resize( 1 );
196 double radiusSquared = double(
radius ) * double(
radius );
198 double distance = sqrt( pointToCenterDistanceSquared );
199 double value1 = radiusSquared /
distance;
200 double value2 = sqrt( radiusSquared - value1 * value1 );
206 pc.
weight = sqrt( weightSquared );
208 resultPoint = direction1 * value1 + direction2 * value2 + circleCenter;
209 pc.
a2.
x = int( resultPoint.
x );
210 pc.
a2.
y = int( resultPoint.
y );
213 resultPoint = direction1 * value1 - direction2 * value2 + circleCenter;
214 pc.
a2.
x = int( resultPoint.
x );
215 pc.
a2.
y = int( resultPoint.
y );
224 std::pair<bool, bool>
result;
241 double pointAngle = testAngle.
AsRadians();
244 bool connectToEndPoint;
246 connectToEndPoint = ( cos( startAngle ) * newPoint.
x + sin( startAngle ) * newPoint.
y >= R );
249 connectToEndPoint &= ( cos( endAngle ) * newPoint.
x + sin( endAngle ) * newPoint.
y <= R );
251 connectToEndPoint |= ( cos( endAngle ) * newPoint.
x + sin( endAngle ) * newPoint.
y <= R )
252 && ( pointAngle >= endAngle || pointAngle <= startAngle );
254 result.first = !connectToEndPoint;
256 connectToEndPoint = ( cos( endAngle ) * newPoint.
x + sin( endAngle ) * newPoint.
y >= R );
259 connectToEndPoint &= ( cos( startAngle ) * newPoint.
x + sin( startAngle ) * newPoint.
y <= R );
261 connectToEndPoint |= ( cos( startAngle ) * newPoint.
x + sin( startAngle ) * newPoint.
y <= R )
262 && ( pointAngle >= endAngle || pointAngle <= startAngle );
264 result.second = !connectToEndPoint;
270 double aMaxSquaredWeight )
const
272 std::vector<PATH_CONNECTION>
result;
278 std::pair<bool, bool> behavesLikeCircle;
281 if( behavesLikeCircle.first && behavesLikeCircle.second )
284 return this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
287 if( behavesLikeCircle.first )
290 std::vector<PATH_CONNECTION> paths = this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
292 if( paths.size() > 1 )
293 result.push_back( paths[1] );
303 if( behavesLikeCircle.second )
306 std::vector<PATH_CONNECTION> paths = this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
308 if( paths.size() > 1 )
309 result.push_back( paths[0] );
323 double aMaxSquaredWeight )
const
325 std::vector<PATH_CONNECTION>
result;
333 double centerDistance = ( circleCenter - arcCenter ).EuclideanNorm();
335 if( centerDistance + arcRadius < circleRadius )
373 double aMaxSquaredWeight )
const
375 std::vector<PATH_CONNECTION>
result;
381 double centerDistance = ( circleCenter - arcCenter ).EuclideanNorm();
383 if( centerDistance + arcRadius < circleRadius )
395 aMaxWeight, aMaxSquaredWeight ) )
404 .
Paths( aS2, aMaxWeight, aMaxSquaredWeight ) )
417 double aMaxSquaredWeight )
const
419 std::vector<PATH_CONNECTION>
result;
424 VECTOR2D distSquared(
double( ( p2 - p1 ).x ),
double( ( p2 - p1 ).y ) );
430 double Rdiff = abs( R1 - R2 );
431 double Rsum = R1 + R2;
434 double weightSquared1 = weightSquared - Rdiff * Rdiff;
436 double weightSquared2 = weightSquared - Rsum * Rsum;
438 if( weightSquared1 <= aMaxSquaredWeight )
441 direction1 = direction1.
Resize( 1 );
444 double D = sqrt( weightSquared );
445 double ratio1 = ( R1 - R2 ) /
D;
446 double ratio2 = sqrt( 1 - ratio1 * ratio1 );
450 pc.
weight = sqrt( weightSquared1 );
452 pc.
a1 = p1 + direction1 * R1 * ratio1 + direction2 * R1 * ratio2;
453 pc.
a2 = p2 + direction1 * R2 * ratio1 + direction2 * R2 * ratio2;
457 pc.
a1 = p1 + direction1 * R1 * ratio1 - direction2 * R1 * ratio2;
458 pc.
a2 = p2 + direction1 * R2 * ratio1 - direction2 * R2 * ratio2;
462 if( weightSquared2 <= aMaxSquaredWeight )
465 direction1 = direction1.
Resize( 1 );
468 double D = sqrt( weightSquared );
469 double ratio1 = ( R1 + R2 ) /
D;
470 double ratio2 = sqrt( 1 - ratio1 * ratio1 );
474 pc.
weight = sqrt( weightSquared2 );
476 pc.
a1 = p1 + direction1 * R1 * ratio1 + direction2 * R1 * ratio2;
477 pc.
a2 = p2 - direction1 * R2 * ratio1 - direction2 * R2 * ratio2;
481 pc.
a1 = p1 + direction1 * R1 * ratio1 - direction2 * R1 * ratio2;
482 pc.
a2 = p2 - direction1 * R2 * ratio1 + direction2 * R2 * ratio2;
498 switch( p1->GetType() )
500 case CREEP_SHAPE::TYPE::POINT:
AddNode( GRAPH_NODE::TYPE::POINT, p1, p1->GetPos() );
break;
501 case CREEP_SHAPE::TYPE::CIRCLE:
AddNode( GRAPH_NODE::TYPE::CIRCLE, p1, p1->GetPos() );
break;
502 case CREEP_SHAPE::TYPE::ARC:
AddNode( GRAPH_NODE::TYPE::ARC, p1, p1->GetPos() );
break;
512 std::vector<CREEP_SHAPE*> newVector;
582 while( endAngle < startAngle )
594 addArc( { x1 + r, y1 + r }, { x1 + r, y1 }, { x1 + r, y2 } );
595 addArc( { x2 - r, y1 + r }, { x2 - r, y2 }, { x2 - r, y1 } );
597 else if( w == 2 * r )
600 addArc( { x1 + r, y1 + r }, { x1, y1 + r }, { x2, y1 + r } );
601 addArc( { x1 + r, y2 - r }, { x2, y2 - r }, { x1, y2 - r } );
606 addArc( { x1 + r, y1 + r }, { x1, y1 + r }, { x1 + r, y1 } );
607 addArc( { x2 - r, y1 + r }, { x2 - r, y1 }, { x2, y1 + r } );
608 addArc( { x2 - r, y2 - r }, { x2, y2 - r }, { x2 - r, y2 } );
609 addArc( { x1 + r, y2 - r }, { x1 + r, y2 }, { x1, y2 - r } );
652 double tolerance = 10;
683 if(
n1->m_type == GRAPH_NODE::TYPE::VIRTUAL ||
n2->m_type == GRAPH_NODE::TYPE::VIRTUAL )
687 &&
n1->m_parent ==
n2->m_parent
688 &&
n1->m_parent->GetType() == CREEP_SHAPE::TYPE::CIRCLE )
695 if( R1.
Cross( R2 ) > 0 )
707 aShapes.push_back( s );
712 &&
n1->m_parent ==
n2->m_parent
713 &&
n1->m_parent->GetType() == CREEP_SHAPE::TYPE::ARC )
722 if( R1.
Cross( R2 ) > 0 )
737 EDA_ANGLE midAngle = arc->AngleBetweenStartAndEnd( mid );
739 if( midAngle > arc->GetEndAngle() )
748 aShapes.push_back( s );
756 aShapes.push_back( s );
787 EDA_ANGLE maxAngle = angle1 > angle2 ? angle1 : angle2;
790 skipAngle += skipAngle;
791 EDA_ANGLE pointAngle = maxAngle - skipAngle;
801 pc.
a1 = maxAngle == angle2 ? a1->m_pos : a2->m_pos;
807 pc.
a2 = maxAngle == angle2 ? a2->m_pos : a1->m_pos;
810 std::shared_ptr<GRAPH_CONNECTION> gc = aG.
AddConnection( gnt, maxAngle == angle2 ? a2 : a1, pc );
813 gc->m_forceStraightLine =
true;
826 VECTOR2D distI( a1->m_pos - a2->m_pos );
827 VECTOR2D distD(
double( distI.
x ),
double( distI.
y ) );
839 pc.
weight = std::max( weight, 0.0 );
860 double weight = abs(
m_radius * ( angle2 - angle1 ).AsRadians() );
889 double aMaxSquaredWeight )
const
891 std::vector<PATH_CONNECTION>
result;
894 double halfWidth = this->
GetWidth() / 2;
898 double length = ( start -
end ).EuclideanNorm();
899 double projectedPos = cos( trackAngle.
AsRadians() ) * ( pointPos.
x - start.
x )
900 + sin( trackAngle.
AsRadians() ) * ( pointPos.
y - start.
y );
904 if( projectedPos <= 0 )
906 newPoint = start + ( pointPos - start ).Resize( halfWidth );
908 else if( projectedPos >= length )
910 newPoint =
end + ( pointPos -
end ).Resize( halfWidth );
914 double posOnSegment = ( start - pointPos ).SquaredEuclideanNorm()
915 - (
end - pointPos ).SquaredEuclideanNorm();
916 posOnSegment = posOnSegment / ( 2 * length ) + length / 2;
918 newPoint = start + (
end - start ).Resize( posOnSegment );
919 newPoint += ( pointPos - newPoint ).Resize( halfWidth );
922 double weightSquared = ( pointPos - newPoint ).SquaredEuclideanNorm();
924 if( weightSquared > aMaxSquaredWeight )
930 pc.
weight = sqrt( weightSquared );
938 double aMaxSquaredWeight )
const
940 std::vector<PATH_CONNECTION>
result;
943 double halfWidth = this->
GetWidth() / 2;
947 double length = ( start -
end ).EuclideanNorm();
950 double weightSquared = std::numeric_limits<double>::infinity();
951 VECTOR2I PointOnTrack, PointOnCircle;
955 double projectedPos1 = cos( trackAngle.
AsRadians() ) * ( circleCenter.
x - start.
x )
956 + sin( trackAngle.
AsRadians() ) * ( circleCenter.
y - start.
y );
957 double projectedPos2 = projectedPos1 + circleRadius;
958 projectedPos1 = projectedPos1 - circleRadius;
960 double trackSide = (
end - start ).Cross( circleCenter - start ) > 0 ? 1 : -1;
962 if( ( projectedPos1 < 0 && projectedPos2 < 0 ) )
970 else if( ( projectedPos1 > length && projectedPos2 > length ) )
978 else if( ( projectedPos1 >= 0 ) && ( projectedPos1 <= length ) && ( projectedPos2 >= 0 )
979 && ( projectedPos2 <= length ) )
982 PointOnTrack = start;
983 PointOnTrack += (
end - start ).Resize( projectedPos1 );
984 PointOnTrack += (
end - start ).Perpendicular().
Resize( halfWidth ) * trackSide;
985 PointOnCircle = circleCenter - (
end - start ).Resize( circleRadius );
986 weightSquared = ( PointOnCircle - PointOnTrack ).SquaredEuclideanNorm();
988 if( weightSquared < aMaxSquaredWeight )
991 pc.
a1 = PointOnTrack;
992 pc.
a2 = PointOnCircle;
993 pc.
weight = sqrt( weightSquared );
997 PointOnTrack = start;
998 PointOnTrack += (
end - start ).Resize( projectedPos2 );
999 PointOnTrack += (
end - start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1000 PointOnCircle = circleCenter + (
end - start ).Resize( circleRadius );
1003 pc.
a1 = PointOnTrack;
1004 pc.
a2 = PointOnCircle;
1009 else if( ( ( projectedPos1 >= 0 ) && ( projectedPos1 <= length ) )
1010 && ( ( projectedPos2 > length ) || projectedPos2 < 0 ) )
1013 std::vector<PATH_CONNECTION> pcs = csc.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1015 if( pcs.size() < 2 )
1018 result.push_back( pcs.at( trackSide == 1 ? 1 : 0 ) );
1021 PointOnTrack = start;
1022 PointOnTrack += (
end - start ).Resize( projectedPos1 );
1023 PointOnTrack += (
end - start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1024 PointOnCircle = circleCenter - (
end - start ).Resize( circleRadius );
1025 weightSquared = ( PointOnCircle - PointOnTrack ).SquaredEuclideanNorm();
1027 if( weightSquared < aMaxSquaredWeight )
1030 pc.
a1 = PointOnTrack;
1031 pc.
a2 = PointOnCircle;
1032 pc.
weight = sqrt( weightSquared );
1037 else if( ( ( projectedPos2 >= 0 ) && ( projectedPos2 <= length ) )
1038 && ( ( projectedPos1 > length ) || projectedPos1 < 0 ) )
1041 std::vector<PATH_CONNECTION> pcs = csc.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1043 if( pcs.size() < 2 )
1046 result.push_back( pcs.at( trackSide == 1 ? 0 : 1 ) );
1048 PointOnTrack = start;
1049 PointOnTrack += (
end - start ).Resize( projectedPos2 );
1050 PointOnTrack += (
end - start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1051 PointOnCircle = circleCenter + (
end - start ).Resize( circleRadius );
1052 weightSquared = ( PointOnCircle - PointOnTrack ).SquaredEuclideanNorm();
1054 if( weightSquared < aMaxSquaredWeight )
1057 pc.
a1 = PointOnTrack;
1058 pc.
a2 = PointOnCircle;
1059 pc.
weight = sqrt( weightSquared );
1070 double aMaxSquaredWeight )
const
1072 std::vector<PATH_CONNECTION>
result;
1096 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1102 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1112 double aMaxSquaredWeight )
const
1114 std::vector<PATH_CONNECTION>
result;
1137 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1143 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1153 double aMaxSquaredWeight )
const
1155 std::vector<PATH_CONNECTION>
result;
1184 double aMaxSquaredWeight )
const
1186 std::vector<PATH_CONNECTION>
result;
1209 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1215 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1225 double aMaxSquaredWeight )
const
1227 std::vector<PATH_CONNECTION>
result;
1232 double weight = (
center - point ).EuclideanNorm() - R;
1234 if( weight > aMaxWeight )
1238 pc.
weight = std::max( weight, 0.0 );
1248 double aMaxSquaredWeight )
const
1250 std::vector<PATH_CONNECTION>
result;
1257 if( ( C1 - C2 ).SquaredEuclideanNorm() < ( R1 - R2 ) * ( R1 - R2 ) )
1263 double weight = ( C1 - C2 ).EuclideanNorm() - R1 - R2;
1265 if( weight > aMaxWeight || weight < 0 )
1269 pc.
weight = std::max( weight, 0.0 );
1270 pc.
a1 = ( C2 - C1 ).Resize( R1 ) + C1;
1271 pc.
a2 = ( C1 - C2 ).Resize( R2 ) + C2;
1278 double aMaxSquaredWeight )
const
1280 std::vector<PATH_CONNECTION>
result;
1284 double halfWidth = this->
GetWidth() / 2;
1286 EDA_ANGLE trackAngle( s_end - s_start );
1289 double length = ( s_start - s_end ).EuclideanNorm();
1290 double projectedPos = cos( trackAngle.
AsRadians() ) * ( pointPos.
x - s_start.
x )
1291 + sin( trackAngle.
AsRadians() ) * ( pointPos.
y - s_start.
y );
1293 if( ( projectedPos <= 0 ) || ( s_start == s_end ) )
1296 return csc.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1299 if( projectedPos >= length )
1302 return csc.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1306 double trackSide = ( s_end - s_start ).Cross( pointPos - s_start ) > 0 ? 1 : -1;
1309 pc.
a1 = s_start + ( s_end - s_start ).Resize( projectedPos )
1310 + ( s_end - s_start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1311 pc.
a2 = ( pc.
a1 - pointPos ).Resize(
radius ) + pointPos;
1312 pc.
weight = ( pc.
a2 - pc.
a1 ).SquaredEuclideanNorm();
1314 if( pc.
weight <= aMaxSquaredWeight )
1325 double aMaxSquaredWeight )
const
1327 std::vector<PATH_CONNECTION>
result;
1332 double circleRadius = this->
GetRadius();
1340 if( ( circlePos - arcPos ).EuclideanNorm() > arcRadius + circleRadius )
1342 const std::vector<PATH_CONNECTION>& pcs = this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
1344 if( pcs.size() == 1 )
1350 result.push_back( pcs[0] );
1362 std::vector<PATH_CONNECTION> pcs1 = this->
Paths( csc1, aMaxWeight, aMaxSquaredWeight );
1363 std::vector<PATH_CONNECTION> pcs2 = this->
Paths( csc2, aMaxWeight, aMaxSquaredWeight );
1367 if( !bestPath || ( ( bestPath->
weight > pc.weight ) && ( pc.weight > 0 ) ) )
1373 if( !bestPath || ( ( bestPath->
weight > pc.weight ) && ( pc.weight > 0 ) ) )
1381 if( ( circlePos - arcPos ).SquaredEuclideanNorm() < arcRadius * arcRadius )
1383 if( circlePos != arcPos )
1389 pc3.
weight = std::max( arcRadius - ( circlePos - arcPos ).EuclideanNorm() - circleRadius, 0.0 );
1390 pc3.
a1 = circlePos + ( circlePos - arcPos ).Resize( circleRadius );
1391 pc3.
a2 = arcPos + ( circlePos - arcPos ).Resize( arcRadius - aS2.
GetWidth() / 2 );
1399 if( bestPath && bestPath->
weight > 0 )
1401 result.push_back( *bestPath );
1409 double aMaxSquaredWeight )
const
1411 std::vector<PATH_CONNECTION>
result;
1415 double halfWidth1 = this->
GetWidth() / 2;
1419 double halfWidth2 = aS2.
GetWidth() / 2;
1424 std::vector<PATH_CONNECTION> pcs;
1425 pcs = this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
1427 if( pcs.size() < 1 )
1433 if( pcs.size() > 0 )
1435 circlePoint = pcs[0].a1;
1439 if( testAngle < aS2.
GetEndAngle() && pcs.size() > 0 )
1441 result.push_back( pcs[0] );
1451 if( !bestPath || ( bestPath->
weight > pc.weight ) )
1457 if( !bestPath || ( bestPath->
weight > pc.weight ) )
1466 if( !bestPath || ( bestPath->
weight > pc.weight ) )
1473 if( !bestPath || ( bestPath->
weight > pc.weight ) )
1478 result.push_back( *bestPath );
1497 t = std::max( 0.0, std::min( 1.0, t ) );
1499 return A + ( AB * t );
1505 double aMaxSquaredWeight )
const
1507 std::vector<PATH_CONNECTION>
result;
1511 double halfWidth1 = this->
GetWidth() / 2;
1516 double halfWidth2 = aS2.
GetWidth() / 2;
1524 double dist1 = ( P1 -
C ).SquaredEuclideanNorm();
1525 double dist2 = ( P2 -
D ).SquaredEuclideanNorm();
1526 double dist3 = ( P3 -
A ).SquaredEuclideanNorm();
1527 double dist4 = ( P4 -
B ).SquaredEuclideanNorm();
1530 double min_dist = dist1;
1534 if( dist2 < min_dist )
1541 if( dist3 < min_dist )
1548 if( dist4 < min_dist )
1557 pc.
a1 = closest1 + ( closest2 - closest1 ).Resize( halfWidth1 );
1558 pc.
a2 = closest2 + ( closest1 - closest2 ).Resize( halfWidth2 );
1559 pc.
weight = std::max( sqrt( min_dist ) - halfWidth1 - halfWidth2, 0.0 );
1561 if( pc.
weight <= aMaxWeight )
1569 double aMaxSquaredWeight )
const
1571 std::vector<PATH_CONNECTION>
result;
1577 double dist = ( center1 - center2 ).EuclideanNorm();
1579 if( dist > aMaxWeight || dist == 0 )
1588 double weight = std::max( R2 - dist - R1, 0.0 );
1590 if( weight > aMaxWeight )
1593 double radialAngle = circleAngle +
M_PI;
1594 double cx = cos( radialAngle );
1595 double cy = sin( radialAngle );
1611 double weight = sqrt( dist * dist - R2 * R2 ) - R1;
1612 double theta = asin( R2 / dist );
1613 double psi = acos( R2 / dist );
1615 if( weight > aMaxWeight )
1619 pc.
weight = std::max( weight, 0.0 );
1624 pStart =
VECTOR2I( R1 * cos( theta + circleAngle ), R1 * sin( theta + circleAngle ) );
1626 pEnd =
VECTOR2I( -R2 * cos( psi - circleAngle ), R2 * sin( psi - circleAngle ) );
1633 pStart =
VECTOR2I( R1 * cos( -theta + circleAngle ), R1 * sin( -theta + circleAngle ) );
1635 pEnd =
VECTOR2I( -R2 * cos( -psi - circleAngle ), R2 * sin( -psi - circleAngle ) );
1647 double aMaxSquaredWeight )
const
1649 std::vector<PATH_CONNECTION>
result;
1665 if( ( point - arcCenter ).SquaredEuclideanNorm() >
radius *
radius )
1668 return circle.Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1673 pc.
weight = std::max( (
radius - width / 2 ) - ( point - arcCenter ).EuclideanNorm(), 0.0 );
1674 pc.
a1 = ( point - arcCenter ).Resize(
radius - width / 2 ) + arcCenter;
1687 if( ( point - this->
GetStartPoint() ).SquaredEuclideanNorm()
1688 > ( point - this->
GetEndPoint() ).SquaredEuclideanNorm() )
1698 return circle.Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1704 double aMaxSquaredWeight )
const
1706 std::vector<PATH_CONNECTION>
result;
1715 bestPath.
weight = std::numeric_limits<double>::infinity();
1724 for(
const std::vector<PATH_CONNECTION>& pcs : { csc1.
Paths( csc2, aMaxWeight, aMaxSquaredWeight ),
1725 this->
Paths( csc2, aMaxWeight, aMaxSquaredWeight ),
1726 csc1.
Paths( aS2, aMaxWeight, aMaxSquaredWeight ) } )
1738 for(
const std::vector<PATH_CONNECTION>& pcs : { this->
Paths( csc5, aMaxWeight, aMaxSquaredWeight ),
1739 this->
Paths( csc6, aMaxWeight, aMaxSquaredWeight ),
1740 csc3.
Paths( aS2, aMaxWeight, aMaxSquaredWeight ),
1741 csc4.
Paths( aS2, aMaxWeight, aMaxSquaredWeight ) } )
1745 if( bestPath.
weight > pc.weight )
1750 if( bestPath.
weight != std::numeric_limits<double>::infinity() )
1751 result.push_back( bestPath );
1758 std::vector<VECTOR2I>* aIntersectPoints )
1760 SEG segment( p1, p2 );
1763 std::vector<VECTOR2I> intersectionPoints;
1768 std::visit( visitor, geom1 );
1770 if( aIntersectPoints )
1772 for(
VECTOR2I& point : intersectionPoints )
1773 aIntersectPoints->push_back( point );
1776 return intersectionPoints.size() > 0;
1780 const std::vector<BOARD_ITEM*>& aBe,
1781 const std::vector<const BOARD_ITEM*>& aDontTestAgainst,
1782 int aMinGrooveWidth )
1784 std::vector<VECTOR2I> intersectionPoints;
1785 bool TestGrooveWidth = aMinGrooveWidth > 0;
1789 if( count( aDontTestAgainst.begin(), aDontTestAgainst.end(), be ) > 0 )
1802 if( intersects && !TestGrooveWidth )
1824 bool intersects =
false;
1829 intersectionPoints );
1831 intersectionPoints );
1837 intersectionPoints );
1839 intersectionPoints );
1842 if( intersects && !TestGrooveWidth )
1848 struct CornerArcRange
1855 std::vector<CornerArcRange> arcs;
1860 arcs.push_back( { { x1 + r, y1 + r },
1863 arcs.push_back( { { x2 - r, y1 + r },
1867 else if( w == 2 * r )
1870 arcs.push_back( { { x1 + r, y1 + r },
1873 arcs.push_back( { { x1 + r, y2 - r },
1891 for(
const CornerArcRange& ca : arcs )
1894 ca.startAngle, ca.endAngle,
1895 &intersectionPoints );
1897 if( arcIntersects && !TestGrooveWidth )
1908 bool intersects =
false;
1914 if( intersects && !TestGrooveWidth )
1925 if( points.size() < 2 )
1928 VECTOR2I prevPoint = points.back();
1930 bool intersects =
false;
1938 if( intersects && !TestGrooveWidth )
1951 if( intersects && !TestGrooveWidth )
1967 if( intersects && !TestGrooveWidth )
1978 if( intersectionPoints.size() <= 0 )
1981 if( intersectionPoints.size() % 2 != 0 )
1984 int minx = intersectionPoints[0].x;
1985 int maxx = intersectionPoints[0].x;
1986 int miny = intersectionPoints[0].y;
1987 int maxy = intersectionPoints[0].y;
1989 for(
const VECTOR2I& v : intersectionPoints )
1991 minx = v.x < minx ? v.x : minx;
1992 maxx = v.x > maxx ? v.x : maxx;
1993 miny = v.x < miny ? v.x : miny;
1994 maxy = v.x > maxy ? v.x : maxy;
1997 if( abs( maxx - minx ) > abs( maxy - miny ) )
1999 std::sort( intersectionPoints.begin(), intersectionPoints.end(),
2007 std::sort( intersectionPoints.begin(), intersectionPoints.end(),
2014 int GVSquared = aMinGrooveWidth * aMinGrooveWidth;
2016 for(
size_t i = 0; i < intersectionPoints.size(); i += 2 )
2018 if( intersectionPoints[i].SquaredDistance( intersectionPoints[i + 1] ) > GVSquared )
2028 double maxWeight = aMaxWeight;
2029 double maxWeightSquared = maxWeight * maxWeight;
2030 std::vector<PATH_CONNECTION>
result;
2049 if( cuarc1 && cuarc2 )
2050 return cuarc1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2051 if( cuarc1 && cucircle2 )
2052 return cuarc1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2053 if( cuarc1 && cusegment2 )
2054 return cuarc1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2055 if( cucircle1 && cuarc2 )
2056 return cucircle1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2057 if( cucircle1 && cucircle2 )
2058 return cucircle1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2059 if( cucircle1 && cusegment2 )
2060 return cucircle1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2061 if( cusegment1 && cuarc2 )
2062 return cusegment1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2063 if( cusegment1 && cucircle2 )
2064 return cusegment1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2065 if( cusegment1 && cusegment2 )
2066 return cusegment1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2071 if( cuarc1 && bearc2 )
2072 return cuarc1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2073 if( cuarc1 && becircle2 )
2074 return cuarc1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2075 if( cuarc1 && bepoint2 )
2076 return cuarc1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2077 if( cucircle1 && bearc2 )
2078 return cucircle1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2079 if( cucircle1 && becircle2 )
2080 return cucircle1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2081 if( cucircle1 && bepoint2 )
2082 return cucircle1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2083 if( cusegment1 && bearc2 )
2084 return cusegment1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2085 if( cusegment1 && becircle2 )
2086 return cusegment1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2087 if( cusegment1 && bepoint2 )
2088 return cusegment1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2092 if( cuarc2 && bearc1 )
2093 return bearc1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2094 if( cuarc2 && becircle1 )
2095 return becircle1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2096 if( cuarc2 && bepoint1 )
2097 return bepoint1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2098 if( cucircle2 && bearc1 )
2099 return bearc1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2100 if( cucircle2 && becircle1 )
2101 return becircle1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2102 if( cucircle2 && bepoint1 )
2103 return bepoint1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2104 if( cusegment2 && bearc1 )
2105 return bearc1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2106 if( cusegment2 && becircle1 )
2107 return becircle1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2108 if( cusegment2 && bepoint1 )
2109 return bepoint1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2114 if( bearc1 && bearc2 )
2115 return bearc1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2116 if( bearc1 && becircle2 )
2117 return bearc1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2118 if( bearc1 && bepoint2 )
2119 return bearc1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2120 if( becircle1 && bearc2 )
2121 return becircle1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2122 if( becircle1 && becircle2 )
2123 return becircle1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2124 if( becircle1 && bepoint2 )
2125 return becircle1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2126 if( bepoint1 && bearc2 )
2127 return bepoint1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2128 if( bepoint1 && becircle2 )
2129 return bepoint1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2130 if( bepoint1 && bepoint2 )
2131 return bepoint1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2137 std::vector<std::shared_ptr<GRAPH_CONNECTION>>& aResult )
2139 if( !aFrom || !aTo )
2146 std::unordered_map<GRAPH_NODE*, double> distances;
2147 std::unordered_map<GRAPH_NODE*, GRAPH_NODE*> previous;
2151 double distLeft = distances[
left];
2152 double distRight = distances[
right];
2154 if( distLeft == distRight )
2156 return distLeft > distRight;
2158 std::priority_queue<GRAPH_NODE*, std::vector<GRAPH_NODE*>,
decltype( cmp )> pq( cmp );
2161 for(
const std::shared_ptr<GRAPH_NODE>& node :
m_nodes )
2163 if( node !=
nullptr )
2164 distances[node.get()] = std::numeric_limits<double>::infinity();
2167 distances[aFrom.get()] = 0.0;
2168 distances[aTo.get()] = std::numeric_limits<double>::infinity();
2169 pq.push( aFrom.get() );
2172 while( !pq.empty() )
2177 if( current == aTo.get() )
2183 for(
const std::shared_ptr<GRAPH_CONNECTION>& connection : current->
m_node_conns )
2185 GRAPH_NODE* neighbor = ( connection->n1 ).get() == current ? ( connection->n2 ).get()
2186 : ( connection->n1 ).get();
2192 if( connection->m_path.weight < 0.0 )
2194 wxLogTrace(
"CREEPAGE",
"Negative weight connection found. Ignoring connection." );
2198 double alt = distances[current] + connection->m_path.weight;
2200 if( alt < distances[neighbor] )
2202 distances[neighbor] = alt;
2203 previous[neighbor] = current;
2204 pq.push( neighbor );
2209 double pathWeight = distances[aTo.get()];
2212 if( pathWeight == std::numeric_limits<double>::infinity() )
2213 return std::numeric_limits<double>::infinity();
2218 while( step != aFrom.get() )
2222 for(
const std::shared_ptr<GRAPH_CONNECTION>& node_conn : step->
m_node_conns )
2224 if( ( ( node_conn->n1 ).get() == prevNode && ( node_conn->n2 ).get() == step )
2225 || ( ( node_conn->n1 ).get() == step && ( node_conn->n2 ).get() == prevNode ) )
2227 aResult.push_back( node_conn );
2245 switch( aShape.
Type() )
2260 newshape =
dynamic_cast<CREEP_SHAPE*
>( cucircle );
2275 start = arc.
GetP0();
2281 start = arc.
GetP1();
2296 int nbShapes =
static_cast<const SHAPE_COMPOUND*
>( &aShape )->Shapes().size();
2297 for(
const SHAPE* subshape : (
static_cast<const SHAPE_COMPOUND*
>( &aShape )->Shapes() ) )
2302 if( !( ( subshape->Type() ==
SH_RECT ) && ( nbShapes == 5 ) ) )
2303 Addshape( *subshape, aConnectTo, aParent );
2315 const SEG object = *it;
2317 Addshape( segment, aConnectTo, aParent );
2332 Addshape( segment, aConnectTo, aParent );
2361 std::shared_ptr<GRAPH_NODE> gnShape =
nullptr;
2365 switch( aShape.
Type() )
2376 gnShape->m_net = aConnectTo->m_net;
2377 std::shared_ptr<GRAPH_CONNECTION> gc =
AddConnection( gnShape, aConnectTo );
2380 gc->m_path.m_show =
false;
2391 std::vector<std::shared_ptr<GRAPH_NODE>> nodes;
2392 std::mutex nodes_lock;
2395 std::vector<CREEPAGE_TRACK_ENTRY*> trackEntries;
2396 TRACK_RTREE::Builder trackBuilder;
2404 std::shared_ptr<SHAPE> sh = track->GetEffectiveShape();
2409 entry->
segment =
SEG( track->GetStart(), track->GetEnd() );
2410 entry->
layer = aLayer;
2411 entry->
halfWidth = track->GetWidth() / 2;
2412 entry->
track = track;
2414 BOX2I bbox = track->GetBoundingBox();
2415 int minCoords[2] = { bbox.
GetX(), bbox.
GetY() };
2417 trackBuilder.Add( minCoords, maxCoords, entry );
2418 trackEntries.push_back( entry );
2426 std::copy_if(
m_nodes.begin(),
m_nodes.end(), std::back_inserter( nodes ),
2427 [&](
const std::shared_ptr<GRAPH_NODE>& gn )
2429 return gn && gn->m_parent && gn->m_connectDirectly && ( gn->m_type != GRAPH_NODE::TYPE::VIRTUAL );
2432 std::sort( nodes.begin(), nodes.end(),
2433 [](
const std::shared_ptr<GRAPH_NODE>& gn1,
const std::shared_ptr<GRAPH_NODE>& gn2 )
2435 return gn1->m_parent < gn2->m_parent
2436 || ( gn1->m_parent == gn2->m_parent && gn1->m_net < gn2->m_net );
2441 std::unordered_map<const BOARD_ITEM*, std::unordered_map<int, std::vector<std::shared_ptr<GRAPH_NODE>>>> parent_net_groups;
2442 std::unordered_map<const BOARD_ITEM*, BOX2I> parent_bboxes;
2443 std::vector<const BOARD_ITEM*> parent_keys;
2445 for(
const auto& gn : nodes )
2447 const BOARD_ITEM* parent = gn->m_parent->GetParent();
2449 if( parent_net_groups[parent].
empty() )
2451 parent_keys.push_back( parent );
2456 parent_net_groups[parent][gn->m_net].push_back( gn );
2460 std::vector<std::pair<std::shared_ptr<GRAPH_NODE>, std::shared_ptr<GRAPH_NODE>>> work_items;
2465 int64_t maxDist =
static_cast<int64_t
>( aMaxWeight );
2473 std::vector<ParentEntry> parentEntries;
2475 for(
const auto* parent : parent_keys )
2480 entry.parent = parent;
2481 entry.bbox = parent_bboxes[parent];
2482 parentEntries.push_back( entry );
2488 for( ParentEntry& entry : parentEntries )
2490 int minCoords[2] = { entry.bbox.GetLeft(), entry.bbox.GetTop() };
2491 int maxCoords[2] = { entry.bbox.GetRight(), entry.bbox.GetBottom() };
2492 parentBuilder.
Add( minCoords, maxCoords, &entry );
2495 auto parentIndex = parentBuilder.
Build();
2498 std::mutex work_items_lock;
2500 auto searchParent = [&](
size_t i ) ->
bool
2502 const ParentEntry& entry1 = parentEntries[i];
2504 BOX2I bbox1 = entry1.bbox;
2506 std::vector<std::pair<std::shared_ptr<GRAPH_NODE>, std::shared_ptr<GRAPH_NODE>>> localWorkItems;
2509 int searchMin[2] = { bbox1.
GetLeft() - (int) maxDist, bbox1.
GetTop() - (int) maxDist };
2510 int searchMax[2] = { bbox1.
GetRight() + (int) maxDist, bbox1.
GetBottom() + (int) maxDist };
2512 auto parentVisitor = [&]( ParentEntry* entry2 ) ->
bool
2517 if( parent1 >= parent2 )
2521 BOX2I bbox2 = entry2->bbox;
2523 int64_t bboxDistX = 0;
2530 int64_t bboxDistY = 0;
2537 int64_t bboxDistSq = bboxDistX * bboxDistX + bboxDistY * bboxDistY;
2539 if( bboxDistSq > maxDist * maxDist )
2543 auto it1 = parent_net_groups.find( parent1 );
2544 auto it2 = parent_net_groups.find( parent2 );
2546 if( it1 == parent_net_groups.end() || it2 == parent_net_groups.end() )
2549 for(
const auto& [net1, nodes1] : it1->second )
2551 for(
const auto& [net2, nodes2] : it2->second )
2554 if( net1 == net2 && !nodes1.empty() && !nodes2.empty() )
2556 if( nodes1[0]->m_parent->IsConductive()
2557 && nodes2[0]->m_parent->IsConductive() )
2561 for(
const auto& gn1 : nodes1 )
2563 for(
const auto& gn2 : nodes2 )
2565 VECTOR2I pos1 = gn1->m_parent->GetPos();
2566 VECTOR2I pos2 = gn2->m_parent->GetPos();
2567 int r1 = gn1->m_parent->GetRadius();
2568 int r2 = gn2->m_parent->GetRadius();
2570 int64_t centerDistSq = ( pos1 - pos2 ).SquaredEuclideanNorm();
2571 double threshold = aMaxWeight + r1 + r2;
2572 double thresholdSq = threshold * threshold;
2574 if( (
double) centerDistSq > thresholdSq )
2577 localWorkItems.push_back( { gn1, gn2 } );
2586 parentIndex.Search( searchMin, searchMax, parentVisitor );
2589 if( !localWorkItems.empty() )
2591 std::lock_guard<std::mutex> lock( work_items_lock );
2592 work_items.insert( work_items.end(), localWorkItems.begin(), localWorkItems.end() );
2599 if( parentEntries.size() > 100 &&
tp.get_tasks_total() <
tp.get_thread_count() - 4 )
2601 auto ret =
tp.submit_loop( 0, parentEntries.size(), searchParent );
2603 for(
auto& r : ret )
2611 for(
size_t i = 0; i < parentEntries.size(); ++i )
2620 for(
const auto& [parent, net_groups] : parent_net_groups )
2622 std::vector<std::shared_ptr<GRAPH_NODE>> sameParentNodes;
2624 for(
const auto& [net, nodeList] : net_groups )
2625 sameParentNodes.insert( sameParentNodes.end(), nodeList.begin(), nodeList.end() );
2627 for(
size_t i = 0; i < sameParentNodes.size(); i++ )
2629 for(
size_t j = i + 1; j < sameParentNodes.size(); j++ )
2631 auto& gn1 = sameParentNodes[i];
2632 auto& gn2 = sameParentNodes[j];
2635 if( gn1->m_parent == gn2->m_parent )
2639 if( gn1->m_parent->IsConductive() && gn2->m_parent->IsConductive()
2640 && gn1->m_net == gn2->m_net )
2645 VECTOR2I pos1 = gn1->m_parent->GetPos();
2646 VECTOR2I pos2 = gn2->m_parent->GetPos();
2647 int r1 = gn1->m_parent->GetRadius();
2648 int r2 = gn2->m_parent->GetRadius();
2650 int64_t centerDistSq = ( pos1 - pos2 ).SquaredEuclideanNorm();
2651 double threshold = aMaxWeight + r1 + r2;
2652 double thresholdSq = threshold * threshold;
2654 if( (
double) centerDistSq > thresholdSq )
2657 work_items.push_back( { gn1, gn2 } );
2662 auto processWorkItems =
2663 [&](
size_t idx ) ->
bool
2665 auto& [gn1, gn2] = work_items[idx];
2673 std::vector<const BOARD_ITEM*> IgnoreForTest;
2687 if( shape1->
GetType() == CREEP_SHAPE::TYPE::CIRCLE
2688 || shape1->
GetType() == CREEP_SHAPE::TYPE::ARC )
2690 IgnoreForTest.push_back( shape1->
GetParent() );
2693 if( shape2->
GetType() == CREEP_SHAPE::TYPE::CIRCLE
2694 || shape2->
GetType() == CREEP_SHAPE::TYPE::ARC )
2696 IgnoreForTest.push_back( shape2->
GetParent() );
2702 IgnoreForTest.push_back( shape1->
GetParent() );
2705 IgnoreForTest.push_back( shape2->
GetParent() );
2715 std::shared_ptr<GRAPH_NODE> connect1 = gn1, connect2 = gn2;
2716 std::lock_guard<std::mutex> lock( nodes_lock );
2719 if( gn1->m_parent->GetType() != CREEP_SHAPE::TYPE::POINT )
2722 gnt1->m_connectDirectly =
false;
2725 if( gn1->m_parent->IsConductive() )
2727 if( std::shared_ptr<GRAPH_CONNECTION> gc =
AddConnection( gn1, gnt1 ) )
2728 gc->m_path.m_show =
false;
2733 if( gn2->m_parent->GetType() != CREEP_SHAPE::TYPE::POINT )
2736 gnt2->m_connectDirectly =
false;
2739 if( gn2->m_parent->IsConductive() )
2741 if( std::shared_ptr<GRAPH_CONNECTION> gc =
AddConnection( gn2, gnt2 ) )
2742 gc->m_path.m_show =
false;
2754 if(
tp.get_tasks_total() >=
tp.get_thread_count() - 4 )
2756 for(
size_t ii = 0; ii < work_items.size(); ii++ )
2757 processWorkItems( ii );
2761 auto ret =
tp.submit_loop( 0, work_items.size(), processWorkItems );
2763 for(
size_t ii = 0; ii < ret.size(); ii++ )
2770 while( r.wait_for( std::chrono::milliseconds( 100 ) ) != std::future_status::ready ){}
2782 std::vector<std::shared_ptr<GRAPH_CONNECTION>> toRemove;
2785 for( std::shared_ptr<GRAPH_CONNECTION>& gc :
m_connections )
2787 if( gc && ( gc->m_path.weight > aWeightLimit ) )
2788 toRemove.push_back( gc );
2792 for(
const std::shared_ptr<GRAPH_CONNECTION>& gc : toRemove )
2802 for( std::shared_ptr<GRAPH_NODE> gn : { aGc->n1, aGc->n2 } )
2806 gn->m_node_conns.erase( aGc );
2808 if( gn->m_node_conns.empty() && aDelete )
2811 [&gn](
const std::shared_ptr<GRAPH_NODE>& node )
2813 return node.get() == gn.get();
2836 std::shared_ptr<GRAPH_NODE> gn =
FindNode( aType, parent, pos );
2841 gn = std::make_shared<GRAPH_NODE>( aType, parent, pos );
2851 std::shared_ptr<GRAPH_NODE> gn = std::make_shared<GRAPH_NODE>( GRAPH_NODE::TYPE::VIRTUAL,
nullptr );
2859 std::shared_ptr<GRAPH_NODE>& aN2,
2865 wxASSERT_MSG( ( aN1 != aN2 ),
"Creepage: a connection connects a node to itself" );
2867 std::shared_ptr<GRAPH_CONNECTION> gc = std::make_shared<GRAPH_CONNECTION>( aN1, aN2, aPc );
2869 aN1->m_node_conns.insert( gc );
2870 aN2->m_node_conns.insert( gc );
2877 std::shared_ptr<GRAPH_NODE>& aN2 )
2894 auto it =
m_nodeset.find( std::make_shared<GRAPH_NODE>( aType, aParent, aPos ) );
2907 virtualNode->m_net = aNetCode;
2911 for(
PAD*
pad : footprint->Pads() )
2913 if(
pad->GetNetCode() != aNetCode || !
pad->IsOnLayer( aLayer ) )
2916 if( std::shared_ptr<SHAPE> padShape =
pad->GetEffectiveShape( aLayer ) )
2923 if( track->GetNetCode() != aNetCode || !track->IsOnLayer( aLayer ) )
2926 if( std::shared_ptr<SHAPE> shape = track->GetEffectiveShape() )
2927 Addshape( *shape, virtualNode, track );
2933 if( zone->GetNetCode() != aNetCode || !zone->IsOnLayer( aLayer ) )
2936 if( std::shared_ptr<SHAPE> shape = zone->GetEffectiveShape( aLayer ) )
2937 Addshape( *shape, virtualNode, zone );
2944 if( drawing->IsConnected() )
2952 Addshape( *shape, virtualNode, bci );
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)
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
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 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 BE_SHAPE_POINT &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
constexpr coord_type GetY() const
constexpr coord_type GetX() const
constexpr coord_type GetLeft() const
constexpr coord_type GetRight() const
constexpr coord_type GetTop() const
constexpr coord_type GetBottom() const
Represent basic circle geometry with utility geometry functions.
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
void TransformEdgeToCreepShapes()
std::shared_ptr< GRAPH_NODE > AddNodeVirtual()
void TransformCreepShapesToNodes(std::vector< CREEP_SHAPE * > &aShapes)
void Trim(double aWeightLimit)
SHAPE_POLY_SET * m_boardOutline
void RemoveDuplicatedShapes()
std::vector< BOARD_ITEM * > m_boardEdge
double m_creepageTargetSquared
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.
CREEP_SHAPE::TYPE GetType() const
void SetParent(BOARD_ITEM *aParent)
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
Creepage: a conductive arc.
VECTOR2I GetStartPoint() const override
EDA_ANGLE AngleBetweenStartAndEnd(const VECTOR2I aPoint) const
VECTOR2I GetEndPoint() const override
EDA_ANGLE GetStartAngle() const override
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 BE_SHAPE_POINT &aS2, double aMaxWeight, double aMaxSquaredWeight) const override
Creepage: a conductive circle.
int GetRadius() const override
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
CU_SHAPE_SEGMENT(VECTOR2I aStart, VECTOR2I aEnd, double aWidth=0)
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
void SetCenter(const VECTOR2I &aCenter)
VECTOR2I getCenter() const
std::vector< VECTOR2I > GetPolyPoints() const
Duplicate the polygon outlines into a flat list of VECTOR2I points.
void CalcArcAngles(EDA_ANGLE &aStartAngle, EDA_ANGLE &aEndAngle) const
Calc arc start and end angles such that aStartAngle < aEndAngle.
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
void SetStart(const VECTOR2I &aStart)
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
void SetEnd(const VECTOR2I &aEnd)
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
int GetCornerRadius() const
VECTOR2I GetArcMid() const
std::shared_ptr< GRAPH_NODE > n2
void GetShapes(std::vector< PCB_SHAPE > &aShapes)
std::shared_ptr< GRAPH_NODE > n1
std::set< std::shared_ptr< GRAPH_CONNECTION > > m_node_conns
Builder for constructing a PACKED_RTREE from a set of items.
void Add(const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], const DATATYPE &aData)
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
const VECTOR2I & GetArcMid() const
int GetWidth() const override
const VECTOR2I & GetP1() const
const VECTOR2I & GetP0() const
SHAPE_TYPE Type() const
Return the type of the shape.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
const std::vector< VECTOR2I > & CPoints() const
Represent a set of closed polygons.
CONST_SEGMENT_ITERATOR CIterateSegmentsWithHoles() const
Return an iterator object, for the aOutline-th outline in the set (with holes).
const VECTOR2I & GetPosition() const
const VECTOR2I GetSize() const
const SEG & GetSeg() const
int GetWidth() const override
An abstract shape on 2D plane.
constexpr extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
VECTOR2_TRAITS< int32_t >::extended_type extended_type
constexpr VECTOR2< T > Perpendicular() const
Compute the perpendicular vector.
constexpr extended_type Dot(const VECTOR2< T > &aVector) const
Compute dot product of self with aVector.
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Handle a list of polygons defining a copper zone.
static bool empty(const wxTextEntryBase *aCtrl)
VECTOR2I closestPointOnSegment(const VECTOR2I &A, const VECTOR2I &B, const VECTOR2I &P)
bool SegmentIntersectsBoard(const VECTOR2I &aP1, const VECTOR2I &aP2, const std::vector< BOARD_ITEM * > &aBe, const std::vector< const BOARD_ITEM * > &aDontTestAgainst, int aMinGrooveWidth)
std::vector< PATH_CONNECTION > GetPaths(CREEP_SHAPE *aS1, CREEP_SHAPE *aS2, double aMaxWeight)
bool segmentIntersectsArc(const VECTOR2I &p1, const VECTOR2I &p2, const VECTOR2I ¢er, double radius, EDA_ANGLE startAngle, EDA_ANGLE endAngle, std::vector< VECTOR2I > *aIntersectionPoints=nullptr)
bool compareShapes(const CREEP_SHAPE *a, const CREEP_SHAPE *b)
bool segments_intersect(const VECTOR2I &p1, const VECTOR2I &q1, const VECTOR2I &p2, const VECTOR2I &q2, std::vector< VECTOR2I > &aIntersectionPoints)
bool areEquivalent(const CREEP_SHAPE *a, const CREEP_SHAPE *b)
bool segmentIntersectsCircle(const VECTOR2I &p1, const VECTOR2I &p2, const VECTOR2I ¢er, double radius, std::vector< VECTOR2I > *aIntersectPoints)
KIRTREE::PACKED_RTREE< CREEPAGE_TRACK_ENTRY *, int, 2 > TRACK_RTREE
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_360
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
std::variant< LINE, HALF_LINE, SEG, CIRCLE, SHAPE_ARC, BOX2I > INTERSECTABLE_GEOM
A variant type that can hold any of the supported geometry types for intersection calculations.
PCB_LAYER_ID
A quick note on layer IDs:
std::deque< BOARD_ITEM * > DRAWINGS
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
@ SH_POLY_SET
set of polygons (with holes, etc.)
@ SH_RECT
axis-aligned rectangle
@ SH_LINE_CHAIN
line chain (polyline)
@ SH_COMPOUND
compound shape, consisting of multiple simple shapes
A visitor that visits INTERSECTABLE_GEOM variant objects with another (which is held as state: m_othe...
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
wxString result
Test unit parsing edge cases and error handling.
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::priority_thread_pool thread_pool
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D