28 std::vector<std::unique_ptr<PCB_SHAPE>>& aOwned,
29 const std::set<const BOARD_ITEM*>* aExclude )
33 auto excluded = [&](
const BOARD_ITEM* aItem ) ->
bool
35 if( !aExclude || !aItem )
38 if( aExclude->count( aItem ) )
43 return parent && aExclude->count( parent );
48 auto addEdgeDrawing = [&](
BOARD_ITEM* aDrawing )
50 if( !aDrawing || !aDrawing->IsOnLayer(
Edge_Cuts ) )
53 if( excluded( aDrawing ) )
65 aVector.push_back( shape );
72 for(
size_t i = 1; i < pts.size(); ++i )
74 if( pts[i - 1] == pts[i] )
78 seg->SetStart( pts[i - 1] );
79 seg->SetEnd( pts[i] );
80 aVector.push_back( seg.get() );
81 aOwned.push_back( std::move( seg ) );
86 addEdgeDrawing( drawing );
93 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
94 addEdgeDrawing( drawing );
105 std::shared_ptr<SHAPE_SEGMENT> hole = p->GetEffectiveHoleShape();
112 int radius = hole->GetWidth() / 2;
118 s->SetPosition( ptA );
119 aVector.push_back( s.get() );
120 aOwned.push_back( std::move( s ) );
129 seg1->SetStart( ptA + perp );
130 seg1->SetEnd( ptB + perp );
131 aVector.push_back( seg1.get() );
132 aOwned.push_back( std::move( seg1 ) );
135 seg2->SetStart( ptA - perp );
136 seg2->SetEnd( ptB - perp );
137 aVector.push_back( seg2.get() );
138 aOwned.push_back( std::move( seg2 ) );
141 auto arcA = std::make_unique<PCB_SHAPE>(
nullptr,
SHAPE_T::ARC );
142 arcA->SetArcGeometry( ptA + perp, midA, ptA - perp );
143 aVector.push_back( arcA.get() );
144 aOwned.push_back( std::move( arcA ) );
147 auto arcB = std::make_unique<PCB_SHAPE>(
nullptr,
SHAPE_T::ARC );
148 arcB->SetArcGeometry( ptB - perp, midB, ptB + perp );
149 aVector.push_back( arcB.get() );
150 aOwned.push_back( std::move( arcB ) );
158 std::vector<VECTOR2I>* aIntersectionPoints =
nullptr )
160 SEG segment( p1, p2 );
167 std::vector<VECTOR2I> rawPoints;
169 std::visit( visitor, geom1 );
173 std::vector<VECTOR2I> filtered;
180 return ( a - b ).SquaredEuclideanNorm() <= toleranceSq;
183 for(
const VECTOR2I& ip : rawPoints )
185 if( !coincident( ip, p1 ) && !coincident( ip, p2 ) )
186 filtered.push_back( ip );
189 if( aIntersectionPoints )
191 for(
const VECTOR2I& ip : filtered )
192 aIntersectionPoints->push_back( ip );
195 return !filtered.empty();
202 std::vector<VECTOR2I>& aIntersectionPoints )
204 if( p1 == p2 || p1 == q2 || q1 == p2 || q1 == q2 )
207 SEG segment1( p1, q1 );
208 SEG segment2( p2, q2 );
213 size_t startCount = aIntersectionPoints.size();
216 std::visit( visitor, geom1 );
218 return aIntersectionPoints.size() > startCount;
233 if( a->
GetType() == CREEP_SHAPE::TYPE::UNDEFINED )
239 if( a->
GetType() == CREEP_SHAPE::TYPE::CIRCLE )
257 if( a->
GetType() == CREEP_SHAPE::TYPE::POINT )
260 if( a->
GetType() == CREEP_SHAPE::TYPE::CIRCLE )
268 double aMaxSquaredWeight )
const
270 std::vector<PATH_CONNECTION>
result;
272 double weight = ( this->
GetPos() - aS2.
GetPos() ).SquaredEuclideanNorm();
274 if( weight > aMaxSquaredWeight )
280 pc.
weight = sqrt( weight );
288 double aMaxSquaredWeight )
const
290 std::vector<PATH_CONNECTION>
result;
298 double pointToCenterDistanceSquared = ( pointPos - circleCenter ).SquaredEuclideanNorm();
299 double weightSquared = pointToCenterDistanceSquared - (float)
radius * (
float)
radius;
301 if( weightSquared > aMaxSquaredWeight )
305 direction1 = direction1.
Resize( 1 );
309 double radiusSquared = double(
radius ) * double(
radius );
311 double distance = sqrt( pointToCenterDistanceSquared );
312 double value1 = radiusSquared /
distance;
313 double value2 = sqrt( radiusSquared - value1 * value1 );
319 pc.
weight = sqrt( weightSquared );
321 resultPoint = direction1 * value1 + direction2 * value2 + circleCenter;
322 pc.
a2.
x = int( resultPoint.
x );
323 pc.
a2.
y = int( resultPoint.
y );
326 resultPoint = direction1 * value1 - direction2 * value2 + circleCenter;
327 pc.
a2.
x = int( resultPoint.
x );
328 pc.
a2.
y = int( resultPoint.
y );
337 std::pair<bool, bool>
result;
354 double pointAngle = testAngle.
AsRadians();
357 bool connectToEndPoint;
359 connectToEndPoint = ( cos( startAngle ) * newPoint.
x + sin( startAngle ) * newPoint.
y >= R );
362 connectToEndPoint &= ( cos( endAngle ) * newPoint.
x + sin( endAngle ) * newPoint.
y <= R );
364 connectToEndPoint |= ( cos( endAngle ) * newPoint.
x + sin( endAngle ) * newPoint.
y <= R )
365 && ( pointAngle >= endAngle || pointAngle <= startAngle );
367 result.first = !connectToEndPoint;
369 connectToEndPoint = ( cos( endAngle ) * newPoint.
x + sin( endAngle ) * newPoint.
y >= R );
372 connectToEndPoint &= ( cos( startAngle ) * newPoint.
x + sin( startAngle ) * newPoint.
y <= R );
374 connectToEndPoint |= ( cos( startAngle ) * newPoint.
x + sin( startAngle ) * newPoint.
y <= R )
375 && ( pointAngle >= endAngle || pointAngle <= startAngle );
377 result.second = !connectToEndPoint;
383 double aMaxSquaredWeight )
const
385 std::vector<PATH_CONNECTION>
result;
391 std::pair<bool, bool> behavesLikeCircle;
394 if( behavesLikeCircle.first && behavesLikeCircle.second )
397 return this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
400 if( behavesLikeCircle.first )
403 std::vector<PATH_CONNECTION> paths = this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
405 if( paths.size() > 1 )
406 result.push_back( paths[1] );
416 if( behavesLikeCircle.second )
419 std::vector<PATH_CONNECTION> paths = this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
421 if( paths.size() > 1 )
422 result.push_back( paths[0] );
436 double aMaxSquaredWeight )
const
438 std::vector<PATH_CONNECTION>
result;
446 double centerDistance = ( circleCenter - arcCenter ).EuclideanNorm();
448 if( centerDistance + arcRadius < circleRadius )
486 double aMaxSquaredWeight )
const
488 std::vector<PATH_CONNECTION>
result;
494 double centerDistance = ( circleCenter - arcCenter ).EuclideanNorm();
496 if( centerDistance + arcRadius < circleRadius )
508 aMaxWeight, aMaxSquaredWeight ) )
517 .
Paths( aS2, aMaxWeight, aMaxSquaredWeight ) )
530 double aMaxSquaredWeight )
const
532 std::vector<PATH_CONNECTION>
result;
537 VECTOR2D distSquared(
double( ( p2 - p1 ).x ),
double( ( p2 - p1 ).y ) );
543 double Rdiff = abs( R1 - R2 );
544 double Rsum = R1 + R2;
547 double weightSquared1 = weightSquared - Rdiff * Rdiff;
549 double weightSquared2 = weightSquared - Rsum * Rsum;
551 if( weightSquared1 <= aMaxSquaredWeight )
554 direction1 = direction1.
Resize( 1 );
557 double D = sqrt( weightSquared );
558 double ratio1 = ( R1 - R2 ) /
D;
559 double ratio2 = sqrt( 1 - ratio1 * ratio1 );
563 pc.
weight = sqrt( weightSquared1 );
565 pc.
a1 = p1 + direction1 * R1 * ratio1 + direction2 * R1 * ratio2;
566 pc.
a2 = p2 + direction1 * R2 * ratio1 + direction2 * R2 * ratio2;
570 pc.
a1 = p1 + direction1 * R1 * ratio1 - direction2 * R1 * ratio2;
571 pc.
a2 = p2 + direction1 * R2 * ratio1 - direction2 * R2 * ratio2;
575 if( weightSquared2 <= aMaxSquaredWeight )
578 direction1 = direction1.
Resize( 1 );
581 double D = sqrt( weightSquared );
582 double ratio1 = ( R1 + R2 ) /
D;
583 double ratio2 = sqrt( 1 - ratio1 * ratio1 );
587 pc.
weight = sqrt( weightSquared2 );
589 pc.
a1 = p1 + direction1 * R1 * ratio1 + direction2 * R1 * ratio2;
590 pc.
a2 = p2 - direction1 * R2 * ratio1 - direction2 * R2 * ratio2;
594 pc.
a1 = p1 + direction1 * R1 * ratio1 - direction2 * R1 * ratio2;
595 pc.
a2 = p2 - direction1 * R2 * ratio1 + direction2 * R2 * ratio2;
611 switch( p1->GetType() )
613 case CREEP_SHAPE::TYPE::POINT:
AddNode( GRAPH_NODE::TYPE::POINT, p1, p1->GetPos() );
break;
614 case CREEP_SHAPE::TYPE::CIRCLE:
AddNode( GRAPH_NODE::TYPE::CIRCLE, p1, p1->GetPos() );
break;
615 case CREEP_SHAPE::TYPE::ARC:
AddNode( GRAPH_NODE::TYPE::ARC, p1, p1->GetPos() );
break;
625 std::vector<CREEP_SHAPE*> newVector;
654 std::vector<BOX2I> cutouts;
670 for(
size_t j = i + 1; j < cutouts.size(); ++j )
672 if( cutouts[i].Intersects( cutouts[j] ) && !cutouts[i].Contains( cutouts[j] )
673 && !cutouts[j].Contains( cutouts[i] ) )
723 while( endAngle < startAngle )
737 addArc( { x1 + r, y1 + r }, { x1 + r, y2 }, { x1 + r, y1 } );
738 addArc( { x2 - r, y1 + r }, { x2 - r, y1 }, { x2 - r, y2 } );
740 else if( w == 2 * r )
743 addArc( { x1 + r, y1 + r }, { x1, y1 + r }, { x2, y1 + r } );
744 addArc( { x1 + r, y2 - r }, { x2, y2 - r }, { x1, y2 - r } );
749 addArc( { x1 + r, y1 + r }, { x1, y1 + r }, { x1 + r, y1 } );
750 addArc( { x2 - r, y1 + r }, { x2 - r, y1 }, { x2, y1 + r } );
751 addArc( { x2 - r, y2 - r }, { x2, y2 - r }, { x2 - r, y2 } );
752 addArc( { x1 + r, y2 - r }, { x1 + r, y2 }, { x1, y2 - r } );
795 double tolerance = 10;
826 if(
n1->m_type == GRAPH_NODE::TYPE::VIRTUAL ||
n2->m_type == GRAPH_NODE::TYPE::VIRTUAL )
830 &&
n1->m_parent ==
n2->m_parent
831 &&
n1->m_parent->GetType() == CREEP_SHAPE::TYPE::CIRCLE )
838 if( R1.
Cross( R2 ) > 0 )
850 aShapes.push_back( s );
855 &&
n1->m_parent ==
n2->m_parent
856 &&
n1->m_parent->GetType() == CREEP_SHAPE::TYPE::ARC )
865 if( R1.
Cross( R2 ) > 0 )
880 EDA_ANGLE midAngle = arc->AngleBetweenStartAndEnd( mid );
882 if( midAngle > arc->GetEndAngle() )
891 aShapes.push_back( s );
899 aShapes.push_back( s );
930 EDA_ANGLE maxAngle = angle1 > angle2 ? angle1 : angle2;
933 skipAngle += skipAngle;
934 EDA_ANGLE pointAngle = maxAngle - skipAngle;
944 pc.
a1 = maxAngle == angle2 ? a1->m_pos : a2->m_pos;
950 pc.
a2 = maxAngle == angle2 ? a2->m_pos : a1->m_pos;
953 std::shared_ptr<GRAPH_CONNECTION> gc = aG.
AddConnection( gnt, maxAngle == angle2 ? a2 : a1, pc );
956 gc->m_forceStraightLine =
true;
976 double delta = a2r - a1r;
983 for(
int i = 0; i <= 8; ++i )
985 double a = a1r +
delta * i / 8.0;
993 VECTOR2D distI( a1->m_pos - a2->m_pos );
994 VECTOR2D distD(
double( distI.
x ),
double( distI.
y ) );
1006 pc.
weight = std::max( weight, 0.0 );
1035 for(
int i = 0; i <= 8; ++i )
1037 double a = a1r + ( a2r - a1r ) * i / 8.0;
1045 double weight = abs(
m_radius * ( angle2 - angle1 ).AsRadians() );
1074 double aMaxSquaredWeight )
const
1076 std::vector<PATH_CONNECTION>
result;
1079 double halfWidth = this->
GetWidth() / 2;
1083 double length = ( start -
end ).EuclideanNorm();
1084 double projectedPos = cos( trackAngle.
AsRadians() ) * ( pointPos.
x - start.
x )
1085 + sin( trackAngle.
AsRadians() ) * ( pointPos.
y - start.
y );
1089 if( projectedPos <= 0 )
1091 newPoint = start + ( pointPos - start ).Resize( halfWidth );
1093 else if( projectedPos >= length )
1095 newPoint =
end + ( pointPos -
end ).Resize( halfWidth );
1099 double posOnSegment = ( start - pointPos ).SquaredEuclideanNorm()
1100 - (
end - pointPos ).SquaredEuclideanNorm();
1101 posOnSegment = posOnSegment / ( 2 * length ) + length / 2;
1103 newPoint = start + (
end - start ).Resize( posOnSegment );
1104 newPoint += ( pointPos - newPoint ).Resize( halfWidth );
1107 double weightSquared = ( pointPos - newPoint ).SquaredEuclideanNorm();
1109 if( weightSquared > aMaxSquaredWeight )
1115 pc.
weight = sqrt( weightSquared );
1123 double aMaxSquaredWeight )
const
1125 std::vector<PATH_CONNECTION>
result;
1128 double halfWidth = this->
GetWidth() / 2;
1132 double length = ( start -
end ).EuclideanNorm();
1135 double weightSquared = std::numeric_limits<double>::infinity();
1136 VECTOR2I PointOnTrack, PointOnCircle;
1140 double projectedPos1 = cos( trackAngle.
AsRadians() ) * ( circleCenter.
x - start.
x )
1141 + sin( trackAngle.
AsRadians() ) * ( circleCenter.
y - start.
y );
1142 double projectedPos2 = projectedPos1 + circleRadius;
1143 projectedPos1 = projectedPos1 - circleRadius;
1145 double trackSide = (
end - start ).Cross( circleCenter - start ) > 0 ? 1 : -1;
1147 if( ( projectedPos1 < 0 && projectedPos2 < 0 ) )
1155 else if( ( projectedPos1 > length && projectedPos2 > length ) )
1163 else if( ( projectedPos1 >= 0 ) && ( projectedPos1 <= length ) && ( projectedPos2 >= 0 )
1164 && ( projectedPos2 <= length ) )
1167 PointOnTrack = start;
1168 PointOnTrack += (
end - start ).Resize( projectedPos1 );
1169 PointOnTrack += (
end - start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1170 PointOnCircle = circleCenter - (
end - start ).Resize( circleRadius );
1171 weightSquared = ( PointOnCircle - PointOnTrack ).SquaredEuclideanNorm();
1173 if( weightSquared < aMaxSquaredWeight )
1176 pc.
a1 = PointOnTrack;
1177 pc.
a2 = PointOnCircle;
1178 pc.
weight = sqrt( weightSquared );
1182 PointOnTrack = start;
1183 PointOnTrack += (
end - start ).Resize( projectedPos2 );
1184 PointOnTrack += (
end - start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1185 PointOnCircle = circleCenter + (
end - start ).Resize( circleRadius );
1188 pc.
a1 = PointOnTrack;
1189 pc.
a2 = PointOnCircle;
1194 else if( ( ( projectedPos1 >= 0 ) && ( projectedPos1 <= length ) )
1195 && ( ( projectedPos2 > length ) || projectedPos2 < 0 ) )
1198 std::vector<PATH_CONNECTION> pcs = csc.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1200 if( pcs.size() < 2 )
1203 result.push_back( pcs.at( trackSide == 1 ? 1 : 0 ) );
1206 PointOnTrack = start;
1207 PointOnTrack += (
end - start ).Resize( projectedPos1 );
1208 PointOnTrack += (
end - start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1209 PointOnCircle = circleCenter - (
end - start ).Resize( circleRadius );
1210 weightSquared = ( PointOnCircle - PointOnTrack ).SquaredEuclideanNorm();
1212 if( weightSquared < aMaxSquaredWeight )
1215 pc.
a1 = PointOnTrack;
1216 pc.
a2 = PointOnCircle;
1217 pc.
weight = sqrt( weightSquared );
1222 else if( ( ( projectedPos2 >= 0 ) && ( projectedPos2 <= length ) )
1223 && ( ( projectedPos1 > length ) || projectedPos1 < 0 ) )
1226 std::vector<PATH_CONNECTION> pcs = csc.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1228 if( pcs.size() < 2 )
1231 result.push_back( pcs.at( trackSide == 1 ? 0 : 1 ) );
1233 PointOnTrack = start;
1234 PointOnTrack += (
end - start ).Resize( projectedPos2 );
1235 PointOnTrack += (
end - start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1236 PointOnCircle = circleCenter + (
end - start ).Resize( circleRadius );
1237 weightSquared = ( PointOnCircle - PointOnTrack ).SquaredEuclideanNorm();
1239 if( weightSquared < aMaxSquaredWeight )
1242 pc.
a1 = PointOnTrack;
1243 pc.
a2 = PointOnCircle;
1244 pc.
weight = sqrt( weightSquared );
1255 double aMaxSquaredWeight )
const
1257 std::vector<PATH_CONNECTION>
result;
1281 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1287 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1297 double aMaxSquaredWeight )
const
1299 std::vector<PATH_CONNECTION>
result;
1322 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1328 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1338 double aMaxSquaredWeight )
const
1340 std::vector<PATH_CONNECTION>
result;
1369 double aMaxSquaredWeight )
const
1371 std::vector<PATH_CONNECTION>
result;
1394 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1400 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1410 double aMaxSquaredWeight )
const
1412 std::vector<PATH_CONNECTION>
result;
1417 double weight = (
center - point ).EuclideanNorm() - R;
1419 if( weight > aMaxWeight )
1423 pc.
weight = std::max( weight, 0.0 );
1433 double aMaxSquaredWeight )
const
1435 std::vector<PATH_CONNECTION>
result;
1442 if( ( C1 - C2 ).SquaredEuclideanNorm() < ( R1 - R2 ) * ( R1 - R2 ) )
1448 double weight = ( C1 - C2 ).EuclideanNorm() - R1 - R2;
1450 if( weight > aMaxWeight || weight < 0 )
1454 pc.
weight = std::max( weight, 0.0 );
1455 pc.
a1 = ( C2 - C1 ).Resize( R1 ) + C1;
1456 pc.
a2 = ( C1 - C2 ).Resize( R2 ) + C2;
1463 double aMaxSquaredWeight )
const
1465 std::vector<PATH_CONNECTION>
result;
1469 double halfWidth = this->
GetWidth() / 2;
1471 EDA_ANGLE trackAngle( s_end - s_start );
1474 double length = ( s_start - s_end ).EuclideanNorm();
1475 double projectedPos = cos( trackAngle.
AsRadians() ) * ( pointPos.
x - s_start.
x )
1476 + sin( trackAngle.
AsRadians() ) * ( pointPos.
y - s_start.
y );
1478 if( ( projectedPos <= 0 ) || ( s_start == s_end ) )
1481 return csc.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1484 if( projectedPos >= length )
1487 return csc.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1491 double trackSide = ( s_end - s_start ).Cross( pointPos - s_start ) > 0 ? 1 : -1;
1494 pc.
a1 = s_start + ( s_end - s_start ).Resize( projectedPos )
1495 + ( s_end - s_start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1496 pc.
a2 = ( pc.
a1 - pointPos ).Resize(
radius ) + pointPos;
1497 pc.
weight = ( pc.
a2 - pc.
a1 ).SquaredEuclideanNorm();
1499 if( pc.
weight <= aMaxSquaredWeight )
1510 double aMaxSquaredWeight )
const
1512 std::vector<PATH_CONNECTION>
result;
1517 double circleRadius = this->
GetRadius();
1525 if( ( circlePos - arcPos ).EuclideanNorm() > arcRadius + circleRadius )
1527 const std::vector<PATH_CONNECTION>& pcs = this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
1529 if( pcs.size() == 1 )
1535 result.push_back( pcs[0] );
1547 std::vector<PATH_CONNECTION> pcs1 = this->
Paths( csc1, aMaxWeight, aMaxSquaredWeight );
1548 std::vector<PATH_CONNECTION> pcs2 = this->
Paths( csc2, aMaxWeight, aMaxSquaredWeight );
1552 if( !bestPath || ( ( bestPath->
weight > pc.weight ) && ( pc.weight > 0 ) ) )
1558 if( !bestPath || ( ( bestPath->
weight > pc.weight ) && ( pc.weight > 0 ) ) )
1566 if( ( circlePos - arcPos ).SquaredEuclideanNorm() < arcRadius * arcRadius )
1568 if( circlePos != arcPos )
1574 pc3.
weight = std::max( arcRadius - ( circlePos - arcPos ).EuclideanNorm() - circleRadius, 0.0 );
1575 pc3.
a1 = circlePos + ( circlePos - arcPos ).Resize( circleRadius );
1576 pc3.
a2 = arcPos + ( circlePos - arcPos ).Resize( arcRadius - aS2.
GetWidth() / 2 );
1584 if( bestPath && bestPath->
weight > 0 )
1586 result.push_back( *bestPath );
1594 double aMaxSquaredWeight )
const
1596 std::vector<PATH_CONNECTION>
result;
1600 double halfWidth1 = this->
GetWidth() / 2;
1604 double halfWidth2 = aS2.
GetWidth() / 2;
1609 std::vector<PATH_CONNECTION> pcs;
1610 pcs = this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
1612 if( pcs.size() < 1 )
1618 if( pcs.size() > 0 )
1620 circlePoint = pcs[0].a1;
1624 if( testAngle < aS2.
GetEndAngle() && pcs.size() > 0 )
1626 result.push_back( pcs[0] );
1636 if( !bestPath || ( bestPath->
weight > pc.weight ) )
1642 if( !bestPath || ( bestPath->
weight > pc.weight ) )
1651 if( !bestPath || ( bestPath->
weight > pc.weight ) )
1658 if( !bestPath || ( bestPath->
weight > pc.weight ) )
1663 result.push_back( *bestPath );
1682 t = std::max( 0.0, std::min( 1.0, t ) );
1684 return A + ( AB * t );
1690 double aMaxSquaredWeight )
const
1692 std::vector<PATH_CONNECTION>
result;
1696 double halfWidth1 = this->
GetWidth() / 2;
1701 double halfWidth2 = aS2.
GetWidth() / 2;
1709 double dist1 = ( P1 -
C ).SquaredEuclideanNorm();
1710 double dist2 = ( P2 -
D ).SquaredEuclideanNorm();
1711 double dist3 = ( P3 -
A ).SquaredEuclideanNorm();
1712 double dist4 = ( P4 -
B ).SquaredEuclideanNorm();
1715 double min_dist = dist1;
1719 if( dist2 < min_dist )
1726 if( dist3 < min_dist )
1733 if( dist4 < min_dist )
1742 pc.
a1 = closest1 + ( closest2 - closest1 ).Resize( halfWidth1 );
1743 pc.
a2 = closest2 + ( closest1 - closest2 ).Resize( halfWidth2 );
1744 pc.
weight = std::max( sqrt( min_dist ) - halfWidth1 - halfWidth2, 0.0 );
1746 if( pc.
weight <= aMaxWeight )
1754 double aMaxSquaredWeight )
const
1756 std::vector<PATH_CONNECTION>
result;
1762 double dist = ( center1 - center2 ).EuclideanNorm();
1764 if( dist > aMaxWeight || dist == 0 )
1773 double weight = std::max( R2 - dist - R1, 0.0 );
1775 if( weight > aMaxWeight )
1778 double radialAngle = circleAngle +
M_PI;
1779 double cx = cos( radialAngle );
1780 double cy = sin( radialAngle );
1796 double weight = sqrt( dist * dist - R2 * R2 ) - R1;
1797 double theta = asin( R2 / dist );
1798 double psi = acos( R2 / dist );
1800 if( weight > aMaxWeight )
1804 pc.
weight = std::max( weight, 0.0 );
1809 pStart =
VECTOR2I( R1 * cos( theta + circleAngle ), R1 * sin( theta + circleAngle ) );
1811 pEnd =
VECTOR2I( -R2 * cos( psi - circleAngle ), R2 * sin( psi - circleAngle ) );
1818 pStart =
VECTOR2I( R1 * cos( -theta + circleAngle ), R1 * sin( -theta + circleAngle ) );
1820 pEnd =
VECTOR2I( -R2 * cos( -psi - circleAngle ), R2 * sin( -psi - circleAngle ) );
1832 double aMaxSquaredWeight )
const
1834 std::vector<PATH_CONNECTION>
result;
1850 if( ( point - arcCenter ).SquaredEuclideanNorm() >
radius *
radius )
1853 return circle.Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1858 pc.
weight = std::max( (
radius - width / 2 ) - ( point - arcCenter ).EuclideanNorm(), 0.0 );
1859 pc.
a1 = ( point - arcCenter ).Resize(
radius - width / 2 ) + arcCenter;
1872 if( ( point - this->
GetStartPoint() ).SquaredEuclideanNorm()
1873 > ( point - this->
GetEndPoint() ).SquaredEuclideanNorm() )
1883 return circle.Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1889 double aMaxSquaredWeight )
const
1891 std::vector<PATH_CONNECTION>
result;
1900 bestPath.
weight = std::numeric_limits<double>::infinity();
1909 for(
const std::vector<PATH_CONNECTION>& pcs : { csc1.
Paths( csc2, aMaxWeight, aMaxSquaredWeight ),
1910 this->
Paths( csc2, aMaxWeight, aMaxSquaredWeight ),
1911 csc1.
Paths( aS2, aMaxWeight, aMaxSquaredWeight ) } )
1923 for(
const std::vector<PATH_CONNECTION>& pcs : { this->
Paths( csc5, aMaxWeight, aMaxSquaredWeight ),
1924 this->
Paths( csc6, aMaxWeight, aMaxSquaredWeight ),
1925 csc3.
Paths( aS2, aMaxWeight, aMaxSquaredWeight ),
1926 csc4.
Paths( aS2, aMaxWeight, aMaxSquaredWeight ) } )
1930 if( bestPath.
weight > pc.weight )
1935 if( bestPath.
weight != std::numeric_limits<double>::infinity() )
1936 result.push_back( bestPath );
1943 std::vector<VECTOR2I>* aIntersectPoints )
1945 SEG segment( p1, p2 );
1948 std::vector<VECTOR2I> intersectionPoints;
1953 std::visit( visitor, geom1 );
1961 return ( a - b ).SquaredEuclideanNorm() <= toleranceSq;
1964 std::vector<VECTOR2I> filtered;
1966 for(
const VECTOR2I& ip : intersectionPoints )
1968 if( !coincident( ip, p1 ) && !coincident( ip, p2 ) )
1969 filtered.push_back( ip );
1972 if( aIntersectPoints )
1975 aIntersectPoints->push_back( point );
1978 return filtered.size() > 0;
1982 const std::vector<BOARD_ITEM*>& aBe,
1983 const std::vector<const BOARD_ITEM*>& aDontTestAgainst,
1984 int aMinGrooveWidth )
1986 std::vector<VECTOR2I> intersectionPoints;
1987 bool TestGrooveWidth = aMinGrooveWidth > 0;
1991 if( count( aDontTestAgainst.begin(), aDontTestAgainst.end(), be ) > 0 )
2004 if( intersects && !TestGrooveWidth )
2026 bool intersects =
false;
2031 intersectionPoints );
2033 intersectionPoints );
2039 intersectionPoints );
2041 intersectionPoints );
2044 if( intersects && !TestGrooveWidth )
2050 struct CornerArcRange
2057 std::vector<CornerArcRange> arcs;
2064 arcs.push_back( { { x1 + r, y1 + r },
2067 arcs.push_back( { { x2 - r, y1 + r },
2071 else if( w == 2 * r )
2074 arcs.push_back( { { x1 + r, y1 + r },
2077 arcs.push_back( { { x1 + r, y2 - r },
2095 for(
const CornerArcRange& ca : arcs )
2098 ca.startAngle, ca.endAngle,
2099 &intersectionPoints );
2101 if( arcIntersects && !TestGrooveWidth )
2112 bool intersects =
false;
2118 if( intersects && !TestGrooveWidth )
2129 if( points.size() < 2 )
2132 VECTOR2I prevPoint = points.back();
2134 bool intersects =
false;
2142 if( intersects && !TestGrooveWidth )
2155 if( intersects && !TestGrooveWidth )
2171 if( intersects && !TestGrooveWidth )
2182 if( intersectionPoints.size() <= 0 )
2185 if( intersectionPoints.size() % 2 != 0 )
2188 int minx = intersectionPoints[0].x;
2189 int maxx = intersectionPoints[0].x;
2190 int miny = intersectionPoints[0].y;
2191 int maxy = intersectionPoints[0].y;
2193 for(
const VECTOR2I& v : intersectionPoints )
2195 minx = v.x < minx ? v.x : minx;
2196 maxx = v.x > maxx ? v.x : maxx;
2197 miny = v.x < miny ? v.x : miny;
2198 maxy = v.x > maxy ? v.x : maxy;
2201 if( abs( maxx - minx ) > abs( maxy - miny ) )
2203 std::sort( intersectionPoints.begin(), intersectionPoints.end(),
2211 std::sort( intersectionPoints.begin(), intersectionPoints.end(),
2218 int GVSquared = aMinGrooveWidth * aMinGrooveWidth;
2220 for(
size_t i = 0; i < intersectionPoints.size(); i += 2 )
2222 if( intersectionPoints[i].SquaredDistance( intersectionPoints[i + 1] ) > GVSquared )
2232 double maxWeight = aMaxWeight;
2233 double maxWeightSquared = maxWeight * maxWeight;
2234 std::vector<PATH_CONNECTION>
result;
2253 if( cuarc1 && cuarc2 )
2254 return cuarc1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2255 if( cuarc1 && cucircle2 )
2256 return cuarc1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2257 if( cuarc1 && cusegment2 )
2258 return cuarc1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2259 if( cucircle1 && cuarc2 )
2260 return cucircle1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2261 if( cucircle1 && cucircle2 )
2262 return cucircle1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2263 if( cucircle1 && cusegment2 )
2264 return cucircle1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2265 if( cusegment1 && cuarc2 )
2266 return cusegment1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2267 if( cusegment1 && cucircle2 )
2268 return cusegment1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2269 if( cusegment1 && cusegment2 )
2270 return cusegment1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2275 if( cuarc1 && bearc2 )
2276 return cuarc1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2277 if( cuarc1 && becircle2 )
2278 return cuarc1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2279 if( cuarc1 && bepoint2 )
2280 return cuarc1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2281 if( cucircle1 && bearc2 )
2282 return cucircle1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2283 if( cucircle1 && becircle2 )
2284 return cucircle1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2285 if( cucircle1 && bepoint2 )
2286 return cucircle1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2287 if( cusegment1 && bearc2 )
2288 return cusegment1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2289 if( cusegment1 && becircle2 )
2290 return cusegment1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2291 if( cusegment1 && bepoint2 )
2292 return cusegment1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2296 if( cuarc2 && bearc1 )
2297 return bearc1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2298 if( cuarc2 && becircle1 )
2299 return becircle1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2300 if( cuarc2 && bepoint1 )
2301 return bepoint1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2302 if( cucircle2 && bearc1 )
2303 return bearc1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2304 if( cucircle2 && becircle1 )
2305 return becircle1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2306 if( cucircle2 && bepoint1 )
2307 return bepoint1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2308 if( cusegment2 && bearc1 )
2309 return bearc1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2310 if( cusegment2 && becircle1 )
2311 return becircle1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2312 if( cusegment2 && bepoint1 )
2313 return bepoint1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2318 if( bearc1 && bearc2 )
2319 return bearc1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2320 if( bearc1 && becircle2 )
2321 return bearc1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2322 if( bearc1 && bepoint2 )
2323 return bearc1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2324 if( becircle1 && bearc2 )
2325 return becircle1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2326 if( becircle1 && becircle2 )
2327 return becircle1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2328 if( becircle1 && bepoint2 )
2329 return becircle1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2330 if( bepoint1 && bearc2 )
2331 return bepoint1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2332 if( bepoint1 && becircle2 )
2333 return bepoint1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2334 if( bepoint1 && bepoint2 )
2335 return bepoint1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2341 std::vector<std::shared_ptr<GRAPH_CONNECTION>>& aResult )
2343 if( !aFrom || !aTo )
2350 std::unordered_map<GRAPH_NODE*, double> distances;
2351 std::unordered_map<GRAPH_NODE*, GRAPH_NODE*> previous;
2356 using QUEUE_ITEM = std::pair<double, GRAPH_NODE*>;
2358 auto cmp = [](
const QUEUE_ITEM& aLeft,
const QUEUE_ITEM& aRight )
2360 if( aLeft.first == aRight.first )
2361 return aLeft.second > aRight.second;
2362 return aLeft.first > aRight.first;
2364 std::priority_queue<QUEUE_ITEM, std::vector<QUEUE_ITEM>,
decltype( cmp )> pq( cmp );
2367 for(
const std::shared_ptr<GRAPH_NODE>& node :
m_nodes )
2369 if( node !=
nullptr )
2370 distances[node.get()] = std::numeric_limits<double>::infinity();
2373 distances[aFrom.get()] = 0.0;
2374 distances[aTo.get()] = std::numeric_limits<double>::infinity();
2375 pq.push( { 0.0, aFrom.get() } );
2378 while( !pq.empty() )
2380 auto [dist, current] = pq.top();
2385 if( dist > distances[current] )
2388 if( current == aTo.get() )
2394 for(
const std::shared_ptr<GRAPH_CONNECTION>& connection : current->m_node_conns )
2396 GRAPH_NODE* neighbor = ( connection->n1 ).get() == current ? ( connection->n2 ).get()
2397 : ( connection->n1 ).get();
2403 if( connection->m_path.weight < 0.0 )
2405 wxLogTrace(
"CREEPAGE",
"Negative weight connection found. Ignoring connection." );
2409 double alt = distances[current] + connection->m_path.weight;
2411 if( alt < distances[neighbor] )
2413 distances[neighbor] = alt;
2414 previous[neighbor] = current;
2415 pq.push( { alt, neighbor } );
2420 double pathWeight = distances[aTo.get()];
2423 if( pathWeight == std::numeric_limits<double>::infinity() )
2424 return std::numeric_limits<double>::infinity();
2429 while( step != aFrom.get() )
2433 for(
const std::shared_ptr<GRAPH_CONNECTION>& node_conn : step->
m_node_conns )
2435 if( ( ( node_conn->n1 ).get() == prevNode && ( node_conn->n2 ).get() == step )
2436 || ( ( node_conn->n1 ).get() == step && ( node_conn->n2 ).get() == prevNode ) )
2438 aResult.push_back( node_conn );
2456 switch( aShape.
Type() )
2471 newshape =
dynamic_cast<CREEP_SHAPE*
>( cucircle );
2486 start = arc.
GetP0();
2492 start = arc.
GetP1();
2507 int nbShapes =
static_cast<const SHAPE_COMPOUND*
>( &aShape )->Shapes().size();
2508 for(
const SHAPE* subshape : (
static_cast<const SHAPE_COMPOUND*
>( &aShape )->Shapes() ) )
2513 if( !( ( subshape->Type() ==
SH_RECT ) && ( nbShapes == 5 ) ) )
2514 Addshape( *subshape, aConnectTo, aParent );
2526 const SEG object = *it;
2528 Addshape( segment, aConnectTo, aParent );
2543 Addshape( segment, aConnectTo, aParent );
2566 if( point != prevPoint )
2598 std::shared_ptr<GRAPH_NODE> gnShape =
nullptr;
2602 switch( aShape.
Type() )
2613 gnShape->m_net = aConnectTo->m_net;
2614 std::shared_ptr<GRAPH_CONNECTION> gc =
AddConnection( gnShape, aConnectTo );
2617 gc->m_path.m_show =
false;
2627 const std::set<int>* aRelevantNets )
2629 auto irrelevantPair = [&](
const std::shared_ptr<GRAPH_NODE>& gn1,
2630 const std::shared_ptr<GRAPH_NODE>& gn2 ) ->
bool
2632 return aRelevantNets && gn1->m_parent && gn2->m_parent && gn1->m_parent->IsConductive()
2633 && gn2->m_parent->IsConductive() && !aRelevantNets->count( gn1->m_net )
2634 && !aRelevantNets->count( gn2->m_net );
2637 std::vector<std::shared_ptr<GRAPH_NODE>> nodes;
2638 std::mutex nodes_lock;
2641 std::vector<CREEPAGE_TRACK_ENTRY*> trackEntries;
2642 TRACK_RTREE::Builder trackBuilder;
2650 std::shared_ptr<SHAPE> sh = track->GetEffectiveShape();
2655 entry->
segment =
SEG( track->GetStart(), track->GetEnd() );
2656 entry->
layer = aLayer;
2657 entry->
halfWidth = track->GetWidth() / 2;
2658 entry->
track = track;
2660 BOX2I bbox = track->GetBoundingBox();
2661 int minCoords[2] = { bbox.
GetX(), bbox.
GetY() };
2663 trackBuilder.Add( minCoords, maxCoords, entry );
2664 trackEntries.push_back( entry );
2672 std::copy_if(
m_nodes.begin(),
m_nodes.end(), std::back_inserter( nodes ),
2673 [&](
const std::shared_ptr<GRAPH_NODE>& gn )
2675 return gn && gn->m_parent && gn->m_connectDirectly && ( gn->m_type != GRAPH_NODE::TYPE::VIRTUAL );
2678 std::sort( nodes.begin(), nodes.end(),
2679 [](
const std::shared_ptr<GRAPH_NODE>& gn1,
const std::shared_ptr<GRAPH_NODE>& gn2 )
2681 return gn1->m_parent < gn2->m_parent
2682 || ( gn1->m_parent == gn2->m_parent && gn1->m_net < gn2->m_net );
2687 std::unordered_map<const BOARD_ITEM*, std::unordered_map<int, std::vector<std::shared_ptr<GRAPH_NODE>>>> parent_net_groups;
2688 std::unordered_map<const BOARD_ITEM*, BOX2I> parent_bboxes;
2689 std::vector<const BOARD_ITEM*> parent_keys;
2691 for(
const auto& gn : nodes )
2693 const BOARD_ITEM* parent = gn->m_parent->GetParent();
2695 if( parent_net_groups[parent].
empty() )
2697 parent_keys.push_back( parent );
2702 parent_net_groups[parent][gn->m_net].push_back( gn );
2706 std::vector<std::pair<std::shared_ptr<GRAPH_NODE>, std::shared_ptr<GRAPH_NODE>>> work_items;
2711 int64_t maxDist =
static_cast<int64_t
>( aMaxWeight );
2719 std::vector<ParentEntry> parentEntries;
2721 for(
const auto* parent : parent_keys )
2726 entry.parent = parent;
2727 entry.bbox = parent_bboxes[parent];
2728 parentEntries.push_back( entry );
2734 for( ParentEntry& entry : parentEntries )
2736 int minCoords[2] = { entry.bbox.GetLeft(), entry.bbox.GetTop() };
2737 int maxCoords[2] = { entry.bbox.GetRight(), entry.bbox.GetBottom() };
2738 parentBuilder.
Add( minCoords, maxCoords, &entry );
2741 auto parentIndex = parentBuilder.
Build();
2744 std::mutex work_items_lock;
2746 auto searchParent = [&](
size_t i ) ->
bool
2748 const ParentEntry& entry1 = parentEntries[i];
2750 BOX2I bbox1 = entry1.bbox;
2752 std::vector<std::pair<std::shared_ptr<GRAPH_NODE>, std::shared_ptr<GRAPH_NODE>>> localWorkItems;
2755 int searchMin[2] = { bbox1.
GetLeft() - (int) maxDist, bbox1.
GetTop() - (int) maxDist };
2756 int searchMax[2] = { bbox1.
GetRight() + (int) maxDist, bbox1.
GetBottom() + (int) maxDist };
2758 auto parentVisitor = [&]( ParentEntry* entry2 ) ->
bool
2763 if( parent1 >= parent2 )
2767 BOX2I bbox2 = entry2->bbox;
2769 int64_t bboxDistX = 0;
2776 int64_t bboxDistY = 0;
2783 int64_t bboxDistSq = bboxDistX * bboxDistX + bboxDistY * bboxDistY;
2785 if( bboxDistSq > maxDist * maxDist )
2789 auto it1 = parent_net_groups.find( parent1 );
2790 auto it2 = parent_net_groups.find( parent2 );
2792 if( it1 == parent_net_groups.end() || it2 == parent_net_groups.end() )
2795 for(
const auto& [net1, nodes1] : it1->second )
2797 for(
const auto& [net2, nodes2] : it2->second )
2800 if( net1 == net2 && !nodes1.empty() && !nodes2.empty() )
2802 if( nodes1[0]->m_parent->IsConductive()
2803 && nodes2[0]->m_parent->IsConductive() )
2807 for(
const auto& gn1 : nodes1 )
2809 for(
const auto& gn2 : nodes2 )
2811 VECTOR2I pos1 = gn1->m_parent->GetPos();
2812 VECTOR2I pos2 = gn2->m_parent->GetPos();
2813 int r1 = gn1->m_parent->GetRadius();
2814 int r2 = gn2->m_parent->GetRadius();
2816 int64_t centerDistSq = ( pos1 - pos2 ).SquaredEuclideanNorm();
2817 double threshold = aMaxWeight + r1 + r2;
2818 double thresholdSq = threshold * threshold;
2820 if( (
double) centerDistSq > thresholdSq )
2823 if( irrelevantPair( gn1, gn2 ) )
2826 localWorkItems.push_back( { gn1, gn2 } );
2835 parentIndex.Search( searchMin, searchMax, parentVisitor );
2838 if( !localWorkItems.empty() )
2840 std::lock_guard<std::mutex> lock( work_items_lock );
2841 work_items.insert( work_items.end(), localWorkItems.begin(), localWorkItems.end() );
2848 if( parentEntries.size() > 100 &&
tp.get_tasks_total() <
tp.get_thread_count() - 4 )
2850 auto ret =
tp.submit_loop( 0, parentEntries.size(), searchParent );
2852 for(
auto& r : ret )
2860 for(
size_t i = 0; i < parentEntries.size(); ++i )
2869 for(
const auto& [parent, net_groups] : parent_net_groups )
2871 std::vector<std::shared_ptr<GRAPH_NODE>> sameParentNodes;
2873 for(
const auto& [net, nodeList] : net_groups )
2874 sameParentNodes.insert( sameParentNodes.end(), nodeList.begin(), nodeList.end() );
2876 for(
size_t i = 0; i < sameParentNodes.size(); i++ )
2878 for(
size_t j = i + 1; j < sameParentNodes.size(); j++ )
2880 auto& gn1 = sameParentNodes[i];
2881 auto& gn2 = sameParentNodes[j];
2884 if( gn1->m_parent == gn2->m_parent )
2888 if( gn1->m_parent->IsConductive() && gn2->m_parent->IsConductive()
2889 && gn1->m_net == gn2->m_net )
2894 VECTOR2I pos1 = gn1->m_parent->GetPos();
2895 VECTOR2I pos2 = gn2->m_parent->GetPos();
2896 int r1 = gn1->m_parent->GetRadius();
2897 int r2 = gn2->m_parent->GetRadius();
2899 int64_t centerDistSq = ( pos1 - pos2 ).SquaredEuclideanNorm();
2900 double threshold = aMaxWeight + r1 + r2;
2901 double thresholdSq = threshold * threshold;
2903 if( (
double) centerDistSq > thresholdSq )
2906 if( irrelevantPair( gn1, gn2 ) )
2909 work_items.push_back( { gn1, gn2 } );
2914 auto processWorkItems =
2915 [&](
size_t idx ) ->
bool
2917 auto& [gn1, gn2] = work_items[idx];
2925 std::vector<const BOARD_ITEM*> IgnoreForTest;
2936 IgnoreForTest.push_back( shape1->
GetParent() );
2939 IgnoreForTest.push_back( shape2->
GetParent() );
2949 std::shared_ptr<GRAPH_NODE> connect1 = gn1, connect2 = gn2;
2950 std::lock_guard<std::mutex> lock( nodes_lock );
2953 if( gn1->m_parent->GetType() != CREEP_SHAPE::TYPE::POINT )
2956 gnt1->m_connectDirectly =
false;
2959 if( gn1->m_parent->IsConductive() )
2961 if( std::shared_ptr<GRAPH_CONNECTION> gc =
AddConnection( gn1, gnt1 ) )
2962 gc->m_path.m_show =
false;
2967 if( gn2->m_parent->GetType() != CREEP_SHAPE::TYPE::POINT )
2970 gnt2->m_connectDirectly =
false;
2973 if( gn2->m_parent->IsConductive() )
2975 if( std::shared_ptr<GRAPH_CONNECTION> gc =
AddConnection( gn2, gnt2 ) )
2976 gc->m_path.m_show =
false;
2988 if(
tp.get_tasks_total() >=
tp.get_thread_count() - 4 )
2990 for(
size_t ii = 0; ii < work_items.size(); ii++ )
2991 processWorkItems( ii );
2995 auto ret =
tp.submit_loop( 0, work_items.size(), processWorkItems );
2997 for(
size_t ii = 0; ii < ret.size(); ii++ )
3004 while( r.wait_for( std::chrono::milliseconds( 100 ) ) != std::future_status::ready ){}
3016 std::vector<std::shared_ptr<GRAPH_CONNECTION>> toRemove;
3019 for( std::shared_ptr<GRAPH_CONNECTION>& gc :
m_connections )
3021 if( gc && ( gc->m_path.weight > aWeightLimit ) )
3022 toRemove.push_back( gc );
3026 for(
const std::shared_ptr<GRAPH_CONNECTION>& gc : toRemove )
3036 for( std::shared_ptr<GRAPH_NODE> gn : { aGc->n1, aGc->n2 } )
3040 gn->m_node_conns.erase( aGc );
3042 if( gn->m_node_conns.empty() && aDelete )
3045 [&gn](
const std::shared_ptr<GRAPH_NODE>& node )
3047 return node.get() == gn.get();
3072 for(
size_t i = aConnectionCount; i < vectorSize; i++ )
3076 m_nodes.resize( aNodeCount,
nullptr );
3081 for(
size_t i = 0; i < aNodeCount; ++i )
3092 std::shared_ptr<GRAPH_NODE> gn =
FindNode( aType, parent, pos );
3097 gn = std::make_shared<GRAPH_NODE>( aType, parent, pos );
3107 std::shared_ptr<GRAPH_NODE> gn = std::make_shared<GRAPH_NODE>( GRAPH_NODE::TYPE::VIRTUAL,
nullptr );
3115 std::shared_ptr<GRAPH_NODE>& aN2,
3121 wxASSERT_MSG( ( aN1 != aN2 ),
"Creepage: a connection connects a node to itself" );
3123 std::shared_ptr<GRAPH_CONNECTION> gc = std::make_shared<GRAPH_CONNECTION>( aN1, aN2, aPc );
3125 aN1->m_node_conns.insert( gc );
3126 aN2->m_node_conns.insert( gc );
3133 std::shared_ptr<GRAPH_NODE>& aN2 )
3150 auto it =
m_nodeset.find( std::make_shared<GRAPH_NODE>( aType, aParent, aPos ) );
3163 virtualNode->m_net = aNetCode;
3167 for(
PAD*
pad : footprint->Pads() )
3169 if(
pad->GetNetCode() != aNetCode || !
pad->IsOnLayer( aLayer ) )
3172 if( std::shared_ptr<SHAPE> padShape =
pad->GetEffectiveShape( aLayer ) )
3179 if( track->GetNetCode() != aNetCode || !track->IsOnLayer( aLayer ) )
3182 if( std::shared_ptr<SHAPE> shape = track->GetEffectiveShape() )
3183 Addshape( *shape, virtualNode, track );
3189 if( zone->GetNetCode() != aNetCode || !zone->IsOnLayer( aLayer ) )
3192 if( std::shared_ptr<SHAPE> shape = zone->GetEffectiveShape( aLayer ) )
3193 Addshape( *shape, virtualNode, zone );
3200 if( drawing->IsConnected() )
3208 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.
Information pertinent to a Pcbnew printed circuit board.
const std::vector< PAD * > GetPads() const
Return a reference to a list of all the pads.
const FOOTPRINTS & Footprints() const
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
const DRAWINGS & Drawings() const
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 GeneratePaths(double aMaxWeight, PCB_LAYER_ID aLayer, const std::set< int > *aRelevantNets=nullptr)
Generate creepage paths between graph nodes.
void TransformEdgeToCreepShapes()
std::shared_ptr< GRAPH_NODE > AddNodeVirtual()
void TransformCreepShapesToNodes(std::vector< CREEP_SHAPE * > &aShapes)
void Trim(double aWeightLimit)
bool m_hasOverlappingCutouts
SHAPE_POLY_SET * m_boardOutline
void RemoveDuplicatedShapes()
void TruncateToPrefix(size_t aNodeCount, size_t aConnectionCount)
Remove every node and connection added after the given prefix sizes, then rebuild the node lookup set...
std::vector< BOARD_ITEM * > m_boardEdge
double m_creepageTargetSquared
std::unordered_set< std::shared_ptr< GRAPH_NODE >, GraphNodeHash, GraphNodeEqual > m_nodeset
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.
void RebuildBezierToSegmentsPointsList(int aMaxError)
Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of segments.
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
const std::vector< VECTOR2I > & GetBezierPoints() const
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)
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
void SetEnd(const VECTOR2I &aEnd) override
void SetStart(const VECTOR2I &aStart) override
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...
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
const std::vector< VECTOR2I > & CPoints() const
Represent a set of closed polygons.
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.
CONST_SEGMENT_ITERATOR CIterateSegmentsWithHoles() const
Return an iterator object, for the aOutline-th outline in the set (with 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.
const VECTOR2I & GetPosition() const
const VECTOR2I GetSize() const
const SEG & GetSeg() const
int GetWidth() const override
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
const SHAPE_LINE_CHAIN & Vertices() const
Return the list of vertices defining this simple polygon.
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)
void BuildCreepageBoardEdges(BOARD &aBoard, std::vector< BOARD_ITEM * > &aVector, std::vector< std::unique_ptr< PCB_SHAPE > > &aOwned, const std::set< const BOARD_ITEM * > *aExclude)
Collect the board-edge items used by the creepage graph.
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:
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
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_SIMPLE
simple polygon
@ 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