63 return via->GetWidth( aLayer );
68 return std::min(
pad->GetSize( aLayer ).x,
pad->GetSize( aLayer ).y );
103 bool nonRound =
false;
107 static_cast<PAD*
>( aItem )->Padstack().ForEachUniqueLayer(
152 for(
PCB_LAYER_ID layer : aItem->GetLayerSet().CuStack() )
157 indexCopper( track );
165 indexCopper( drawing );
179 return connected->GetNetCode();
193 std::shared_ptr<DRC_ENGINE> drcEngine = bds.
m_DRCEngine;
214const std::vector<std::set<const BOARD_ITEM*>>&
222 std::vector<std::set<const BOARD_ITEM*>> islands;
224 m_board->GetConnectivity()->GetZoneIslandConnections( aZone, aLayer, &islands );
237 if( zone->IsTeardropArea() )
241 if( !zone->IsOnLayer( layer ) )
244 if( zone->GetNetCode() != aTrack->
GetNetCode() )
248 if( !zone->HasFilledPolysForLayer( layer ) )
253 for(
const std::set<const BOARD_ITEM*>& island :
zoneConnections( zone, layer ) )
255 if( island.count( aPadOrVia ) && island.count( aTrack ) )
265 const std::vector<const BOARD_ITEM*>& aExempt )
const
267 if( aPoints.size() < 3 )
274 teardrop.
Append( pt.x, pt.y );
289 std::vector<std::shared_ptr<SHAPE>> anchorShapes;
290 std::map<const BOARD_ITEM*, bool> touchesAnchor;
296 if( std::shared_ptr<SHAPE> shape = item->GetEffectiveShape( layer ) )
297 anchorShapes.push_back( shape );
301 auto touchesTeardropAnchor =
304 auto it = touchesAnchor.find( aItem );
306 if( it == touchesAnchor.end() )
308 std::shared_ptr<SHAPE> shape = aItem->GetEffectiveShape( layer );
309 bool touches =
false;
313 touches = std::any_of( anchorShapes.begin(), anchorShapes.end(),
314 [&](
const std::shared_ptr<SHAPE>& aAnchor )
316 return aAnchor->Collide( shape.get() );
320 it = touchesAnchor.emplace( aItem, touches ).first;
326 auto isSameConductor =
332 return itemNet == netcode;
334 return itemNet <= 0 && touchesTeardropAnchor( aItem );
340 if(
alg::contains( aExempt, aItem ) || isSameConductor( aItem ) )
353 if( collides( item->parent, item->shape ) )
362 const int bmin[2] = { box.
GetX(), box.
GetY() };
364 bool collision =
false;
367 [&](
ZONE* aCreated ) ->
bool
369 collision = collides( aCreated, aCreated->GetEffectiveShape( layer ).get() );
373 it->second.Search( bmin, bmax, visit );
379 std::vector<VECTOR2I>& aPoints,
385 const std::vector<const BOARD_ITEM*> exempt = { aOther, aSourceTrack, aTrack };
406 std::vector<VECTOR2I> fitted;
409 [&](
int aWidth ) ->
bool
411 std::vector<VECTOR2I> candidate;
421 fitted = std::move( candidate );
427 if( !tryWidth( lo ) )
430 for(
int ii = 0; ii < 4 && hi - lo > 1; ++ii )
432 int mid = lo + ( hi - lo ) / 2;
434 if( tryWidth( mid ) )
440 aPoints = std::move( fitted );
442 return !aPoints.empty();
447 const VECTOR2I& aInsidePoint )
const
451 return std::numeric_limits<int>::max();
454 double len =
delta.EuclideanNorm();
457 return std::numeric_limits<int>::max();
459 int maxError =
m_board->GetDesignSettings().m_MaxError;
463 if(
IsRound( aOther, aLayer ) )
469 wxCHECK_MSG( aOther->
Type() ==
PCB_PAD_T, 0, wxT(
"Expected non-round item to be PAD" ) );
470 static_cast<PAD*
>( aOther )->TransformShapeToPolygon( shapebuffer, aLayer, 0, maxError,
ERROR_INSIDE );
482 std::vector<SHAPE_LINE_CHAIN::INTERSECTION> pts;
484 for(
int ii = 0; ii < shapebuffer.
OutlineCount(); ++ii )
490 for(
int jj = 0; jj < shapebuffer.
HoleCount( ii ); ++jj )
500 return std::numeric_limits<int>::max();
504 std::vector<double> proj;
505 proj.reserve( pts.size() );
508 proj.push_back( ( hit.p - extStart ).Dot( dir ) );
510 std::sort( proj.begin(), proj.end() );
512 double insideProj = (
VECTOR2D( aInsidePoint ) -
VECTOR2D( extStart ) ).Dot( dir );
514 for(
size_t ii = 0; ii + 1 < proj.size(); ++ii )
517 KiROUND( dir.
y * ( proj[ii] + proj[ii + 1] ) / 2 ) );
519 if( !shapebuffer.
Contains( spanMid ) )
522 if( insideProj >= proj[ii] && insideProj <= proj[ii + 1] )
523 return KiROUND( proj[ii + 1] - proj[ii] );
527 return std::numeric_limits<int>::max();
543 return trackItem != aTrackRef && trackItem != aSourceTrack;
548 PCB_TRACK* curr_track = static_cast<PCB_TRACK*>( trackItem );
551 if( EDA_ITEM_FLAGS match = curr_track->IsPointOnEnds( aEndPoint, m_tolerance ) )
558 double previous_len = candidate->GetLength();
559 double curr_len = curr_track->GetLength();
561 if( previous_len >= curr_len )
566 candidate = curr_track;
599 const VECTOR2I& aOtherPos, std::vector<VECTOR2I>& pts )
const
601 int maxError =
m_board->GetDesignSettings().m_MaxError;
621 double minVpercent = double( aTrackHalfWidth ) /
radius;
622 double weaken = (Vpercent - minVpercent) / ( 1 - minVpercent ) /
radius;
634 vecC = pts[2] - aOtherPos;
644 vecE = pts[4] - aOtherPos;
647 double biasBC = 0.5 *
SEG( pts[1], pts[2] ).
Length();
648 double biasAE = 0.5 *
SEG( pts[4], pts[0] ).
Length();
650 VECTOR2I tangentC =
VECTOR2I( pts[2].x - vecC.
y * biasBC * weaken, pts[2].y + vecC.
x * biasBC * weaken );
651 VECTOR2I tangentE =
VECTOR2I( pts[4].x + vecE.
y * biasAE * weaken, pts[4].y - vecE.
x * biasAE * weaken );
653 VECTOR2I tangentB =
VECTOR2I( pts[1].x - aTrackDir.
x * biasBC, pts[1].y - aTrackDir.
y * biasBC );
654 VECTOR2I tangentA =
VECTOR2I( pts[0].x - aTrackDir.
x * biasAE, pts[0].y - aTrackDir.
y * biasAE );
656 std::vector<VECTOR2I> curve_pts;
660 aPoly.push_back( corner );
662 aPoly.push_back( pts[3] );
668 aPoly.push_back( corner );
684 double aBias,
const VECTOR2I& aDesiredDir )
686 VECTOR2I radial = aAnchor - aCornerCenter;
698 int64_t dot1 =
static_cast<int64_t
>( tangent1.
x ) * aDesiredDir.
x
699 +
static_cast<int64_t
>( tangent1.
y ) * aDesiredDir.
y;
700 int64_t dot2 =
static_cast<int64_t
>( tangent2.
x ) * aDesiredDir.
x
701 +
static_cast<int64_t
>( tangent2.
y ) * aDesiredDir.
y;
703 VECTOR2I tangent = ( dot1 > dot2 ) ? tangent1 : tangent2;
724 VECTOR2I localPt = aPoint - aPadPos;
727 int halfW = aPadSize.
x / 2;
728 int halfH = aPadSize.
y / 2;
732 int radius = std::min( halfW, halfH );
733 bool isHorizontal = halfW > halfH;
738 int centerOffset = halfW -
radius;
741 if(
std::abs( localPt.
x ) <= centerOffset )
745 int centerX = ( localPt.
x > 0 ) ? centerOffset : -centerOffset;
746 aArcCenter =
VECTOR2I( centerX, 0 );
751 int centerOffset = halfH -
radius;
754 if(
std::abs( localPt.
y ) <= centerOffset )
758 int centerY = ( localPt.
y > 0 ) ? centerOffset : -centerOffset;
759 aArcCenter =
VECTOR2I( 0, centerY );
764 aArcCenter += aPadPos;
786 VECTOR2I localPt = aPoint - aPadPos;
790 int halfW = aPadSize.
x / 2;
791 int halfH = aPadSize.
y / 2;
792 int innerHalfW = halfW - aCornerRadius;
793 int innerHalfH = halfH - aCornerRadius;
796 bool inCornerX =
std::abs( localPt.
x ) > innerHalfW;
797 bool inCornerY =
std::abs( localPt.
y ) > innerHalfH;
799 if( !inCornerX || !inCornerY )
803 int cornerX = ( localPt.
x > 0 ) ? innerHalfW : -innerHalfW;
804 int cornerY = ( localPt.
y > 0 ) ? innerHalfH : -innerHalfH;
806 aCornerCenter =
VECTOR2I( cornerX, cornerY );
810 aCornerCenter += aPadPos;
822 int aTdWidth,
int aTrackHalfWidth, std::vector<VECTOR2I>& aPts,
826 int maxError =
m_board->GetDesignSettings().m_MaxError;
834 VECTOR2I side1( aPts[2] - aPts[1] );
836 VECTOR2I side2( aPts[4] - aPts[0] );
838 VECTOR2I trackDir( aIntersection - ( aPts[0] + aPts[1] ) / 2 );
841 bool isRoundRect =
false;
843 int cornerRadius = 0;
855 cornerRadius =
pad->GetRoundRectCornerRadius( aLayer );
856 padSize =
pad->GetSize( aLayer );
857 padRotation =
pad->GetOrientation();
862 padSize =
pad->GetSize( aLayer );
863 padRotation =
pad->GetOrientation();
867 std::vector<VECTOR2I> curve_pts;
877 ctrl2 = ( aPts[2] + aIntersection ) / 2;
879 if( isRoundRect && cornerRadius > 0 )
894 if(
isPointOnOvalEnd( aPts[2], aOtherPos, padSize, padRotation, arcCenter ) )
905 aPoly.push_back( corner );
907 aPoly.push_back( aPts[3] );
913 ctrl1 = ( aPts[4] + aIntersection ) / 2;
915 if( isRoundRect && cornerRadius > 0 )
930 if(
isPointOnOvalEnd( aPts[4], aOtherPos, padSize, padRotation, arcCenter ) )
943 aPoly.push_back( corner );
949 std::vector<VECTOR2I>& aPts )
const
951 int maxError =
m_board->GetDesignSettings().m_MaxError;
981 wxCHECK_MSG( aItem->
Type() ==
PCB_PAD_T,
false, wxT(
"Expected non-round item to be PAD" ) );
987 pad->TransformShapeToPolygon( c_buffer, aLayer, 0, maxError,
ERROR_INSIDE );
996 : preferred_width ) / 2;
1001 VECTOR2I ref_on_track = ( aPts[0] + aPts[1] ) / 2;
1002 VECTOR2I teardrop_axis( aPts[3] - ref_on_track );
1014 clipping_rect.
Append( 0, - halfsize );
1015 clipping_rect.
Append( 0, halfsize );
1016 clipping_rect.
Append( len, halfsize );
1017 clipping_rect.
Append( len, - halfsize );
1019 clipping_rect.
Rotate( -orient );
1020 clipping_rect.
Move( ref_on_track );
1036 std::vector<VECTOR2I> points = padpoly.
CPoints();
1038 std::vector<VECTOR2I> initialPoints;
1039 initialPoints.push_back( aPts[0] );
1040 initialPoints.push_back( aPts[1] );
1043 initialPoints.emplace_back( pt.x, pt.y );
1045 std::vector<VECTOR2I> hull;
1052 int found_start = -1;
1058 for(
unsigned ii = 0, jj = 0; jj < hull.size(); ii++, jj++ )
1060 unsigned next = ii+ 1;
1062 if(
next >= hull.size() )
1068 prev = hull.size()-1;
1070 if( hull[ii] == start )
1073 if( hull[
next] != pend )
1074 PointE = hull[
next];
1076 PointE = hull[prev];
1081 if( hull[ii] == pend )
1083 if( hull[
next] != start )
1084 PointC = hull[
next];
1086 PointC = hull[prev];
1092 if( found_start < 0 )
1094 int ii = found_end-1;
1104 int ii = found_start-1;
1121 double area1 = dummy1.
Area();
1123 std::swap( aPts[2], aPts[4] );
1125 double area2 = dummy2.
Area();
1128 std::swap( aPts[2], aPts[4] );
1139 int* aEffectiveTeardropLen )
const
1146 int maxError =
m_board->GetDesignSettings().m_MaxError;
1152 targetLength = std::min( aParams.
m_TdMaxLen, targetLength );
1156 bool need_swap =
false;
1160 if( !aOther->
HitTest( start, 0 ) )
1162 std::swap( start,
end );
1168 if(
IsRound( aOther, layer ) )
1174 wxCHECK_MSG( aOther->
Type() ==
PCB_PAD_T,
false, wxT(
"Expected non-round item to be PAD" ) );
1175 static_cast<PAD*
>( aOther )->TransformShapeToPolygon( shapebuffer, aTrack->
GetLayer(), 0,
1184 std::vector<SHAPE_LINE_CHAIN::INTERSECTION> pts;
1195 pt_count = outline.
Intersect( poly, pts );
1207 aIntersection = pts[0].p;
1208 start = aIntersection;
1212 actualTdLen = std::min( targetLength,
SEG( start,
end ).Length() );
1221 while( actualTdLen + consumed < targetLength )
1227 if( connected_track ==
nullptr )
1234 constexpr double kMinCosForTwoSegmentExtension = 0.5;
1244 double cosAngle = firstDir.
x * secondDir.
x + firstDir.
y * secondDir.
y;
1246 if( cosAngle < kMinCosForTwoSegmentExtension )
1249 consumed += actualTdLen;
1251 actualTdLen = std::min( targetLength-consumed,
int( connected_track->
GetLength() ) );
1252 aTrack = connected_track;
1254 start = connected_track->
GetStart();
1259 std::swap( start,
end );
1286 for(
int ii = 0; ii < poly.
PointCount(); ++ii )
1298 for(
int ii = poly.
PointCount()-1; ii >= 0 ; ii-- )
1300 int dist_from_start = ( poly.
CPoint( ii ) - start ).EuclideanNorm();
1304 if( dist_from_start < actualTdLen || ii == 0 )
1306 start = poly.
CPoint( ii );
1315 actualTdLen -= (start - ref_lenght_point).EuclideanNorm();
1318 if( actualTdLen < 0 )
1321 actualTdLen = std::min( actualTdLen, (
end - start).EuclideanNorm() );
1333 aStartPoint = start;
1336 *aEffectiveTeardropLen = actualTdLen;
1342 std::vector<VECTOR2I>& aCorners,
PCB_TRACK* aTrack,
1358 aOtherPos, &track_stub_len ) )
1374 bool twoSegments = ( aTrack != originalTrack );
1382 if( twoSegments && start != intersection )
1386 int track_halfwidth = aTrack->
GetWidth() / 2;
1393 int maxError =
m_board->GetDesignSettings().m_MaxError;
1394 track_halfwidth = std::max( aTrack->
GetWidth() / 4, aTrack->
GetWidth() / 2 - maxError );
1397 VECTOR2I pointB = start +
VECTOR2I( vecT.
x * track_stub_len + vecT.
y * track_halfwidth,
1398 vecT.
y * track_stub_len - vecT.
x * track_halfwidth );
1399 VECTOR2I pointA = start +
VECTOR2I( vecT.
x * track_stub_len - vecT.
y * track_halfwidth,
1400 vecT.
y * track_stub_len + vecT.
x * track_halfwidth );
1406 if( !
IsRound( aOther, layer ) )
1410 if(
pad->HitTest( pointA, 0, layer ) )
1413 if(
pad->HitTest( pointB, 0, layer ) )
1421 int padRadius =
GetWidth( aOther, layer ) / 2;
1423 double projOnTrack = -( intToPad.
x * vecVia.
x + intToPad.
y * vecVia.
y );
1431 double effectiveDist = isCustomPad ?
static_cast<double>( padRadius )
1432 : std::max( projOnTrack,
static_cast<double>( padRadius ) );
1439 int maxError =
m_board->GetDesignSettings().m_MaxError;
1441 pad->TransformShapeToPolygon( padPoly, layer, 0, maxError,
ERROR_INSIDE );
1449 double reach = effectiveDist + 2.0 *
pad->GetBoundingRadius() + offset;
1455 std::vector<SHAPE_LINE_CHAIN::INTERSECTION> hits;
1461 padOutline.
Intersect(
SEG( intersection, rayEnd ), hits );
1463 for(
int jj = 0; jj < padPoly.
HoleCount( ii ); ++jj )
1471 std::vector<double> crossings;
1472 crossings.reserve( hits.size() );
1477 double d = ( hit.p - intersection ).EuclideanNorm();
1480 crossings.push_back( d );
1483 std::sort( crossings.begin(), crossings.end() );
1487 double exitEdge = 0;
1489 for(
double d : crossings )
1492 KiROUND( -vecVia.
y * ( d + offset ) ) );
1503 effectiveDist = std::min( effectiveDist, std::max( 0.0, exitEdge - 2.0 * offset ) );
1514 double R =
static_cast<double>( padRadius );
1515 double cx = intToPad.
x;
1516 double cy = intToPad.
y;
1517 double distCenterSq = cx * cx + cy * cy;
1522 double disc = projOnTrack * projOnTrack - ( distCenterSq - R * R );
1526 double farEdge = projOnTrack + std::sqrt( disc );
1527 double maxAllowed = std::max( 0.0, farEdge - 2.0 * offset );
1529 if( effectiveDist > maxAllowed )
1530 effectiveDist = maxAllowed;
1535 KiROUND( -vecVia.
y * ( effectiveDist + offset ) ) );
1542 VECTOR2I junctionB_seg2, junctionB_seg1, junctionA_seg2, junctionA_seg1;
1547 KiROUND( -vecT.
x * track_halfwidth ) );
1549 KiROUND( vecT.
x * track_halfwidth ) );
1551 KiROUND( -vecVia.
x * track_halfwidth ) );
1553 KiROUND( vecVia.
x * track_halfwidth ) );
1559 bool skipJunctionA =
false;
1560 bool skipJunctionB =
false;
1566 skipJunctionA = ( transA.
x * anchorDirA.
x + transA.
y * anchorDirA.
y ) < 0;
1570 skipJunctionB = ( transB.
x * anchorDirB.
x + transB.
y * anchorDirB.
y ) < 0;
1573 VECTOR2I anchorA = twoSegments ? junctionA_seg1 : pointA;
1574 VECTOR2I anchorB = twoSegments ? junctionB_seg1 : pointB;
1576 std::vector<VECTOR2I> pts = { anchorA, anchorB, pointC, pointD, pointE };
1585 if(
IsRound( aOther, layer ) )
1591 double perpDistToCenter = padOffset.
x * perpVia.
x + padOffset.
y * perpVia.
y;
1594 if(
std::abs( perpDistToCenter ) > padRadius * 0.1 )
1596 double d =
std::abs( perpDistToCenter );
1602 double maxSymmetric =
static_cast<double>( padRadius ) - d;
1606 int maxHalfWidth = preferred_width / 2;
1609 maxHalfWidth = std::min( maxHalfWidth, aParams.
m_TdMaxWidth / 2 );
1611 double symHalfWidth = std::min( maxSymmetric,
static_cast<double>( maxHalfWidth ) );
1613 if( symHalfWidth > track_halfwidth )
1616 double R =
static_cast<double>( padRadius );
1622 auto findCircleLineIntersection =
1625 double projAlongTrack = padOffset.
x * vecVia.
x
1626 + padOffset.
y * vecVia.
y;
1628 + vecVia * projAlongTrack
1629 + perpVia * perpDist;
1632 double b_coeff = oc.
x * vecVia.
x + oc.
y * vecVia.
y;
1633 double c_coeff = oc.
x * oc.
x + oc.
y * oc.
y - R * R;
1634 double disc = b_coeff * b_coeff - c_coeff;
1639 double sqrtDisc = std::sqrt( disc );
1640 double t1 = -b_coeff - sqrtDisc;
1641 double t2 = -b_coeff + sqrtDisc;
1644 VECTOR2D p1 = lineOrigin + vecVia * t1;
1645 VECTOR2D p2 = lineOrigin + vecVia * t2;
1648 if( ( p1 - intPt ).EuclideanNorm() < ( p2 - intPt ).EuclideanNorm() )
1661 pts[2] = findCircleLineIntersection( -symHalfWidth );
1662 pts[4] = findCircleLineIntersection( symHalfWidth );
1672 aCorners.push_back( pointA );
1673 aCorners.push_back( pointB );
1675 if( !skipJunctionB )
1676 aCorners.push_back( junctionB_seg2 );
1678 aCorners.push_back( pts[1] );
1679 aCorners.push_back( pts[2] );
1680 aCorners.push_back( pts[3] );
1681 aCorners.push_back( pts[4] );
1682 aCorners.push_back( pts[0] );
1684 if( !skipJunctionA )
1685 aCorners.push_back( junctionA_seg2 );
1689 aCorners = std::move( pts );
1696 if(
IsRound( aOther, layer ) )
1700 std::vector<VECTOR2I> curvePoly;
1703 aCorners.push_back( pointB );
1705 if( !skipJunctionB )
1706 aCorners.push_back( junctionB_seg2 );
1708 for(
const VECTOR2I& pt : curvePoly )
1709 aCorners.push_back( pt );
1711 if( !skipJunctionA )
1712 aCorners.push_back( junctionA_seg2 );
1714 aCorners.push_back( pointA );
1730 std::vector<VECTOR2I> curvePoly;
1734 aCorners.push_back( pointB );
1736 if( !skipJunctionB )
1737 aCorners.push_back( junctionB_seg2 );
1739 for(
const VECTOR2I& pt : curvePoly )
1740 aCorners.push_back( pt );
1742 if( !skipJunctionA )
1743 aCorners.push_back( junctionA_seg2 );
1745 aCorners.push_back( pointA );
constexpr EDA_IU_SCALE pcbIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Bezier curves to polygon converter.
void GetPoly(std::vector< VECTOR2I > &aOutput, int aMaxError=10)
Convert a Bezier curve to a polygon.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Container for design settings for a BOARD object.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
int GetDRCEpsilon() const
Return an epsilon which accounts for rounding errors, etc.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
ecoord_type Diagonal() const
Return the length of the diagonal of the rectangle.
constexpr coord_type GetY() const
constexpr coord_type GetX() const
constexpr coord_type GetRight() const
constexpr coord_type GetBottom() const
MINOPTMAX< int > & Value()
virtual VECTOR2I GetPosition() const
KICAD_T Type() const
Returns the type of object.
virtual bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const
Test if aPosition is inside or on the boundary of this item.
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
const VECTOR2I & GetMid() const
virtual double GetLength() const
Get the length of the track using the hypotenuse calculation.
const VECTOR2I & GetStart() const
const VECTOR2I & GetEnd() const
virtual int GetWidth() const
int Length() const
Return the length (this).
const SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError=DefaultAccuracyForPCB(), int *aActualError=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
VECTOR2I NearestPoint(const VECTOR2I &aP) const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int Intersect(const SEG &aSeg, std::vector< INTERSECTION > &aIp) const
Find all intersection points between our line chain and the segment aSeg.
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
double Area(bool aAbsolute=true) const
Return the area of this chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
const std::vector< VECTOR2I > & CPoints() const
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the reference to aHole-th hole in the aIndex-th outline.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
void BooleanIntersection(const SHAPE_POLY_SET &b)
Perform boolean polyset intersection.
int OutlineCount() const
Return the number of outlines in the set.
void Move(const VECTOR2I &aVector) override
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 BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
An abstract shape on 2D plane.
PCB_TRACK * findTouchingTrack(EDA_ITEM_FLAGS &aMatchType, PCB_TRACK *aTrackRef, PCB_TRACK *aSourceTrack, const VECTOR2I &aEndPoint) const
Find a track connected to the end of another track.
std::map< PCB_LAYER_ID, KIRTREE::DYNAMIC_RTREE< ZONE *, int, 2 > > m_createdTdRTree
The teardrops of this pass by layer, since m_copperRTree cannot take inserts once built.
static bool IsRound(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer)
static bool IsUniformlyRound(BOARD_ITEM *aItem)
bool computeAnchorPoints(const TEARDROP_PARAMETERS &aParams, PCB_LAYER_ID aLayer, BOARD_ITEM *aItem, const VECTOR2I &aPos, std::vector< VECTOR2I > &aPts) const
Compute the 2 points on pad/via of the teardrop shape.
static int GetWidth(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer)
std::unordered_map< PTR_PTR_LAYER_CACHE_KEY, int > m_pairClearanceCache
bool computeTeardropPolygon(const TEARDROP_PARAMETERS &aParams, std::vector< VECTOR2I > &aCorners, PCB_TRACK *aTrack, PCB_TRACK *aSourceTrack, BOARD_ITEM *aOther, const VECTOR2I &aOtherPos) const
Compute all teardrop points of the polygon shape.
static int copperNetcode(const BOARD_ITEM *aItem)
std::unordered_map< PTR_LAYER_CACHE_KEY, std::vector< std::set< const BOARD_ITEM * > > > m_zoneConnectionCache
DRC_RTREE m_copperRTree
Every copper item on the board before this pass, to keep teardrops off other nets.
void computeCurvedForRectShape(const TEARDROP_PARAMETERS &aParams, std::vector< VECTOR2I > &aPoly, int aTdWidth, int aTrackHalfWidth, std::vector< VECTOR2I > &aPts, const VECTOR2I &aIntersection, BOARD_ITEM *aOther, const VECTOR2I &aOtherPos, PCB_LAYER_ID aLayer) const
Compute the curve part points for teardrops connected to a rectangular/polygonal shape The Bezier cur...
void computeCurvedForRoundShape(const TEARDROP_PARAMETERS &aParams, std::vector< VECTOR2I > &aPoly, PCB_LAYER_ID aLayer, int aTrackHalfWidth, const VECTOR2D &aTrackDir, BOARD_ITEM *aOther, const VECTOR2I &aOtherPos, std::vector< VECTOR2I > &aPts) const
Compute the curve part points for teardrops connected to a round shape The Bezier curve control point...
int pairClearance(PCB_TRACK *aSourceTrack, BOARD_ITEM *aItem, PCB_LAYER_ID aLayer) const
TRACK_BUFFER m_trackLookupList
bool collidesWithOtherNets(const std::vector< VECTOR2I > &aPoints, PCB_TRACK *aSourceTrack, const std::vector< const BOARD_ITEM * > &aExempt) const
bool findAnchorPointsOnTrack(const TEARDROP_PARAMETERS &aParams, VECTOR2I &aStartPoint, VECTOR2I &aEndPoint, VECTOR2I &aIntersection, PCB_TRACK *&aTrack, PCB_TRACK *aSourceTrack, BOARD_ITEM *aOther, const VECTOR2I &aOtherPos, int *aEffectiveTeardropLen) const
bool areItemsInSameZone(BOARD_ITEM *aPadOrVia, PCB_TRACK *aTrack) const
bool computeFittedTeardropPolygon(const TEARDROP_PARAMETERS &aParams, std::vector< VECTOR2I > &aPoints, PCB_TRACK *aTrack, PCB_TRACK *aSourceTrack, BOARD_ITEM *aOther, const VECTOR2I &aOtherPos) const
Widen a teardrop as far as the surrounding copper allows.
void ensureCopperIndex() const
Build the copper collision index, deferred so a commit with no teardrop candidate never pays for it.
friend class TEARDROP_PARAMETERS
int computeChordThroughShape(PCB_TRACK *aTrack, BOARD_ITEM *aOther, PCB_LAYER_ID aLayer, const VECTOR2I &aInsidePoint) const
Return the centerline chord length through aOther's copper span at aInsidePoint.
const std::vector< std::set< const BOARD_ITEM * > > & zoneConnections(ZONE *aZone, PCB_LAYER_ID aLayer) const
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
bool m_CurvedEdges
True if the teardrop should be curved.
int idxFromLayNet(int aLayer, int aNetcode) const
void AddTrack(PCB_TRACK *aTrack, int aLayer, int aNetcode)
Add a track in buffer, in space grouping tracks having the same netcode and the same layer.
std::map< int, std::vector< PCB_TRACK * > > m_map_tracks
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
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.
bool IsTeardropArea() const
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
void BuildConvexHull(std::vector< VECTOR2I > &aResult, const std::vector< VECTOR2I > &aPoly)
Calculate the convex hull of a list of points in counter-clockwise order.
std::uint32_t EDA_ITEM_FLAGS
#define STARTPOINT
When a line is selected, these flags indicate which.
PCB_LAYER_ID
A quick note on layer IDs:
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
Represent an intersection between two line segments.
static bool isPointOnRoundedCorner(const VECTOR2I &aPoint, const VECTOR2I &aPadPos, const VECTOR2I &aPadSize, int aCornerRadius, const EDA_ANGLE &aRotation, VECTOR2I &aCornerCenter)
Check if a point is within a rounded corner region of a rounded rectangle pad.
static bool isPointOnOvalEnd(const VECTOR2I &aPoint, const VECTOR2I &aPadPos, const VECTOR2I &aPadSize, const EDA_ANGLE &aRotation, VECTOR2I &aArcCenter)
Check if a point is on the curved (semicircular) end of an oval pad.
static VECTOR2D NormalizeVector(const VECTOR2I &aVector)
static VECTOR2I computeCornerTangentControlPoint(const VECTOR2I &aAnchor, const VECTOR2I &aCornerCenter, double aBias, const VECTOR2I &aDesiredDir)
Helper to compute a control point for a teardrop anchor on a rounded rectangle corner.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D