28 std::vector<std::unique_ptr<PCB_SHAPE>>& aOwned,
29 const std::set<const BOARD_ITEM*>* aExclude )
36 if( !aExclude || !aItem )
39 if( aExclude->count( aItem ) )
44 return parent && aExclude->count( parent );
52 if( !aDrawing || !aDrawing->IsOnLayer(
Edge_Cuts ) )
55 if( excluded( aDrawing ) )
67 aVector.push_back( shape );
74 for(
size_t i = 1; i < pts.size(); ++i )
76 if( pts[i - 1] == pts[i] )
80 seg->SetStart( pts[i - 1] );
81 seg->SetEnd( pts[i] );
82 aVector.push_back( seg.get() );
83 aOwned.push_back( std::move( seg ) );
88 addEdgeDrawing( drawing );
95 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
96 addEdgeDrawing( drawing );
109 std::shared_ptr<SHAPE_SEGMENT> hole = p->GetEffectiveHoleShape();
116 int radius = hole->GetWidth() / 2;
122 s->SetPosition( ptA );
123 aVector.push_back( s.get() );
124 aOwned.push_back( std::move( s ) );
133 seg1->SetStart( ptA + perp );
134 seg1->SetEnd( ptB + perp );
135 aVector.push_back( seg1.get() );
136 aOwned.push_back( std::move( seg1 ) );
139 seg2->SetStart( ptA - perp );
140 seg2->SetEnd( ptB - perp );
141 aVector.push_back( seg2.get() );
142 aOwned.push_back( std::move( seg2 ) );
145 auto arcA = std::make_unique<PCB_SHAPE>(
nullptr,
SHAPE_T::ARC );
146 arcA->SetArcGeometry( ptA + perp, midA, ptA - perp );
147 aVector.push_back( arcA.get() );
148 aOwned.push_back( std::move( arcA ) );
151 auto arcB = std::make_unique<PCB_SHAPE>(
nullptr,
SHAPE_T::ARC );
152 arcB->SetArcGeometry( ptB - perp, midB, ptB + perp );
153 aVector.push_back( arcB.get() );
154 aOwned.push_back( std::move( arcB ) );
162 std::vector<VECTOR2I>* aIntersectionPoints =
nullptr )
164 SEG segment( p1, p2 );
171 std::vector<VECTOR2I> rawPoints;
173 std::visit( visitor, geom1 );
177 std::vector<VECTOR2I> filtered;
185 return ( a - b ).SquaredEuclideanNorm() <= toleranceSq;
188 for(
const VECTOR2I& ip : rawPoints )
190 if( !coincident( ip, p1 ) && !coincident( ip, p2 ) )
191 filtered.push_back( ip );
194 if( aIntersectionPoints )
196 for(
const VECTOR2I& ip : filtered )
197 aIntersectionPoints->push_back( ip );
200 return !filtered.empty();
207 std::vector<VECTOR2I>& aIntersectionPoints )
209 if( p1 == p2 || p1 == q2 || q1 == p2 || q1 == q2 )
212 SEG segment1( p1, q1 );
213 SEG segment2( p2, q2 );
218 size_t startCount = aIntersectionPoints.size();
221 std::visit( visitor, geom1 );
223 return aIntersectionPoints.size() > startCount;
238 if( a->
GetType() == CREEP_SHAPE::TYPE::UNDEFINED )
244 if( a->
GetType() == CREEP_SHAPE::TYPE::CIRCLE )
262 if( a->
GetType() == CREEP_SHAPE::TYPE::POINT_TYPE )
265 if( a->
GetType() == CREEP_SHAPE::TYPE::CIRCLE )
273 double aMaxSquaredWeight )
const
275 std::vector<PATH_CONNECTION>
result;
277 double weight = ( this->
GetPos() - aS2.
GetPos() ).SquaredEuclideanNorm();
279 if( weight > aMaxSquaredWeight )
285 pc.
weight = sqrt( weight );
293 double aMaxSquaredWeight )
const
295 std::vector<PATH_CONNECTION>
result;
303 double pointToCenterDistanceSquared = ( pointPos - circleCenter ).SquaredEuclideanNorm();
304 double weightSquared = pointToCenterDistanceSquared - (float)
radius * (
float)
radius;
306 if( weightSquared > aMaxSquaredWeight )
310 direction1 = direction1.
Resize( 1 );
314 double radiusSquared = double(
radius ) * double(
radius );
316 double distance = sqrt( pointToCenterDistanceSquared );
317 double value1 = radiusSquared /
distance;
318 double value2 = sqrt( radiusSquared - value1 * value1 );
324 pc.
weight = sqrt( weightSquared );
326 resultPoint = direction1 * value1 + direction2 * value2 + circleCenter;
327 pc.
a2.
x = int( resultPoint.
x );
328 pc.
a2.
y = int( resultPoint.
y );
331 resultPoint = direction1 * value1 - direction2 * value2 + circleCenter;
332 pc.
a2.
x = int( resultPoint.
x );
333 pc.
a2.
y = int( resultPoint.
y );
342 std::pair<bool, bool>
result;
359 double pointAngle = testAngle.
AsRadians();
362 bool connectToEndPoint;
364 connectToEndPoint = ( cos( startAngle ) * newPoint.
x + sin( startAngle ) * newPoint.
y >= R );
367 connectToEndPoint &= ( cos( endAngle ) * newPoint.
x + sin( endAngle ) * newPoint.
y <= R );
369 connectToEndPoint |= ( cos( endAngle ) * newPoint.
x + sin( endAngle ) * newPoint.
y <= R )
370 && ( pointAngle >= endAngle || pointAngle <= startAngle );
372 result.first = !connectToEndPoint;
374 connectToEndPoint = ( cos( endAngle ) * newPoint.
x + sin( endAngle ) * newPoint.
y >= R );
377 connectToEndPoint &= ( cos( startAngle ) * newPoint.
x + sin( startAngle ) * newPoint.
y <= R );
379 connectToEndPoint |= ( cos( startAngle ) * newPoint.
x + sin( startAngle ) * newPoint.
y <= R )
380 && ( pointAngle >= endAngle || pointAngle <= startAngle );
382 result.second = !connectToEndPoint;
388 double aMaxSquaredWeight )
const
390 std::vector<PATH_CONNECTION>
result;
396 std::pair<bool, bool> behavesLikeCircle;
399 if( behavesLikeCircle.first && behavesLikeCircle.second )
402 return this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
405 if( behavesLikeCircle.first )
408 std::vector<PATH_CONNECTION> paths = this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
410 if( paths.size() > 1 )
411 result.push_back( paths[1] );
421 if( behavesLikeCircle.second )
424 std::vector<PATH_CONNECTION> paths = this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
426 if( paths.size() > 1 )
427 result.push_back( paths[0] );
441 double aMaxSquaredWeight )
const
443 std::vector<PATH_CONNECTION>
result;
451 double centerDistance = ( circleCenter - arcCenter ).EuclideanNorm();
453 if( centerDistance + arcRadius < circleRadius )
491 double aMaxSquaredWeight )
const
493 std::vector<PATH_CONNECTION>
result;
499 double centerDistance = ( circleCenter - arcCenter ).EuclideanNorm();
501 if( centerDistance + arcRadius < circleRadius )
513 aMaxWeight, aMaxSquaredWeight ) )
522 .
Paths( aS2, aMaxWeight, aMaxSquaredWeight ) )
535 double aMaxSquaredWeight )
const
537 std::vector<PATH_CONNECTION>
result;
542 VECTOR2D distSquared(
double( ( p2 - p1 ).x ),
double( ( p2 - p1 ).y ) );
548 double Rdiff = abs( R1 - R2 );
549 double Rsum = R1 + R2;
552 double weightSquared1 = weightSquared - Rdiff * Rdiff;
554 double weightSquared2 = weightSquared - Rsum * Rsum;
556 if( weightSquared1 <= aMaxSquaredWeight )
559 direction1 = direction1.
Resize( 1 );
562 double D = sqrt( weightSquared );
563 double ratio1 = ( R1 - R2 ) /
D;
564 double ratio2 = sqrt( 1 - ratio1 * ratio1 );
568 pc.
weight = sqrt( weightSquared1 );
570 pc.
a1 = p1 + direction1 * R1 * ratio1 + direction2 * R1 * ratio2;
571 pc.
a2 = p2 + direction1 * R2 * ratio1 + direction2 * R2 * ratio2;
575 pc.
a1 = p1 + direction1 * R1 * ratio1 - direction2 * R1 * ratio2;
576 pc.
a2 = p2 + direction1 * R2 * ratio1 - direction2 * R2 * ratio2;
580 if( weightSquared2 <= aMaxSquaredWeight )
583 direction1 = direction1.
Resize( 1 );
586 double D = sqrt( weightSquared );
587 double ratio1 = ( R1 + R2 ) /
D;
588 double ratio2 = sqrt( 1 - ratio1 * ratio1 );
592 pc.
weight = sqrt( weightSquared2 );
594 pc.
a1 = p1 + direction1 * R1 * ratio1 + direction2 * R1 * ratio2;
595 pc.
a2 = p2 - direction1 * R2 * ratio1 - direction2 * R2 * ratio2;
599 pc.
a1 = p1 + direction1 * R1 * ratio1 - direction2 * R1 * ratio2;
600 pc.
a2 = p2 - direction1 * R2 * ratio1 + direction2 * R2 * ratio2;
616 switch( p1->GetType() )
618 case CREEP_SHAPE::TYPE::POINT_TYPE:
AddNode( GRAPH_NODE::TYPE::POINT, p1, p1->GetPos() );
break;
619 case CREEP_SHAPE::TYPE::CIRCLE:
AddNode( GRAPH_NODE::TYPE::CIRCLE, p1, p1->GetPos() );
break;
620 case CREEP_SHAPE::TYPE::ARC:
AddNode( GRAPH_NODE::TYPE::ARC, p1, p1->GetPos() );
break;
630 std::vector<CREEP_SHAPE*> newVector;
659 std::vector<BOX2I> cutouts;
675 for(
size_t j = i + 1; j < cutouts.size(); ++j )
677 if( cutouts[i].Intersects( cutouts[j] ) && !cutouts[i].Contains( cutouts[j] )
678 && !cutouts[j].Contains( cutouts[i] ) )
728 while( endAngle < startAngle )
742 addArc( { x1 + r, y1 + r }, { x1 + r, y2 }, { x1 + r, y1 } );
743 addArc( { x2 - r, y1 + r }, { x2 - r, y1 }, { x2 - r, y2 } );
745 else if( w == 2 * r )
748 addArc( { x1 + r, y1 + r }, { x1, y1 + r }, { x2, y1 + r } );
749 addArc( { x1 + r, y2 - r }, { x2, y2 - r }, { x1, y2 - r } );
754 addArc( { x1 + r, y1 + r }, { x1, y1 + r }, { x1 + r, y1 } );
755 addArc( { x2 - r, y1 + r }, { x2 - r, y1 }, { x2, y1 + r } );
756 addArc( { x2 - r, y2 - r }, { x2, y2 - r }, { x2 - r, y2 } );
757 addArc( { x1 + r, y2 - r }, { x1 + r, y2 }, { x1, y2 - r } );
800 double tolerance = 10;
831 if(
n1->m_type == GRAPH_NODE::TYPE::VIRTUAL ||
n2->m_type == GRAPH_NODE::TYPE::VIRTUAL )
835 &&
n1->m_parent ==
n2->m_parent
836 &&
n1->m_parent->GetType() == CREEP_SHAPE::TYPE::CIRCLE )
843 if( R1.
Cross( R2 ) > 0 )
855 aShapes.push_back( s );
860 &&
n1->m_parent ==
n2->m_parent
861 &&
n1->m_parent->GetType() == CREEP_SHAPE::TYPE::ARC )
870 if( R1.
Cross( R2 ) > 0 )
885 EDA_ANGLE midAngle = arc->AngleBetweenStartAndEnd( mid );
887 if( midAngle > arc->GetEndAngle() )
896 aShapes.push_back( s );
904 aShapes.push_back( s );
935 EDA_ANGLE maxAngle = angle1 > angle2 ? angle1 : angle2;
938 skipAngle += skipAngle;
939 EDA_ANGLE pointAngle = maxAngle - skipAngle;
949 pc.
a1 = maxAngle == angle2 ? a1->m_pos : a2->m_pos;
955 pc.
a2 = maxAngle == angle2 ? a2->m_pos : a1->m_pos;
958 std::shared_ptr<GRAPH_CONNECTION> gc = aG.
AddConnection( gnt, maxAngle == angle2 ? a2 : a1, pc );
961 gc->m_forceStraightLine =
true;
981 double delta = a2r - a1r;
988 for(
int i = 0; i <= 8; ++i )
990 double a = a1r +
delta * i / 8.0;
998 VECTOR2D distI( a1->m_pos - a2->m_pos );
999 VECTOR2D distD(
double( distI.
x ),
double( distI.
y ) );
1011 pc.
weight = std::max( weight, 0.0 );
1040 for(
int i = 0; i <= 8; ++i )
1042 double a = a1r + ( a2r - a1r ) * i / 8.0;
1050 double weight = abs(
m_radius * ( angle2 - angle1 ).AsRadians() );
1079 double aMaxSquaredWeight )
const
1081 std::vector<PATH_CONNECTION>
result;
1084 double halfWidth = this->
GetWidth() / 2;
1088 double length = ( start -
end ).EuclideanNorm();
1089 double projectedPos = cos( trackAngle.
AsRadians() ) * ( pointPos.
x - start.
x )
1090 + sin( trackAngle.
AsRadians() ) * ( pointPos.
y - start.
y );
1094 if( projectedPos <= 0 )
1096 newPoint = start + ( pointPos - start ).Resize( halfWidth );
1098 else if( projectedPos >= length )
1100 newPoint =
end + ( pointPos -
end ).Resize( halfWidth );
1104 double posOnSegment = ( start - pointPos ).SquaredEuclideanNorm()
1105 - (
end - pointPos ).SquaredEuclideanNorm();
1106 posOnSegment = posOnSegment / ( 2 * length ) + length / 2;
1108 newPoint = start + (
end - start ).Resize( posOnSegment );
1109 newPoint += ( pointPos - newPoint ).Resize( halfWidth );
1112 double weightSquared = ( pointPos - newPoint ).SquaredEuclideanNorm();
1114 if( weightSquared > aMaxSquaredWeight )
1120 pc.
weight = sqrt( weightSquared );
1128 double aMaxSquaredWeight )
const
1130 std::vector<PATH_CONNECTION>
result;
1133 double halfWidth = this->
GetWidth() / 2;
1137 double length = ( start -
end ).EuclideanNorm();
1140 double weightSquared = std::numeric_limits<double>::infinity();
1141 VECTOR2I PointOnTrack, PointOnCircle;
1145 double projectedPos1 = cos( trackAngle.
AsRadians() ) * ( circleCenter.
x - start.
x )
1146 + sin( trackAngle.
AsRadians() ) * ( circleCenter.
y - start.
y );
1147 double projectedPos2 = projectedPos1 + circleRadius;
1148 projectedPos1 = projectedPos1 - circleRadius;
1150 double trackSide = (
end - start ).Cross( circleCenter - start ) > 0 ? 1 : -1;
1152 if( ( projectedPos1 < 0 && projectedPos2 < 0 ) )
1160 else if( ( projectedPos1 > length && projectedPos2 > length ) )
1168 else if( ( projectedPos1 >= 0 ) && ( projectedPos1 <= length ) && ( projectedPos2 >= 0 )
1169 && ( projectedPos2 <= length ) )
1172 PointOnTrack = start;
1173 PointOnTrack += (
end - start ).Resize( projectedPos1 );
1174 PointOnTrack += (
end - start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1175 PointOnCircle = circleCenter - (
end - start ).Resize( circleRadius );
1176 weightSquared = ( PointOnCircle - PointOnTrack ).SquaredEuclideanNorm();
1178 if( weightSquared < aMaxSquaredWeight )
1181 pc.
a1 = PointOnTrack;
1182 pc.
a2 = PointOnCircle;
1183 pc.
weight = sqrt( weightSquared );
1187 PointOnTrack = start;
1188 PointOnTrack += (
end - start ).Resize( projectedPos2 );
1189 PointOnTrack += (
end - start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1190 PointOnCircle = circleCenter + (
end - start ).Resize( circleRadius );
1193 pc.
a1 = PointOnTrack;
1194 pc.
a2 = PointOnCircle;
1199 else if( ( ( projectedPos1 >= 0 ) && ( projectedPos1 <= length ) )
1200 && ( ( projectedPos2 > length ) || projectedPos2 < 0 ) )
1203 std::vector<PATH_CONNECTION> pcs = csc.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1205 if( pcs.size() < 2 )
1208 result.push_back( pcs.at( trackSide == 1 ? 1 : 0 ) );
1211 PointOnTrack = start;
1212 PointOnTrack += (
end - start ).Resize( projectedPos1 );
1213 PointOnTrack += (
end - start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1214 PointOnCircle = circleCenter - (
end - start ).Resize( circleRadius );
1215 weightSquared = ( PointOnCircle - PointOnTrack ).SquaredEuclideanNorm();
1217 if( weightSquared < aMaxSquaredWeight )
1220 pc.
a1 = PointOnTrack;
1221 pc.
a2 = PointOnCircle;
1222 pc.
weight = sqrt( weightSquared );
1227 else if( ( ( projectedPos2 >= 0 ) && ( projectedPos2 <= length ) )
1228 && ( ( projectedPos1 > length ) || projectedPos1 < 0 ) )
1231 std::vector<PATH_CONNECTION> pcs = csc.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1233 if( pcs.size() < 2 )
1236 result.push_back( pcs.at( trackSide == 1 ? 0 : 1 ) );
1238 PointOnTrack = start;
1239 PointOnTrack += (
end - start ).Resize( projectedPos2 );
1240 PointOnTrack += (
end - start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1241 PointOnCircle = circleCenter + (
end - start ).Resize( circleRadius );
1242 weightSquared = ( PointOnCircle - PointOnTrack ).SquaredEuclideanNorm();
1244 if( weightSquared < aMaxSquaredWeight )
1247 pc.
a1 = PointOnTrack;
1248 pc.
a2 = PointOnCircle;
1249 pc.
weight = sqrt( weightSquared );
1254 else if( projectedPos1 < 0 && projectedPos2 > length )
1259 std::vector<PATH_CONNECTION> startPcs = cscStart.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1261 if( startPcs.size() >= 2 )
1262 result.push_back( startPcs.at( trackSide == 1 ? 0 : 1 ) );
1265 std::vector<PATH_CONNECTION> endPcs = cscEnd.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1267 if( endPcs.size() >= 2 )
1268 result.push_back( endPcs.at( trackSide == 1 ? 1 : 0 ) );
1276 double aMaxSquaredWeight )
const
1278 std::vector<PATH_CONNECTION>
result;
1302 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1308 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1318 double aMaxSquaredWeight )
const
1320 std::vector<PATH_CONNECTION>
result;
1343 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1349 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1359 double aMaxSquaredWeight )
const
1361 std::vector<PATH_CONNECTION>
result;
1390 double aMaxSquaredWeight )
const
1392 std::vector<PATH_CONNECTION>
result;
1415 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1421 if( !
segmentIntersectsArc( pc.a1, pc.a2, beArcPos, beArcRadius, beArcStartAngle, beArcEndAngle ) )
1431 double aMaxSquaredWeight )
const
1433 std::vector<PATH_CONNECTION>
result;
1438 double weight = (
center - point ).EuclideanNorm() - R;
1440 if( weight > aMaxWeight )
1444 pc.
weight = std::max( weight, 0.0 );
1454 double aMaxSquaredWeight )
const
1456 std::vector<PATH_CONNECTION>
result;
1463 if( ( C1 - C2 ).SquaredEuclideanNorm() < ( R1 - R2 ) * ( R1 - R2 ) )
1469 double weight = ( C1 - C2 ).EuclideanNorm() - R1 - R2;
1471 if( weight > aMaxWeight || weight < 0 )
1475 pc.
weight = std::max( weight, 0.0 );
1476 pc.
a1 = ( C2 - C1 ).Resize( R1 ) + C1;
1477 pc.
a2 = ( C1 - C2 ).Resize( R2 ) + C2;
1484 double aMaxSquaredWeight )
const
1486 std::vector<PATH_CONNECTION>
result;
1490 double halfWidth = this->
GetWidth() / 2;
1492 EDA_ANGLE trackAngle( s_end - s_start );
1495 double length = ( s_start - s_end ).EuclideanNorm();
1496 double projectedPos = cos( trackAngle.
AsRadians() ) * ( pointPos.
x - s_start.
x )
1497 + sin( trackAngle.
AsRadians() ) * ( pointPos.
y - s_start.
y );
1499 if( ( projectedPos <= 0 ) || ( s_start == s_end ) )
1502 return csc.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1505 if( projectedPos >= length )
1508 return csc.
Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1512 double trackSide = ( s_end - s_start ).Cross( pointPos - s_start ) > 0 ? 1 : -1;
1515 pc.
a1 = s_start + ( s_end - s_start ).Resize( projectedPos )
1516 + ( s_end - s_start ).Perpendicular().
Resize( halfWidth ) * trackSide;
1517 pc.
a2 = ( pc.
a1 - pointPos ).Resize(
radius ) + pointPos;
1518 pc.
weight = ( pc.
a2 - pc.
a1 ).SquaredEuclideanNorm();
1520 if( pc.
weight <= aMaxSquaredWeight )
1531 double aMaxSquaredWeight )
const
1533 std::vector<PATH_CONNECTION>
result;
1538 double circleRadius = this->
GetRadius();
1546 if( ( circlePos - arcPos ).EuclideanNorm() > arcRadius + circleRadius )
1548 const std::vector<PATH_CONNECTION>& pcs = this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
1550 if( pcs.size() == 1 )
1556 result.push_back( pcs[0] );
1568 std::vector<PATH_CONNECTION> pcs1 = this->
Paths( csc1, aMaxWeight, aMaxSquaredWeight );
1569 std::vector<PATH_CONNECTION> pcs2 = this->
Paths( csc2, aMaxWeight, aMaxSquaredWeight );
1573 if( !bestPath || ( ( bestPath->
weight > pc.weight ) && ( pc.weight > 0 ) ) )
1579 if( !bestPath || ( ( bestPath->
weight > pc.weight ) && ( pc.weight > 0 ) ) )
1587 if( ( circlePos - arcPos ).SquaredEuclideanNorm() < arcRadius * arcRadius )
1589 if( circlePos != arcPos )
1595 pc3.
weight = std::max( arcRadius - ( circlePos - arcPos ).EuclideanNorm() - circleRadius, 0.0 );
1596 pc3.
a1 = circlePos + ( circlePos - arcPos ).Resize( circleRadius );
1597 pc3.
a2 = arcPos + ( circlePos - arcPos ).Resize( arcRadius - aS2.
GetWidth() / 2 );
1605 if( bestPath && bestPath->
weight > 0 )
1607 result.push_back( *bestPath );
1615 double aMaxSquaredWeight )
const
1617 std::vector<PATH_CONNECTION>
result;
1621 double halfWidth1 = this->
GetWidth() / 2;
1625 double halfWidth2 = aS2.
GetWidth() / 2;
1630 std::vector<PATH_CONNECTION> pcs;
1631 pcs = this->
Paths( csc, aMaxWeight, aMaxSquaredWeight );
1633 if( pcs.size() < 1 )
1639 if( pcs.size() > 0 )
1641 circlePoint = pcs[0].a1;
1645 if( testAngle < aS2.
GetEndAngle() && pcs.size() > 0 )
1647 result.push_back( pcs[0] );
1657 if( !bestPath || ( bestPath->
weight > pc.weight ) )
1663 if( !bestPath || ( bestPath->
weight > pc.weight ) )
1672 if( !bestPath || ( bestPath->
weight > pc.weight ) )
1679 if( !bestPath || ( bestPath->
weight > pc.weight ) )
1684 result.push_back( *bestPath );
1703 t = std::max( 0.0, std::min( 1.0, t ) );
1705 return A + ( AB * t );
1711 double aMaxSquaredWeight )
const
1713 std::vector<PATH_CONNECTION>
result;
1717 double halfWidth1 = this->
GetWidth() / 2;
1722 double halfWidth2 = aS2.
GetWidth() / 2;
1730 double dist1 = ( P1 -
C ).SquaredEuclideanNorm();
1731 double dist2 = ( P2 -
D ).SquaredEuclideanNorm();
1732 double dist3 = ( P3 -
A ).SquaredEuclideanNorm();
1733 double dist4 = ( P4 -
B ).SquaredEuclideanNorm();
1736 double min_dist = dist1;
1740 if( dist2 < min_dist )
1747 if( dist3 < min_dist )
1754 if( dist4 < min_dist )
1763 pc.
a1 = closest1 + ( closest2 - closest1 ).Resize( halfWidth1 );
1764 pc.
a2 = closest2 + ( closest1 - closest2 ).Resize( halfWidth2 );
1765 pc.
weight = std::max( sqrt( min_dist ) - halfWidth1 - halfWidth2, 0.0 );
1767 if( pc.
weight <= aMaxWeight )
1775 double aMaxSquaredWeight )
const
1777 std::vector<PATH_CONNECTION>
result;
1783 double dist = ( center1 - center2 ).EuclideanNorm();
1787 double reach = aMaxWeight + R1;
1789 if( dist == 0 || dist * dist > reach * reach + R2 * R2 )
1798 double weight = std::max( R2 - dist - R1, 0.0 );
1800 if( weight > aMaxWeight )
1803 double radialAngle = circleAngle +
M_PI;
1804 double cx = cos( radialAngle );
1805 double cy = sin( radialAngle );
1821 double weight = sqrt( dist * dist - R2 * R2 ) - R1;
1822 double theta = asin( R2 / dist );
1823 double psi = acos( R2 / dist );
1825 if( weight > aMaxWeight )
1829 pc.
weight = std::max( weight, 0.0 );
1834 pStart =
VECTOR2I( R1 * cos( theta + circleAngle ), R1 * sin( theta + circleAngle ) );
1836 pEnd =
VECTOR2I( -R2 * cos( psi - circleAngle ), R2 * sin( psi - circleAngle ) );
1843 pStart =
VECTOR2I( R1 * cos( -theta + circleAngle ), R1 * sin( -theta + circleAngle ) );
1845 pEnd =
VECTOR2I( -R2 * cos( -psi - circleAngle ), R2 * sin( -psi - circleAngle ) );
1857 double aMaxSquaredWeight )
const
1859 std::vector<PATH_CONNECTION>
result;
1875 if( ( point - arcCenter ).SquaredEuclideanNorm() >
radius *
radius )
1878 return circle.Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1883 pc.
weight = std::max( (
radius - width / 2 ) - ( point - arcCenter ).EuclideanNorm(), 0.0 );
1884 pc.
a1 = ( point - arcCenter ).Resize(
radius - width / 2 ) + arcCenter;
1897 if( ( point - this->
GetStartPoint() ).SquaredEuclideanNorm()
1898 > ( point - this->
GetEndPoint() ).SquaredEuclideanNorm() )
1908 return circle.Paths( aS2, aMaxWeight, aMaxSquaredWeight );
1914 double aMaxSquaredWeight )
const
1916 std::vector<PATH_CONNECTION>
result;
1925 bestPath.
weight = std::numeric_limits<double>::infinity();
1934 for(
const std::vector<PATH_CONNECTION>& pcs : { csc1.
Paths( csc2, aMaxWeight, aMaxSquaredWeight ),
1935 this->
Paths( csc2, aMaxWeight, aMaxSquaredWeight ),
1936 csc1.
Paths( aS2, aMaxWeight, aMaxSquaredWeight ) } )
1948 for(
const std::vector<PATH_CONNECTION>& pcs : { this->
Paths( csc5, aMaxWeight, aMaxSquaredWeight ),
1949 this->
Paths( csc6, aMaxWeight, aMaxSquaredWeight ),
1950 csc3.
Paths( aS2, aMaxWeight, aMaxSquaredWeight ),
1951 csc4.
Paths( aS2, aMaxWeight, aMaxSquaredWeight ) } )
1955 if( bestPath.
weight > pc.weight )
1960 if( bestPath.
weight != std::numeric_limits<double>::infinity() )
1961 result.push_back( bestPath );
1968 std::vector<VECTOR2I>* aIntersectPoints )
1970 SEG segment( p1, p2 );
1973 std::vector<VECTOR2I> intersectionPoints;
1978 std::visit( visitor, geom1 );
1986 return ( a - b ).SquaredEuclideanNorm() <= toleranceSq;
1989 std::vector<VECTOR2I> filtered;
1991 for(
const VECTOR2I& ip : intersectionPoints )
1993 if( !coincident( ip, p1 ) && !coincident( ip, p2 ) )
1994 filtered.push_back( ip );
1997 if( aIntersectPoints )
2000 aIntersectPoints->push_back( point );
2003 return filtered.size() > 0;
2007 const std::vector<BOARD_ITEM*>& aBe,
2008 const std::vector<const BOARD_ITEM*>& aDontTestAgainst,
2009 int aMinGrooveWidth )
2011 std::vector<VECTOR2I> intersectionPoints;
2012 bool TestGrooveWidth = aMinGrooveWidth > 0;
2016 if( count( aDontTestAgainst.begin(), aDontTestAgainst.end(), be ) > 0 )
2029 if( intersects && !TestGrooveWidth )
2051 bool intersects =
false;
2056 intersectionPoints );
2058 intersectionPoints );
2064 intersectionPoints );
2066 intersectionPoints );
2069 if( intersects && !TestGrooveWidth )
2075 struct CornerArcRange
2082 std::vector<CornerArcRange> arcs;
2089 arcs.push_back( { { x1 + r, y1 + r },
2092 arcs.push_back( { { x2 - r, y1 + r },
2096 else if( w == 2 * r )
2099 arcs.push_back( { { x1 + r, y1 + r },
2102 arcs.push_back( { { x1 + r, y2 - r },
2120 for(
const CornerArcRange& ca : arcs )
2123 ca.startAngle, ca.endAngle,
2124 &intersectionPoints );
2126 if( arcIntersects && !TestGrooveWidth )
2137 bool intersects =
false;
2143 if( intersects && !TestGrooveWidth )
2154 if( points.size() < 2 )
2157 VECTOR2I prevPoint = points.back();
2159 bool intersects =
false;
2167 if( intersects && !TestGrooveWidth )
2180 if( intersects && !TestGrooveWidth )
2196 if( intersects && !TestGrooveWidth )
2207 if( intersectionPoints.size() <= 0 )
2210 if( intersectionPoints.size() % 2 != 0 )
2213 int minx = intersectionPoints[0].x;
2214 int maxx = intersectionPoints[0].x;
2215 int miny = intersectionPoints[0].y;
2216 int maxy = intersectionPoints[0].y;
2218 for(
const VECTOR2I& v : intersectionPoints )
2220 minx = v.x < minx ? v.x : minx;
2221 maxx = v.x > maxx ? v.x : maxx;
2222 miny = v.x < miny ? v.x : miny;
2223 maxy = v.x > maxy ? v.x : maxy;
2226 if( abs( maxx - minx ) > abs( maxy - miny ) )
2228 std::sort( intersectionPoints.begin(), intersectionPoints.end(),
2236 std::sort( intersectionPoints.begin(), intersectionPoints.end(),
2243 int GVSquared = aMinGrooveWidth * aMinGrooveWidth;
2245 for(
size_t i = 0; i < intersectionPoints.size(); i += 2 )
2247 if( intersectionPoints[i].SquaredDistance( intersectionPoints[i + 1] ) > GVSquared )
2257 double maxWeight = aMaxWeight;
2258 double maxWeightSquared = maxWeight * maxWeight;
2259 std::vector<PATH_CONNECTION>
result;
2278 if( cuarc1 && cuarc2 )
2279 return cuarc1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2280 if( cuarc1 && cucircle2 )
2281 return cuarc1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2282 if( cuarc1 && cusegment2 )
2283 return cuarc1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2284 if( cucircle1 && cuarc2 )
2285 return cucircle1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2286 if( cucircle1 && cucircle2 )
2287 return cucircle1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2288 if( cucircle1 && cusegment2 )
2289 return cucircle1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2290 if( cusegment1 && cuarc2 )
2291 return cusegment1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2292 if( cusegment1 && cucircle2 )
2293 return cusegment1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2294 if( cusegment1 && cusegment2 )
2295 return cusegment1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2300 if( cuarc1 && bearc2 )
2301 return cuarc1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2302 if( cuarc1 && becircle2 )
2303 return cuarc1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2304 if( cuarc1 && bepoint2 )
2305 return cuarc1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2306 if( cucircle1 && bearc2 )
2307 return cucircle1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2308 if( cucircle1 && becircle2 )
2309 return cucircle1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2310 if( cucircle1 && bepoint2 )
2311 return cucircle1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2312 if( cusegment1 && bearc2 )
2313 return cusegment1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2314 if( cusegment1 && becircle2 )
2315 return cusegment1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2316 if( cusegment1 && bepoint2 )
2317 return cusegment1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2321 if( cuarc2 && bearc1 )
2322 return bearc1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2323 if( cuarc2 && becircle1 )
2324 return becircle1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2325 if( cuarc2 && bepoint1 )
2326 return bepoint1->
Paths( *cuarc2, maxWeight, maxWeightSquared );
2327 if( cucircle2 && bearc1 )
2328 return bearc1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2329 if( cucircle2 && becircle1 )
2330 return becircle1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2331 if( cucircle2 && bepoint1 )
2332 return bepoint1->
Paths( *cucircle2, maxWeight, maxWeightSquared );
2333 if( cusegment2 && bearc1 )
2334 return bearc1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2335 if( cusegment2 && becircle1 )
2336 return becircle1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2337 if( cusegment2 && bepoint1 )
2338 return bepoint1->
Paths( *cusegment2, maxWeight, maxWeightSquared );
2343 if( bearc1 && bearc2 )
2344 return bearc1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2345 if( bearc1 && becircle2 )
2346 return bearc1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2347 if( bearc1 && bepoint2 )
2348 return bearc1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2349 if( becircle1 && bearc2 )
2350 return becircle1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2351 if( becircle1 && becircle2 )
2352 return becircle1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2353 if( becircle1 && bepoint2 )
2354 return becircle1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2355 if( bepoint1 && bearc2 )
2356 return bepoint1->
Paths( *bearc2, maxWeight, maxWeightSquared );
2357 if( bepoint1 && becircle2 )
2358 return bepoint1->
Paths( *becircle2, maxWeight, maxWeightSquared );
2359 if( bepoint1 && bepoint2 )
2360 return bepoint1->
Paths( *bepoint2, maxWeight, maxWeightSquared );
2366 std::vector<std::shared_ptr<GRAPH_CONNECTION>>& aResult )
2368 if( !aFrom || !aTo )
2375 std::unordered_map<GRAPH_NODE*, double> distances;
2376 std::unordered_map<GRAPH_NODE*, GRAPH_NODE*> previous;
2381 using QUEUE_ITEM = std::pair<double, GRAPH_NODE*>;
2383 auto cmp = [](
const QUEUE_ITEM& aLeft,
const QUEUE_ITEM& aRight )
2385 if( aLeft.first == aRight.first )
2386 return aLeft.second > aRight.second;
2387 return aLeft.first > aRight.first;
2389 std::priority_queue<QUEUE_ITEM, std::vector<QUEUE_ITEM>,
decltype( cmp )> pq( cmp );
2392 for(
const std::shared_ptr<GRAPH_NODE>& node :
m_nodes )
2394 if( node !=
nullptr )
2395 distances[node.get()] = std::numeric_limits<double>::infinity();
2398 distances[aFrom.get()] = 0.0;
2399 distances[aTo.get()] = std::numeric_limits<double>::infinity();
2400 pq.push( { 0.0, aFrom.get() } );
2403 while( !pq.empty() )
2405 auto [dist, current] = pq.top();
2410 if( dist > distances[current] )
2413 if( current == aTo.get() )
2419 for(
const std::shared_ptr<GRAPH_CONNECTION>& connection : current->m_node_conns )
2421 GRAPH_NODE* neighbor = ( connection->n1 ).get() == current ? ( connection->n2 ).get()
2422 : ( connection->n1 ).get();
2428 if( connection->m_path.weight < 0.0 )
2430 wxLogTrace(
"CREEPAGE",
"Negative weight connection found. Ignoring connection." );
2434 double alt = distances[current] + connection->m_path.weight;
2436 if( alt < distances[neighbor] )
2438 distances[neighbor] = alt;
2439 previous[neighbor] = current;
2440 pq.push( { alt, neighbor } );
2445 double pathWeight = distances[aTo.get()];
2448 if( pathWeight == std::numeric_limits<double>::infinity() )
2449 return std::numeric_limits<double>::infinity();
2454 while( step != aFrom.get() )
2458 for(
const std::shared_ptr<GRAPH_CONNECTION>& node_conn : step->
m_node_conns )
2460 if( ( ( node_conn->n1 ).get() == prevNode && ( node_conn->n2 ).get() == step )
2461 || ( ( node_conn->n1 ).get() == step && ( node_conn->n2 ).get() == prevNode ) )
2463 aResult.push_back( node_conn );
2481 switch( aShape.
Type() )
2496 newshape =
dynamic_cast<CREEP_SHAPE*
>( cucircle );
2511 start = arc.
GetP0();
2517 start = arc.
GetP1();
2532 int nbShapes =
static_cast<const SHAPE_COMPOUND*
>( &aShape )->Shapes().size();
2533 for(
const SHAPE* subshape : (
static_cast<const SHAPE_COMPOUND*
>( &aShape )->Shapes() ) )
2538 if( !( ( subshape->Type() ==
SH_RECT ) && ( nbShapes == 5 ) ) )
2539 Addshape( *subshape, aConnectTo, aParent );
2551 const SEG object = *it;
2553 Addshape( segment, aConnectTo, aParent );
2568 Addshape( segment, aConnectTo, aParent );
2591 if( point != prevPoint )
2623 std::shared_ptr<GRAPH_NODE> gnShape =
nullptr;
2627 switch( aShape.
Type() )
2638 gnShape->m_net = aConnectTo->m_net;
2639 std::shared_ptr<GRAPH_CONNECTION> gc =
AddConnection( gnShape, aConnectTo );
2642 gc->m_path.m_show =
false;
2652 const std::set<int>* aRelevantNets )
2654 auto irrelevantPair = [&](
const std::shared_ptr<GRAPH_NODE>& gn1,
2655 const std::shared_ptr<GRAPH_NODE>& gn2 ) ->
bool
2657 return aRelevantNets && gn1->m_parent && gn2->m_parent && gn1->m_parent->IsConductive()
2658 && gn2->m_parent->IsConductive() && !aRelevantNets->count( gn1->m_net )
2659 && !aRelevantNets->count( gn2->m_net );
2662 std::vector<std::shared_ptr<GRAPH_NODE>> nodes;
2663 std::mutex nodes_lock;
2666 std::vector<CREEPAGE_TRACK_ENTRY*> trackEntries;
2667 TRACK_RTREE::Builder trackBuilder;
2675 std::shared_ptr<SHAPE> sh = track->GetEffectiveShape();
2680 entry->
segment =
SEG( track->GetStart(), track->GetEnd() );
2681 entry->
layer = aLayer;
2682 entry->
halfWidth = track->GetWidth() / 2;
2683 entry->
track = track;
2685 BOX2I bbox = track->GetBoundingBox();
2686 int minCoords[2] = { bbox.
GetX(), bbox.
GetY() };
2688 trackBuilder.Add( minCoords, maxCoords, entry );
2689 trackEntries.push_back( entry );
2697 std::copy_if(
m_nodes.begin(),
m_nodes.end(), std::back_inserter( nodes ),
2698 [&](
const std::shared_ptr<GRAPH_NODE>& gn )
2700 return gn && gn->m_parent && gn->m_connectDirectly && ( gn->m_type != GRAPH_NODE::TYPE::VIRTUAL );
2703 std::sort( nodes.begin(), nodes.end(),
2704 [](
const std::shared_ptr<GRAPH_NODE>& gn1,
const std::shared_ptr<GRAPH_NODE>& gn2 )
2706 return gn1->m_parent < gn2->m_parent
2707 || ( gn1->m_parent == gn2->m_parent && gn1->m_net < gn2->m_net );
2712 std::unordered_map<const BOARD_ITEM*, std::unordered_map<int, std::vector<std::shared_ptr<GRAPH_NODE>>>> parent_net_groups;
2713 std::unordered_map<const BOARD_ITEM*, BOX2I> parent_bboxes;
2714 std::vector<const BOARD_ITEM*> parent_keys;
2716 for(
const auto& gn : nodes )
2718 const BOARD_ITEM* parent = gn->m_parent->GetParent();
2720 if( parent_net_groups[parent].
empty() )
2722 parent_keys.push_back( parent );
2727 parent_net_groups[parent][gn->m_net].push_back( gn );
2731 std::vector<std::pair<std::shared_ptr<GRAPH_NODE>, std::shared_ptr<GRAPH_NODE>>> work_items;
2736 int64_t maxDist =
static_cast<int64_t
>( aMaxWeight );
2744 std::vector<ParentEntry> parentEntries;
2746 for(
const auto* parent : parent_keys )
2751 entry.parent = parent;
2752 entry.bbox = parent_bboxes[parent];
2753 parentEntries.push_back( entry );
2759 for( ParentEntry& entry : parentEntries )
2761 int minCoords[2] = { entry.bbox.GetLeft(), entry.bbox.GetTop() };
2762 int maxCoords[2] = { entry.bbox.GetRight(), entry.bbox.GetBottom() };
2763 parentBuilder.
Add( minCoords, maxCoords, &entry );
2766 auto parentIndex = parentBuilder.
Build();
2769 std::mutex work_items_lock;
2771 auto searchParent = [&](
size_t i ) ->
bool
2773 const ParentEntry& entry1 = parentEntries[i];
2775 BOX2I bbox1 = entry1.bbox;
2777 std::vector<std::pair<std::shared_ptr<GRAPH_NODE>, std::shared_ptr<GRAPH_NODE>>> localWorkItems;
2780 int searchMin[2] = { bbox1.
GetLeft() - (int) maxDist, bbox1.
GetTop() - (int) maxDist };
2781 int searchMax[2] = { bbox1.
GetRight() + (int) maxDist, bbox1.
GetBottom() + (int) maxDist };
2783 auto parentVisitor = [&]( ParentEntry* entry2 ) ->
bool
2788 if( parent1 >= parent2 )
2792 BOX2I bbox2 = entry2->bbox;
2794 int64_t bboxDistX = 0;
2801 int64_t bboxDistY = 0;
2808 int64_t bboxDistSq = bboxDistX * bboxDistX + bboxDistY * bboxDistY;
2810 if( bboxDistSq > maxDist * maxDist )
2814 auto it1 = parent_net_groups.find( parent1 );
2815 auto it2 = parent_net_groups.find( parent2 );
2817 if( it1 == parent_net_groups.end() || it2 == parent_net_groups.end() )
2820 for(
const auto& [net1, nodes1] : it1->second )
2822 for(
const auto& [net2, nodes2] : it2->second )
2825 if( net1 == net2 && !nodes1.empty() && !nodes2.empty() )
2827 if( nodes1[0]->m_parent->IsConductive()
2828 && nodes2[0]->m_parent->IsConductive() )
2832 for(
const auto& gn1 : nodes1 )
2834 for(
const auto& gn2 : nodes2 )
2836 VECTOR2I pos1 = gn1->m_parent->GetPos();
2837 VECTOR2I pos2 = gn2->m_parent->GetPos();
2838 int r1 = gn1->m_parent->GetRadius();
2839 int r2 = gn2->m_parent->GetRadius();
2841 int64_t centerDistSq = ( pos1 - pos2 ).SquaredEuclideanNorm();
2842 double threshold = aMaxWeight + r1 + r2;
2843 double thresholdSq = threshold * threshold;
2845 if( (
double) centerDistSq > thresholdSq )
2848 if( irrelevantPair( gn1, gn2 ) )
2851 localWorkItems.push_back( { gn1, gn2 } );
2860 parentIndex.Search( searchMin, searchMax, parentVisitor );
2863 if( !localWorkItems.empty() )
2865 std::lock_guard<std::mutex> lock( work_items_lock );
2866 work_items.insert( work_items.end(), localWorkItems.begin(), localWorkItems.end() );
2873 if( parentEntries.size() > 100 &&
tp.get_tasks_total() <
tp.get_thread_count() - 4 )
2875 auto ret =
tp.submit_loop( 0, parentEntries.size(), searchParent );
2877 for(
auto& r : ret )
2885 for(
size_t i = 0; i < parentEntries.size(); ++i )
2894 for(
const auto& [parent, net_groups] : parent_net_groups )
2896 std::vector<std::shared_ptr<GRAPH_NODE>> sameParentNodes;
2898 for(
const auto& [net, nodeList] : net_groups )
2899 sameParentNodes.insert( sameParentNodes.end(), nodeList.begin(), nodeList.end() );
2901 for(
size_t i = 0; i < sameParentNodes.size(); i++ )
2903 for(
size_t j = i + 1; j < sameParentNodes.size(); j++ )
2905 auto& gn1 = sameParentNodes[i];
2906 auto& gn2 = sameParentNodes[j];
2909 if( gn1->m_parent == gn2->m_parent )
2913 if( gn1->m_parent->IsConductive() && gn2->m_parent->IsConductive()
2914 && gn1->m_net == gn2->m_net )
2919 VECTOR2I pos1 = gn1->m_parent->GetPos();
2920 VECTOR2I pos2 = gn2->m_parent->GetPos();
2921 int r1 = gn1->m_parent->GetRadius();
2922 int r2 = gn2->m_parent->GetRadius();
2924 int64_t centerDistSq = ( pos1 - pos2 ).SquaredEuclideanNorm();
2925 double threshold = aMaxWeight + r1 + r2;
2926 double thresholdSq = threshold * threshold;
2928 if( (
double) centerDistSq > thresholdSq )
2931 if( irrelevantPair( gn1, gn2 ) )
2934 work_items.push_back( { gn1, gn2 } );
2939 auto processWorkItems =
2940 [&](
size_t idx ) ->
bool
2942 auto& [gn1, gn2] = work_items[idx];
2950 std::vector<const BOARD_ITEM*> IgnoreForTest;
2961 IgnoreForTest.push_back( shape1->
GetParent() );
2964 IgnoreForTest.push_back( shape2->
GetParent() );
2974 std::shared_ptr<GRAPH_NODE> connect1 = gn1, connect2 = gn2;
2975 std::lock_guard<std::mutex> lock( nodes_lock );
2978 if( gn1->m_parent->GetType() != CREEP_SHAPE::TYPE::POINT_TYPE )
2981 gnt1->m_connectDirectly =
false;
2984 if( gn1->m_parent->IsConductive() )
2986 if( std::shared_ptr<GRAPH_CONNECTION> gc =
AddConnection( gn1, gnt1 ) )
2987 gc->m_path.m_show =
false;
2992 if( gn2->m_parent->GetType() != CREEP_SHAPE::TYPE::POINT_TYPE )
2995 gnt2->m_connectDirectly =
false;
2998 if( gn2->m_parent->IsConductive() )
3000 if( std::shared_ptr<GRAPH_CONNECTION> gc =
AddConnection( gn2, gnt2 ) )
3001 gc->m_path.m_show =
false;
3013 if(
tp.get_tasks_total() >=
tp.get_thread_count() - 4 )
3015 for(
size_t ii = 0; ii < work_items.size(); ii++ )
3016 processWorkItems( ii );
3020 auto ret =
tp.submit_loop( 0, work_items.size(), processWorkItems );
3022 for(
size_t ii = 0; ii < ret.size(); ii++ )
3029 while( r.wait_for( std::chrono::milliseconds( 100 ) ) != std::future_status::ready ){}
3041 std::vector<std::shared_ptr<GRAPH_CONNECTION>> toRemove;
3044 for( std::shared_ptr<GRAPH_CONNECTION>& gc :
m_connections )
3046 if( gc && ( gc->m_path.weight > aWeightLimit ) )
3047 toRemove.push_back( gc );
3051 for(
const std::shared_ptr<GRAPH_CONNECTION>& gc : toRemove )
3061 for( std::shared_ptr<GRAPH_NODE> gn : { aGc->n1, aGc->n2 } )
3065 gn->m_node_conns.erase( aGc );
3067 if( gn->m_node_conns.empty() && aDelete )
3070 [&gn](
const std::shared_ptr<GRAPH_NODE>& node )
3072 return node.get() == gn.get();
3097 for(
size_t i = aConnectionCount; i < vectorSize; i++ )
3101 m_nodes.resize( aNodeCount,
nullptr );
3106 for(
size_t i = 0; i < aNodeCount; ++i )
3117 std::shared_ptr<GRAPH_NODE> gn =
FindNode( aType, parent, pos );
3122 gn = std::make_shared<GRAPH_NODE>( aType, parent, pos );
3132 std::shared_ptr<GRAPH_NODE> gn = std::make_shared<GRAPH_NODE>( GRAPH_NODE::TYPE::VIRTUAL,
nullptr );
3140 std::shared_ptr<GRAPH_NODE>& aN2,
3146 wxASSERT_MSG( ( aN1 != aN2 ),
"Creepage: a connection connects a node to itself" );
3148 std::shared_ptr<GRAPH_CONNECTION> gc = std::make_shared<GRAPH_CONNECTION>( aN1, aN2, aPc );
3150 aN1->m_node_conns.insert( gc );
3151 aN2->m_node_conns.insert( gc );
3158 std::shared_ptr<GRAPH_NODE>& aN2 )
3175 auto it =
m_nodeset.find( std::make_shared<GRAPH_NODE>( aType, aParent, aPos ) );
3188 virtualNode->m_net = aNetCode;
3192 for(
PAD*
pad : footprint->Pads() )
3194 if(
pad->GetNetCode() != aNetCode || !
pad->IsOnLayer( aLayer ) )
3197 if( std::shared_ptr<SHAPE> padShape =
pad->GetEffectiveShape( aLayer ) )
3204 if( track->GetNetCode() != aNetCode || !track->IsOnLayer( aLayer ) )
3207 if( std::shared_ptr<SHAPE> shape = track->GetEffectiveShape() )
3208 Addshape( *shape, virtualNode, track );
3214 if( zone->GetIsRuleArea() )
3217 if( zone->GetNetCode() != aNetCode || !zone->IsOnLayer( aLayer ) )
3220 if( std::shared_ptr<SHAPE> shape = zone->GetEffectiveShape( aLayer ) )
3221 Addshape( *shape, virtualNode, zone );
3228 if( drawing->IsConnected() )
3236 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, DRC_CONSTRAINT_T aUsage=NULL_CONSTRAINT) 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, SHAPE_ELLIPSE, 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