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 );
177 return connected->GetNetCode();
192 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 ) )
266 const std::vector<const BOARD_ITEM*>& aExempt )
const
268 if( aPoints.size() < 3 )
275 teardrop.
Append( pt.x, pt.y );
290 std::vector<std::shared_ptr<SHAPE>> anchorShapes;
291 std::map<const BOARD_ITEM*, bool> touchesAnchor;
297 if( std::shared_ptr<SHAPE> shape = item->GetEffectiveShape( layer ) )
298 anchorShapes.push_back( shape );
302 auto touchesTeardropAnchor =
305 auto it = touchesAnchor.find( aItem );
307 if( it == touchesAnchor.end() )
309 std::shared_ptr<SHAPE> shape = aItem->GetEffectiveShape( layer );
310 bool touches =
false;
314 touches = std::any_of( anchorShapes.begin(), anchorShapes.end(),
315 [&](
const std::shared_ptr<SHAPE>& aAnchor )
317 return aAnchor->Collide( shape.get() );
321 it = touchesAnchor.emplace( aItem, touches ).first;
327 auto isSameConductor =
333 return itemNet == netcode;
335 return itemNet <= 0 && touchesTeardropAnchor( aItem );
338 auto resolveClearance =
339 [&](
BOARD_ITEM* aItem,
int* aClearance ) ->
bool
341 if(
alg::contains( aExempt, aItem ) || isSameConductor( aItem ) )
356 std::vector<VECTOR2I>& aPoints,
363 const std::vector<const BOARD_ITEM*> exempt = { aOther, aSourceTrack, aTrack };
384 std::vector<VECTOR2I> fitted;
387 [&](
int aWidth ) ->
bool
389 std::vector<VECTOR2I> candidate;
400 fitted = std::move( candidate );
406 if( !tryWidth( lo ) )
409 for(
int ii = 0; ii < 4 && hi - lo > 1; ++ii )
411 int mid = lo + ( hi - lo ) / 2;
413 if( tryWidth( mid ) )
419 aPoints = std::move( fitted );
421 return !aPoints.empty();
430 return std::numeric_limits<int>::max();
433 double len =
delta.EuclideanNorm();
436 return std::numeric_limits<int>::max();
438 int maxError =
m_board->GetDesignSettings().m_MaxError;
442 if(
IsRound( aOther, aLayer ) )
449 wxCHECK_MSG( aOther->
Type() ==
PCB_PAD_T, 0, wxT(
"Expected non-round item to be PAD" ) );
450 static_cast<PAD*
>( aOther )->TransformShapeToPolygon( shapebuffer, aLayer, 0, maxError,
ERROR_INSIDE );
464 for(
int ii = 0; ii < shapebuffer.
OutlineCount(); ++ii )
470 for(
int jj = 0; jj < shapebuffer.
HoleCount( ii ); ++jj )
480 return std::numeric_limits<int>::max();
484 std::vector<double> proj;
485 proj.reserve( pts.size() );
488 proj.push_back( ( hit.p - extStart ).Dot( dir ) );
490 std::sort( proj.begin(), proj.end() );
492 double insideProj = (
VECTOR2D( aInsidePoint ) -
VECTOR2D( extStart ) ).Dot( dir );
494 for(
size_t ii = 0; ii + 1 < proj.size(); ++ii )
497 KiROUND( dir.
y * ( proj[ii] + proj[ii + 1] ) / 2 ) );
499 if( !shapebuffer.
Contains( spanMid ) )
502 if( insideProj >= proj[ii] && insideProj <= proj[ii + 1] )
503 return KiROUND( proj[ii + 1] - proj[ii] );
507 return std::numeric_limits<int>::max();
524 return trackItem != aTrackRef && trackItem != aSourceTrack;
529 PCB_TRACK* curr_track = static_cast<PCB_TRACK*>( trackItem );
532 if( EDA_ITEM_FLAGS match = curr_track->IsPointOnEnds( aEndPoint, m_tolerance ) )
539 double previous_len = candidate->GetLength();
540 double curr_len = curr_track->GetLength();
542 if( previous_len >= curr_len )
547 candidate = curr_track;
578 std::vector<VECTOR2I>& aPoly,
580 int aTrackHalfWidth,
const VECTOR2D& aTrackDir,
582 std::vector<VECTOR2I>& pts )
const
584 int maxError =
m_board->GetDesignSettings().m_MaxError;
604 double minVpercent = double( aTrackHalfWidth ) /
radius;
605 double weaken = (Vpercent - minVpercent) / ( 1 - minVpercent ) /
radius;
617 vecC = pts[2] - aOtherPos;
627 vecE = pts[4] - aOtherPos;
630 double biasBC = 0.5 *
SEG( pts[1], pts[2] ).
Length();
631 double biasAE = 0.5 *
SEG( pts[4], pts[0] ).
Length();
633 VECTOR2I tangentC =
VECTOR2I( pts[2].x - vecC.
y * biasBC * weaken, pts[2].y + vecC.
x * biasBC * weaken );
634 VECTOR2I tangentE =
VECTOR2I( pts[4].x + vecE.
y * biasAE * weaken, pts[4].y - vecE.
x * biasAE * weaken );
636 VECTOR2I tangentB =
VECTOR2I( pts[1].x - aTrackDir.
x * biasBC, pts[1].y - aTrackDir.
y * biasBC );
637 VECTOR2I tangentA =
VECTOR2I( pts[0].x - aTrackDir.
x * biasAE, pts[0].y - aTrackDir.
y * biasAE );
639 std::vector<VECTOR2I> curve_pts;
643 aPoly.push_back( corner );
645 aPoly.push_back( pts[3] );
651 aPoly.push_back( corner );
667 double aBias,
const VECTOR2I& aDesiredDir )
669 VECTOR2I radial = aAnchor - aCornerCenter;
681 int64_t dot1 =
static_cast<int64_t
>( tangent1.
x ) * aDesiredDir.
x
682 +
static_cast<int64_t
>( tangent1.
y ) * aDesiredDir.
y;
683 int64_t dot2 =
static_cast<int64_t
>( tangent2.
x ) * aDesiredDir.
x
684 +
static_cast<int64_t
>( tangent2.
y ) * aDesiredDir.
y;
686 VECTOR2I tangent = ( dot1 > dot2 ) ? tangent1 : tangent2;
707 VECTOR2I localPt = aPoint - aPadPos;
710 int halfW = aPadSize.
x / 2;
711 int halfH = aPadSize.
y / 2;
715 int radius = std::min( halfW, halfH );
716 bool isHorizontal = halfW > halfH;
721 int centerOffset = halfW -
radius;
724 if(
std::abs( localPt.
x ) <= centerOffset )
728 int centerX = ( localPt.
x > 0 ) ? centerOffset : -centerOffset;
729 aArcCenter =
VECTOR2I( centerX, 0 );
734 int centerOffset = halfH -
radius;
737 if(
std::abs( localPt.
y ) <= centerOffset )
741 int centerY = ( localPt.
y > 0 ) ? centerOffset : -centerOffset;
742 aArcCenter =
VECTOR2I( 0, centerY );
747 aArcCenter += aPadPos;
769 VECTOR2I localPt = aPoint - aPadPos;
773 int halfW = aPadSize.
x / 2;
774 int halfH = aPadSize.
y / 2;
775 int innerHalfW = halfW - aCornerRadius;
776 int innerHalfH = halfH - aCornerRadius;
779 bool inCornerX =
std::abs( localPt.
x ) > innerHalfW;
780 bool inCornerY =
std::abs( localPt.
y ) > innerHalfH;
782 if( !inCornerX || !inCornerY )
786 int cornerX = ( localPt.
x > 0 ) ? innerHalfW : -innerHalfW;
787 int cornerY = ( localPt.
y > 0 ) ? innerHalfH : -innerHalfH;
789 aCornerCenter =
VECTOR2I( cornerX, cornerY );
793 aCornerCenter += aPadPos;
805 std::vector<VECTOR2I>& aPoly,
int aTdWidth,
807 std::vector<VECTOR2I>& aPts,
813 int maxError =
m_board->GetDesignSettings().m_MaxError;
821 VECTOR2I side1( aPts[2] - aPts[1] );
823 VECTOR2I side2( aPts[4] - aPts[0] );
825 VECTOR2I trackDir( aIntersection - ( aPts[0] + aPts[1] ) / 2 );
828 bool isRoundRect =
false;
830 int cornerRadius = 0;
842 cornerRadius =
pad->GetRoundRectCornerRadius( aLayer );
843 padSize =
pad->GetSize( aLayer );
844 padRotation =
pad->GetOrientation();
849 padSize =
pad->GetSize( aLayer );
850 padRotation =
pad->GetOrientation();
854 std::vector<VECTOR2I> curve_pts;
864 ctrl2 = ( aPts[2] + aIntersection ) / 2;
866 if( isRoundRect && cornerRadius > 0 )
881 if(
isPointOnOvalEnd( aPts[2], aOtherPos, padSize, padRotation, arcCenter ) )
892 aPoly.push_back( corner );
894 aPoly.push_back( aPts[3] );
900 ctrl1 = ( aPts[4] + aIntersection ) / 2;
902 if( isRoundRect && cornerRadius > 0 )
917 if(
isPointOnOvalEnd( aPts[4], aOtherPos, padSize, padRotation, arcCenter ) )
930 aPoly.push_back( corner );
936 std::vector<VECTOR2I>& aPts )
const
938 int maxError =
m_board->GetDesignSettings().m_MaxError;
968 wxCHECK_MSG( aItem->
Type() ==
PCB_PAD_T,
false, wxT(
"Expected non-round item to be PAD" ) );
974 pad->TransformShapeToPolygon( c_buffer, aLayer, 0, maxError,
ERROR_INSIDE );
984 : preferred_width ) / 2;
989 VECTOR2I ref_on_track = ( aPts[0] + aPts[1] ) / 2;
990 VECTOR2I teardrop_axis( aPts[3] - ref_on_track );
1002 clipping_rect.
Append( 0, - halfsize );
1003 clipping_rect.
Append( 0, halfsize );
1004 clipping_rect.
Append( len, halfsize );
1005 clipping_rect.
Append( len, - halfsize );
1007 clipping_rect.
Rotate( -orient );
1008 clipping_rect.
Move( ref_on_track );
1024 std::vector<VECTOR2I> points = padpoly.
CPoints();
1026 std::vector<VECTOR2I> initialPoints;
1027 initialPoints.push_back( aPts[0] );
1028 initialPoints.push_back( aPts[1] );
1031 initialPoints.emplace_back( pt.x, pt.y );
1033 std::vector<VECTOR2I> hull;
1040 int found_start = -1;
1046 for(
unsigned ii = 0, jj = 0; jj < hull.size(); ii++, jj++ )
1048 unsigned next = ii+ 1;
1050 if(
next >= hull.size() )
1056 prev = hull.size()-1;
1058 if( hull[ii] == start )
1061 if( hull[
next] != pend )
1062 PointE = hull[
next];
1064 PointE = hull[prev];
1069 if( hull[ii] == pend )
1071 if( hull[
next] != start )
1072 PointC = hull[
next];
1074 PointC = hull[prev];
1080 if( found_start < 0 )
1082 int ii = found_end-1;
1092 int ii = found_start-1;
1109 double area1 = dummy1.
Area();
1111 std::swap( aPts[2], aPts[4] );
1113 double area2 = dummy2.
Area();
1116 std::swap( aPts[2], aPts[4] );
1127 int* aEffectiveTeardropLen )
const
1134 int maxError =
m_board->GetDesignSettings().m_MaxError;
1140 targetLength = std::min( aParams.
m_TdMaxLen, targetLength );
1144 bool need_swap =
false;
1148 if( !aOther->
HitTest( start, 0 ) )
1150 std::swap( start,
end );
1156 if(
IsRound( aOther, layer ) )
1162 wxCHECK_MSG( aOther->
Type() ==
PCB_PAD_T,
false, wxT(
"Expected non-round item to be PAD" ) );
1163 static_cast<PAD*
>( aOther )->TransformShapeToPolygon( shapebuffer, aTrack->
GetLayer(), 0,
1183 pt_count = outline.
Intersect( poly, pts );
1195 aIntersection = pts[0].p;
1196 start = aIntersection;
1200 actualTdLen = std::min( targetLength,
SEG( start,
end ).Length() );
1209 while( actualTdLen + consumed < targetLength )
1215 if( connected_track ==
nullptr )
1222 constexpr double kMinCosForTwoSegmentExtension = 0.5;
1232 double cosAngle = firstDir.
x * secondDir.
x + firstDir.
y * secondDir.
y;
1234 if( cosAngle < kMinCosForTwoSegmentExtension )
1237 consumed += actualTdLen;
1239 actualTdLen = std::min( targetLength-consumed,
int( connected_track->
GetLength() ) );
1240 aTrack = connected_track;
1242 start = connected_track->
GetStart();
1247 std::swap( start,
end );
1274 for(
int ii = 0; ii < poly.
PointCount(); ++ii )
1286 for(
int ii = poly.
PointCount()-1; ii >= 0 ; ii-- )
1288 int dist_from_start = ( poly.
CPoint( ii ) - start ).EuclideanNorm();
1292 if( dist_from_start < actualTdLen || ii == 0 )
1294 start = poly.
CPoint( ii );
1303 actualTdLen -= (start - ref_lenght_point).EuclideanNorm();
1306 if( actualTdLen < 0 )
1309 actualTdLen = std::min( actualTdLen, (
end - start).EuclideanNorm() );
1321 aStartPoint = start;
1324 *aEffectiveTeardropLen = actualTdLen;
1330 std::vector<VECTOR2I>& aCorners,
PCB_TRACK* aTrack,
1346 aOtherPos, &track_stub_len ) )
1362 bool twoSegments = ( aTrack != originalTrack );
1370 if( twoSegments && start != intersection )
1374 int track_halfwidth = aTrack->
GetWidth() / 2;
1381 int maxError =
m_board->GetDesignSettings().m_MaxError;
1382 track_halfwidth = std::max( aTrack->
GetWidth() / 4, aTrack->
GetWidth() / 2 - maxError );
1385 VECTOR2I pointB = start +
VECTOR2I( vecT.
x * track_stub_len + vecT.
y * track_halfwidth,
1386 vecT.
y * track_stub_len - vecT.
x * track_halfwidth );
1387 VECTOR2I pointA = start +
VECTOR2I( vecT.
x * track_stub_len - vecT.
y * track_halfwidth,
1388 vecT.
y * track_stub_len + vecT.
x * track_halfwidth );
1394 if( !
IsRound( aOther, layer ) )
1398 if(
pad->HitTest( pointA, 0, layer ) )
1401 if(
pad->HitTest( pointB, 0, layer ) )
1409 int padRadius =
GetWidth( aOther, layer ) / 2;
1411 double projOnTrack = -( intToPad.
x * vecVia.
x + intToPad.
y * vecVia.
y );
1419 double effectiveDist = isCustomPad ?
static_cast<double>( padRadius )
1420 : std::max( projOnTrack,
static_cast<double>( padRadius ) );
1427 int maxError =
m_board->GetDesignSettings().m_MaxError;
1429 pad->TransformShapeToPolygon( padPoly, layer, 0, maxError,
ERROR_INSIDE );
1437 double reach = effectiveDist + 2.0 *
pad->GetBoundingRadius() + offset;
1449 padOutline.
Intersect(
SEG( intersection, rayEnd ), hits );
1451 for(
int jj = 0; jj < padPoly.
HoleCount( ii ); ++jj )
1459 std::vector<double> crossings;
1460 crossings.reserve( hits.size() );
1465 double d = ( hit.p - intersection ).EuclideanNorm();
1468 crossings.push_back( d );
1471 std::sort( crossings.begin(), crossings.end() );
1475 double exitEdge = 0;
1477 for(
double d : crossings )
1480 KiROUND( -vecVia.
y * ( d + offset ) ) );
1491 effectiveDist = std::min( effectiveDist, std::max( 0.0, exitEdge - 2.0 * offset ) );
1502 double R =
static_cast<double>( padRadius );
1503 double cx = intToPad.
x;
1504 double cy = intToPad.
y;
1505 double distCenterSq = cx * cx + cy * cy;
1510 double disc = projOnTrack * projOnTrack - ( distCenterSq - R * R );
1514 double farEdge = projOnTrack + std::sqrt( disc );
1515 double maxAllowed = std::max( 0.0, farEdge - 2.0 * offset );
1517 if( effectiveDist > maxAllowed )
1518 effectiveDist = maxAllowed;
1523 KiROUND( -vecVia.
y * ( effectiveDist + offset ) ) );
1530 VECTOR2I junctionB_seg2, junctionB_seg1, junctionA_seg2, junctionA_seg1;
1535 KiROUND( -vecT.
x * track_halfwidth ) );
1537 KiROUND( vecT.
x * track_halfwidth ) );
1539 KiROUND( -vecVia.
x * track_halfwidth ) );
1541 KiROUND( vecVia.
x * track_halfwidth ) );
1547 bool skipJunctionA =
false;
1548 bool skipJunctionB =
false;
1554 skipJunctionA = ( transA.
x * anchorDirA.
x + transA.
y * anchorDirA.
y ) < 0;
1558 skipJunctionB = ( transB.
x * anchorDirB.
x + transB.
y * anchorDirB.
y ) < 0;
1561 VECTOR2I anchorA = twoSegments ? junctionA_seg1 : pointA;
1562 VECTOR2I anchorB = twoSegments ? junctionB_seg1 : pointB;
1564 std::vector<VECTOR2I> pts = { anchorA, anchorB, pointC, pointD, pointE };
1573 if(
IsRound( aOther, layer ) )
1579 double perpDistToCenter = padOffset.
x * perpVia.
x + padOffset.
y * perpVia.
y;
1582 if(
std::abs( perpDistToCenter ) > padRadius * 0.1 )
1584 double d =
std::abs( perpDistToCenter );
1590 double maxSymmetric =
static_cast<double>( padRadius ) - d;
1594 int maxHalfWidth = preferred_width / 2;
1597 maxHalfWidth = std::min( maxHalfWidth, aParams.
m_TdMaxWidth / 2 );
1599 double symHalfWidth = std::min( maxSymmetric,
1600 static_cast<double>( maxHalfWidth ) );
1602 if( symHalfWidth > track_halfwidth )
1605 double R =
static_cast<double>( padRadius );
1611 auto findCircleLineIntersection =
1614 double projAlongTrack = padOffset.
x * vecVia.
x
1615 + padOffset.
y * vecVia.
y;
1617 + vecVia * projAlongTrack
1618 + perpVia * perpDist;
1621 double b_coeff = oc.
x * vecVia.
x + oc.
y * vecVia.
y;
1622 double c_coeff = oc.
x * oc.
x + oc.
y * oc.
y - R * R;
1623 double disc = b_coeff * b_coeff - c_coeff;
1629 double sqrtDisc = std::sqrt( disc );
1630 double t1 = -b_coeff - sqrtDisc;
1631 double t2 = -b_coeff + sqrtDisc;
1634 VECTOR2D p1 = lineOrigin + vecVia * t1;
1635 VECTOR2D p2 = lineOrigin + vecVia * t2;
1638 if( ( p1 - intPt ).EuclideanNorm() < ( p2 - intPt ).EuclideanNorm() )
1651 pts[2] = findCircleLineIntersection( -symHalfWidth );
1652 pts[4] = findCircleLineIntersection( symHalfWidth );
1662 aCorners.push_back( pointA );
1663 aCorners.push_back( pointB );
1665 if( !skipJunctionB )
1666 aCorners.push_back( junctionB_seg2 );
1668 aCorners.push_back( pts[1] );
1669 aCorners.push_back( pts[2] );
1670 aCorners.push_back( pts[3] );
1671 aCorners.push_back( pts[4] );
1672 aCorners.push_back( pts[0] );
1674 if( !skipJunctionA )
1675 aCorners.push_back( junctionA_seg2 );
1679 aCorners = std::move( pts );
1686 if(
IsRound( aOther, layer ) )
1690 std::vector<VECTOR2I> curvePoly;
1693 aCorners.push_back( pointB );
1695 if( !skipJunctionB )
1696 aCorners.push_back( junctionB_seg2 );
1698 for(
const VECTOR2I& pt : curvePoly )
1699 aCorners.push_back( pt );
1701 if( !skipJunctionA )
1702 aCorners.push_back( junctionA_seg2 );
1704 aCorners.push_back( pointA );
1720 std::vector<VECTOR2I> curvePoly;
1724 aCorners.push_back( pointB );
1726 if( !skipJunctionB )
1727 aCorners.push_back( junctionB_seg2 );
1729 for(
const VECTOR2I& pt : curvePoly )
1730 aCorners.push_back( pt );
1732 if( !skipJunctionA )
1733 aCorners.push_back( junctionA_seg2 );
1735 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...
ecoord_type Diagonal() const
Return the length of the diagonal of the rectangle.
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...
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 Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Find all intersection points between our line chain and the segment aSeg.
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.
std::vector< INTERSECTION > INTERSECTIONS
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.
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.
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.
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 plus the teardrops built so far, 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