Add distance reporting for copper item DRC tests.

Also adds some performance improvements.
This commit is contained in:
Jeff Young 2020-04-28 22:43:29 +01:00
parent 932fdf8674
commit dfe4a00d43
6 changed files with 209 additions and 122 deletions

View File

@ -113,6 +113,11 @@ public:
return (A != aSeg.A || B != aSeg.B);
}
static SEG::ecoord Square( int a )
{
return ecoord( a ) * a;
}
/**
* Function LineProject()
*

View File

@ -1169,7 +1169,7 @@ class SHAPE_POLY_SET : public SHAPE
* @return int - The minimum distance between aPoint and all the segments of the aIndex-th
* polygon. If the point is contained in the polygon, the distance is zero.
*/
int DistanceToPolygon( VECTOR2I aPoint, int aIndex );
SEG::ecoord SquaredDistanceToPolygon( VECTOR2I aPoint, int aIndex );
/**
* Function DistanceToPolygon
@ -1183,26 +1183,28 @@ class SHAPE_POLY_SET : public SHAPE
* aIndex-th polygon. If the point is contained in the polygon, the
* distance is zero.
*/
int DistanceToPolygon( const SEG& aSegment, int aIndex, int aSegmentWidth = 0 );
SEG::ecoord SquaredDistanceToPolygon( const SEG& aSegment, int aIndex );
/**
* Function DistanceToPolygon
* computes the minimum distance between aPoint and all the polygons in the set
* Function SquaredDistance
* computes the minimum distance squared between aPoint and all the polygons in the set.
* Squared distances are used because they avoid the cost of doing square-roots.
* @param aPoint is the point whose distance to the set has to be measured.
* @return int - The minimum distance between aPoint and all the polygons in the set. If
* the point is contained in any of the polygons, the distance is zero.
* @return The minimum distance squared between aPoint and all the polygons in the set.
* If the point is contained in any of the polygons, the distance is zero.
*/
int Distance( VECTOR2I aPoint );
SEG::ecoord SquaredDistance( VECTOR2I aPoint );
/**
* Function DistanceToPolygon
* computes the minimum distance between aSegment and all the polygons in the set.
* Function SquaredDistance
* computes the minimum distance squared between aSegment and all the polygons in the set.
* Squared distances are used because they avoid the cost of doing square-roots.
* @param aSegment is the segment whose distance to the polygon set has to be measured.
* @param aSegmentWidth is the width of the segment; defaults to zero.
* @return int - The minimum distance between aSegment and all the polygons in the set.
* If the point is contained in the polygon, the distance is zero.
* @return The minimum distance squared between aSegment and all the polygons in the set.
* If the point is contained in the polygon, the distance is zero.
*/
int Distance( const SEG& aSegment, int aSegmentWidth = 0 );
SEG::ecoord SquaredDistance( const SEG& aSegment );
/**
* Function IsVertexInHole.

View File

@ -1557,7 +1557,7 @@ SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::FilletPolygon( unsigned int aRadius, int
}
int SHAPE_POLY_SET::DistanceToPolygon( VECTOR2I aPoint, int aPolygonIndex )
SEG::ecoord SHAPE_POLY_SET::SquaredDistanceToPolygon( VECTOR2I aPoint, int aPolygonIndex )
{
// We calculate the min dist between the segment and each outline segment. However, if the
// segment to test is inside the outline, and does not cross any edge, it can be seen outside
@ -1569,13 +1569,13 @@ int SHAPE_POLY_SET::DistanceToPolygon( VECTOR2I aPoint, int aPolygonIndex )
SEGMENT_ITERATOR iterator = IterateSegmentsWithHoles( aPolygonIndex );
SEG polygonEdge = *iterator;
int minDistance = polygonEdge.Distance( aPoint );
SEG::ecoord minDistance = polygonEdge.SquaredDistance( aPoint );
for( iterator++; iterator && minDistance > 0; iterator++ )
{
polygonEdge = *iterator;
int currentDistance = polygonEdge.Distance( aPoint );
SEG::ecoord currentDistance = polygonEdge.SquaredDistance( aPoint );
if( currentDistance < minDistance )
minDistance = currentDistance;
@ -1585,7 +1585,7 @@ int SHAPE_POLY_SET::DistanceToPolygon( VECTOR2I aPoint, int aPolygonIndex )
}
int SHAPE_POLY_SET::DistanceToPolygon( const SEG& aSegment, int aPolygonIndex, int aSegmentWidth )
SEG::ecoord SHAPE_POLY_SET::SquaredDistanceToPolygon( const SEG& aSegment, int aPolygonIndex )
{
// We calculate the min dist between the segment and each outline segment. However, if the
// segment to test is inside the outline, and does not cross any edge, it can be seen outside
@ -1595,38 +1595,33 @@ int SHAPE_POLY_SET::DistanceToPolygon( const SEG& aSegment, int aPolygonIndex, i
return 0;
SEGMENT_ITERATOR iterator = IterateSegmentsWithHoles( aPolygonIndex );
SEG polygonEdge = *iterator;
int minDistance = polygonEdge.Distance( aSegment );
SEG polygonEdge = *iterator;
SEG::ecoord minDistance = polygonEdge.SquaredDistance( aSegment );
for( iterator++; iterator && minDistance > 0; iterator++ )
{
polygonEdge = *iterator;
int currentDistance = polygonEdge.Distance( aSegment );
SEG::ecoord currentDistance = polygonEdge.SquaredDistance( aSegment );
if( currentDistance < minDistance )
minDistance = currentDistance;
}
// Take into account the width of the segment
if( aSegmentWidth > 0 )
minDistance -= aSegmentWidth / 2;
// Return the maximum of minDistance and zero
return minDistance < 0 ? 0 : minDistance;
}
int SHAPE_POLY_SET::Distance( VECTOR2I aPoint )
SEG::ecoord SHAPE_POLY_SET::SquaredDistance( VECTOR2I aPoint )
{
int currentDistance;
int minDistance = DistanceToPolygon( aPoint, 0 );
SEG::ecoord currentDistance;
SEG::ecoord minDistance = SquaredDistanceToPolygon( aPoint, 0 );
// Iterate through all the polygons and get the minimum distance.
for( unsigned int polygonIdx = 1; polygonIdx < m_polys.size(); polygonIdx++ )
{
currentDistance = DistanceToPolygon( aPoint, polygonIdx );
currentDistance = SquaredDistanceToPolygon( aPoint, polygonIdx );
if( currentDistance < minDistance )
minDistance = currentDistance;
@ -1636,15 +1631,15 @@ int SHAPE_POLY_SET::Distance( VECTOR2I aPoint )
}
int SHAPE_POLY_SET::Distance( const SEG& aSegment, int aSegmentWidth )
SEG::ecoord SHAPE_POLY_SET::SquaredDistance( const SEG& aSegment )
{
int currentDistance;
int minDistance = DistanceToPolygon( aSegment, 0, aSegmentWidth );
SEG::ecoord currentDistance;
SEG::ecoord minDistance = SquaredDistanceToPolygon( aSegment, 0 );
// Iterate through all the polygons and get the minimum distance.
for( unsigned int polygonIdx = 1; polygonIdx < m_polys.size(); polygonIdx++ )
{
currentDistance = DistanceToPolygon( aSegment, polygonIdx, aSegmentWidth );
currentDistance = SquaredDistanceToPolygon( aSegment, polygonIdx );
if( currentDistance < minDistance )
minDistance = currentDistance;

View File

@ -887,7 +887,6 @@ void DRC::testKeepoutAreas()
// Test keepout areas for vias, tracks and pads inside keepout areas
for( ZONE_CONTAINER* area : areasToInspect )
{
if( !area->GetIsKeepout() )
continue;
@ -902,9 +901,11 @@ void DRC::testKeepoutAreas()
if( !area->IsOnLayer( segm->GetLayer() ) )
continue;
SEG trackSeg( segm->GetStart(), segm->GetEnd() );
int widths = segm->GetWidth() / 2;
SEG trackSeg( segm->GetStart(), segm->GetEnd() );
SEG::ecoord center2center_squared = area->Outline()->SquaredDistance( trackSeg );
if( area->Outline()->Distance( trackSeg, segm->GetWidth() ) == 0 )
if( center2center_squared <= SEG::Square( widths) )
{
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_INSIDE_KEEPOUT );
drcItem->SetItems( segm, area );
@ -923,7 +924,11 @@ void DRC::testKeepoutAreas()
if( !area->CommonLayerExists( viaLayers ) )
continue;
if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 )
int widths = segm->GetWidth() / 2;
wxPoint viaPos = segm->GetPosition();
SEG::ecoord center2center_squared = area->Outline()->SquaredDistance( viaPos );
if( center2center_squared <= SEG::Square( widths) )
{
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_VIA_INSIDE_KEEPOUT );
drcItem->SetItems( segm, area );
@ -984,7 +989,7 @@ void DRC::testCopperTextAndGraphics()
void DRC::testCopperDrawItem( DRAWSEGMENT* aItem )
{
std::vector<SEG> itemShape;
int itemWidth = aItem->GetWidth();
int itemWidth = aItem->GetWidth();
switch( aItem->GetShape() )
{
@ -1036,40 +1041,60 @@ void DRC::testCopperDrawItem( DRAWSEGMENT* aItem )
break;
}
EDA_RECT bbox = aItem->GetBoundingBox();
SHAPE_RECT rect_area( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
wxString msg;
// Test tracks and vias
for( auto track : m_pcb->Tracks() )
{
if( !track->IsOnLayer( aItem->GetLayer() ) )
continue;
int minDist = ( track->GetWidth() + itemWidth ) / 2 + track->GetClearance( NULL );
SEG trackAsSeg( track->GetStart(), track->GetEnd() );
wxString clearanceSource;
int minClearance = track->GetClearance( nullptr, &clearanceSource );
int widths = ( track->GetWidth() + itemWidth ) / 2;
int center2centerAllowed = minClearance + widths;
for( const auto& itemSeg : itemShape )
SEG trackSeg( track->GetStart(), track->GetEnd() );
// Fast test to detect a track segment candidate inside the text bounding box
if( !rect_area.Collide( trackSeg, center2centerAllowed ) )
continue;
OPT<SEG> minSeg;
SEG::ecoord center2center_squared = 0;
for( const SEG& itemSeg : itemShape )
{
if( trackAsSeg.Distance( itemSeg ) < minDist )
SEG::ecoord thisDist_squared = trackSeg.SquaredDistance( itemSeg );
if( !minSeg || thisDist_squared < center2center_squared )
{
if( track->Type() == PCB_VIA_T )
{
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_VIA_NEAR_COPPER );
drcItem->SetItems( track, aItem );
wxPoint pos = getLocation( track, itemSeg );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
addMarkerToPcb( marker );
}
else
{
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_COPPER );
drcItem->SetItems( track, aItem );
wxPoint pos = getLocation( track, itemSeg );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
addMarkerToPcb( marker );
}
break;
minSeg = itemSeg;
center2center_squared = thisDist_squared;
}
}
if( center2center_squared < SEG::Square( center2centerAllowed ) )
{
int actual = std::max( 0.0, sqrt( center2center_squared ) - widths );
int errorCode = ( track->Type() == PCB_VIA_T ) ? DRCE_VIA_NEAR_COPPER
: DRCE_TRACK_NEAR_COPPER;
DRC_ITEM* drcItem = new DRC_ITEM( errorCode );
msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
clearanceSource,
MessageTextFromValue( userUnits(), minClearance, true ),
MessageTextFromValue( userUnits(), actual, true ) );
drcItem->SetErrorMessage( msg );
drcItem->SetItems( track, aItem );
wxPoint pos = getLocation( track, minSeg.get() );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
addMarkerToPcb( marker );
}
}
// Test pads
@ -1082,21 +1107,52 @@ void DRC::testCopperDrawItem( DRAWSEGMENT* aItem )
if( pad->GetParent() == aItem->GetParent() )
continue;
// Fast test to detect a pad candidate inside the text bounding box
// Finer test (time consumming) is made only for pads near the text.
int bb_radius = pad->GetBoundingRadius() + pad->GetClearance( nullptr );
VECTOR2I shape_pos( pad->ShapePos() );
if( !rect_area.Collide( SEG( shape_pos, shape_pos ), bb_radius ) )
continue;
wxString clearanceSource;
int minClearance = pad->GetClearance( nullptr, &clearanceSource );
int widths = itemWidth / 2;
int center2centerAllowed = minClearance + widths;
SHAPE_POLY_SET padOutline;
pad->TransformShapeWithClearanceToPolygon( padOutline, pad->GetClearance( NULL ) );
pad->TransformShapeWithClearanceToPolygon( padOutline, 0 );
for( const auto& itemSeg : itemShape )
OPT<SEG> minSeg;
SEG::ecoord center2center_squared = 0;
for( const SEG& itemSeg : itemShape )
{
if( padOutline.Distance( itemSeg, itemWidth ) == 0 )
{
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_PAD_NEAR_COPPER );
drcItem->SetItems( pad, aItem );
SEG::ecoord thisCenter2center_squared = padOutline.SquaredDistance( itemSeg );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() );
addMarkerToPcb( marker );
break;
if( !minSeg || thisCenter2center_squared < center2center_squared )
{
minSeg = itemSeg;
center2center_squared = thisCenter2center_squared;
}
}
if( center2center_squared < SEG::Square( center2centerAllowed ) )
{
int actual = std::max( 0.0, sqrt( center2center_squared ) - widths );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_PAD_NEAR_COPPER );
msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
clearanceSource,
MessageTextFromValue( userUnits(), minClearance, true ),
MessageTextFromValue( userUnits(), actual, true ) );
drcItem->SetErrorMessage( msg );
drcItem->SetItems( pad, aItem );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() );
addMarkerToPcb( marker );
}
}
}
@ -1109,7 +1165,7 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
return;
std::vector<wxPoint> textShape; // a buffer to store the text shape (set of segments)
int penWidth = text->GetEffectiveTextPenWidth();
int penWidth = text->GetEffectiveTextPenWidth();
// So far the bounding box makes up the text-area
text->TransformTextShapeToSegmentList( textShape );
@ -1117,8 +1173,9 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
if( textShape.size() == 0 ) // Should not happen (empty text?)
return;
EDA_RECT bbox = text->GetTextBox();
EDA_RECT bbox = text->GetTextBox();
SHAPE_RECT rect_area( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
wxString msg;
// Test tracks and vias
for( auto track : m_pcb->Tracks() )
@ -1126,40 +1183,51 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
if( !track->IsOnLayer( aTextItem->GetLayer() ) )
continue;
int minDist = ( track->GetWidth() + penWidth ) / 2 + track->GetClearance( NULL );
SEG trackAsSeg( track->GetStart(), track->GetEnd() );
wxString clearanceSource;
int minClearance = track->GetClearance( nullptr, &clearanceSource );
int widths = ( track->GetWidth() + penWidth ) / 2;
int center2centerAllowed = minClearance + widths;
// Fast test to detect a trach segment candidate inside the text bounding box
if( !rect_area.Collide( trackAsSeg, minDist ) )
SEG trackSeg( track->GetStart(), track->GetEnd() );
// Fast test to detect a track segment candidate inside the text bounding box
if( !rect_area.Collide( trackSeg, center2centerAllowed ) )
continue;
OPT<SEG> minSeg;
SEG::ecoord center2center_squared = 0;
for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
{
SEG textSeg( textShape[jj], textShape[jj+1] );
SEG textSeg( textShape[jj], textShape[jj+1] );
SEG::ecoord thisDist_squared = trackSeg.SquaredDistance( textSeg );
if( trackAsSeg.Distance( textSeg ) < minDist )
if( !minSeg || thisDist_squared < center2center_squared )
{
if( track->Type() == PCB_VIA_T )
{
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_VIA_NEAR_COPPER );
drcItem->SetItems( track, aTextItem );
wxPoint pos = getLocation( track, textSeg );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
addMarkerToPcb( marker );
}
else
{
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_COPPER );
drcItem->SetItems( track, aTextItem );
wxPoint pos = getLocation( track, textSeg );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
addMarkerToPcb( marker );
}
break;
minSeg = textSeg;
center2center_squared = thisDist_squared;
}
}
if( center2center_squared < SEG::Square( center2centerAllowed ) )
{
int actual = std::max( 0.0, sqrt( center2center_squared ) - widths );
int errorCode = ( track->Type() == PCB_VIA_T ) ? DRCE_VIA_NEAR_COPPER
: DRCE_TRACK_NEAR_COPPER;
DRC_ITEM* drcItem = new DRC_ITEM( errorCode );
msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
clearanceSource,
MessageTextFromValue( userUnits(), minClearance, true ),
MessageTextFromValue( userUnits(), actual, true ) );
drcItem->SetErrorMessage( msg );
drcItem->SetItems( track, aTextItem );
wxPoint pos = getLocation( track, minSeg.get() );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
addMarkerToPcb( marker );
}
}
// Test pads
@ -1176,25 +1244,45 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
if( !rect_area.Collide( SEG( shape_pos, shape_pos ), bb_radius ) )
continue;
SHAPE_POLY_SET padOutline;
wxString clearanceSource;
int minClearance = pad->GetClearance( nullptr, &clearanceSource );
int widths = penWidth / 2;
int center2centerAllowed = minClearance + widths;
int minDist = penWidth / 2 + pad->GetClearance( NULL );
SHAPE_POLY_SET padOutline;
pad->TransformShapeWithClearanceToPolygon( padOutline, 0 );
OPT<SEG> minSeg;
SEG::ecoord center2center_squared = 0;
for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
{
SEG textSeg( textShape[jj], textShape[jj+1] );
SEG textSeg( textShape[jj], textShape[jj+1] );
SEG::ecoord thisCenter2center_squared = padOutline.SquaredDistance( textSeg );
if( padOutline.Distance( textSeg, 0 ) <= minDist )
if( !minSeg || thisCenter2center_squared < center2center_squared )
{
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_PAD_NEAR_COPPER );
drcItem->SetItems( pad, aTextItem );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() );
addMarkerToPcb( marker );
break;
minSeg = textSeg;
center2center_squared = thisCenter2center_squared;
}
}
if( center2center_squared < SEG::Square( center2centerAllowed ) )
{
int actual = std::max( 0.0, sqrt( center2center_squared ) - widths );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_PAD_NEAR_COPPER );
msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
clearanceSource,
MessageTextFromValue( userUnits(), minClearance, true ),
MessageTextFromValue( userUnits(), actual, true ) );
drcItem->SetErrorMessage( msg );
drcItem->SetItems( pad, aTextItem );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() );
addMarkerToPcb( marker );
}
}
}
@ -1568,7 +1656,7 @@ wxPoint DRC::getLocation( TRACK* aTrack, ZONE_CONTAINER* aConflictZone ) const
wxPoint pt2 = aTrack->GetEnd();
// If the mid-point is in the zone, then that's a fine place for the marker
if( conflictOutline->Distance( ( pt1 + pt2 ) / 2 ) == 0 )
if( conflictOutline->SquaredDistance( ( pt1 + pt2 ) / 2 ) == 0 )
return ( pt1 + pt2 ) / 2;
// Otherwise do a binary search for a "good enough" marker location
@ -1576,7 +1664,7 @@ wxPoint DRC::getLocation( TRACK* aTrack, ZONE_CONTAINER* aConflictZone ) const
{
while( GetLineLength( pt1, pt2 ) > EPSILON )
{
if( conflictOutline->Distance( pt1 ) < conflictOutline->Distance( pt2 ) )
if( conflictOutline->SquaredDistance( pt1 ) < conflictOutline->SquaredDistance( pt2 ) )
pt2 = ( pt1 + pt2 ) / 2;
else
pt1 = ( pt1 + pt2 ) / 2;

View File

@ -43,12 +43,6 @@
#include <macros.h>
static SEG::ecoord square( int a )
{
return SEG::ecoord( a ) * a;
}
/**
* compare 2 convex polygons and return true if distance > aDist (if no error DRC)
* i.e if for each edge of the first polygon distance from each edge of the other polygon
@ -366,7 +360,7 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
// Avoid square-roots if possible (for performance)
SEG::ecoord center2center_squared = refSeg.SquaredDistance( slotSeg );
if( center2center_squared < square( center2centerAllowed ) )
if( center2center_squared < SEG::Square( center2centerAllowed ) )
{
int actual = std::max( 0.0, sqrt( center2center_squared ) - widths );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_THROUGH_HOLE );
@ -460,7 +454,7 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
if( !m_reportAllTrackErrors )
return;
}
else if( center2center_squared < square( center2centerAllowed ) )
else if( center2center_squared < SEG::Square( center2centerAllowed ) )
{
int errorCode = DRCE_TRACK_ENDS;
@ -511,23 +505,26 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
wxString clearanceSource;
int minClearance = aRefSeg->GetClearance( zone, &clearanceSource );
int widths = refSegWidth / 2;
int center2centerAllowed = minClearance + widths;
SHAPE_POLY_SET* outline = const_cast<SHAPE_POLY_SET*>( &zone->GetFilledPolysList() );
int error = minClearance - outline->Distance( testSeg, refSegWidth );
SEG::ecoord center2center_squared = outline->SquaredDistance( testSeg );
// to avoid false positive, due to rounding issues and approxiamtions
// in distance and clearance calculations, use a small threshold for distance
// (1 micron)
#define THRESHOLD_DIST Millimeter2iu( 0.001 )
if( error > THRESHOLD_DIST )
if( center2center_squared + THRESHOLD_DIST < SEG::Square( center2centerAllowed ) )
{
int actual = std::max( 0.0, sqrt( center2center_squared ) - widths );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_ZONE );
msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
clearanceSource,
MessageTextFromValue( userUnits(), minClearance, true ),
MessageTextFromValue( userUnits(), minClearance - error, true ) );
MessageTextFromValue( userUnits(), actual, true ) );
drcItem->SetErrorMessage( msg );
drcItem->SetItems( aRefSeg, zone );
@ -560,7 +557,7 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
{
SEG::ecoord center2center_squared = testSeg.SquaredDistance( *it );
if( center2center_squared < square( center2centerAllowed ) )
if( center2center_squared < SEG::Square( center2centerAllowed ) )
{
VECTOR2I pt = testSeg.NearestPoint( *it );
@ -861,7 +858,7 @@ bool DRC::checkClearanceSegmToPad( const SEG& refSeg, int refSegWidth, const D_P
// Avoid square-roots if possible (for performance)
SEG::ecoord center2center_squared = refSeg.SquaredDistance( padSeg );
if( center2center_squared < square( center2centerAllowed ) )
if( center2center_squared < SEG::Square( center2centerAllowed ) )
{
*aActualDist = std::max( 0.0, sqrt( center2center_squared ) - widths );
return false;

View File

@ -140,7 +140,7 @@ BOOST_AUTO_TEST_CASE( SegDistance )
{
SHAPE_POLY_SET polyset = c.m_polyset;
int dist = polyset.Distance( c.m_seg, c.m_seg_width );
int dist = sqrt( polyset.SquaredDistance( c.m_seg ) ) - c.m_seg_width;
// right answer?
BOOST_CHECK_PREDICATE( KI_TEST::IsWithin<int>, ( dist )( c.m_exp_dist )( 1 ) );