Move rest of DRC to SHAPE collision architecture.
This commit is contained in:
parent
2a1550d1d2
commit
d85a707385
|
@ -430,7 +430,7 @@ COBJECT2D *BOARD_ADAPTER::createNewPadDrill( const D_PAD* aPad, int aInflateValu
|
|||
}
|
||||
else // Oblong hole
|
||||
{
|
||||
const std::shared_ptr<SHAPE_SEGMENT>& seg = aPad->GetEffectiveHoleShape();
|
||||
const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape();
|
||||
float width = seg->GetWidth() + aInflateValue * 2;
|
||||
|
||||
SFVEC2F start3DU( seg->GetSeg().A.x * m_biuTo3Dunits,
|
||||
|
|
|
@ -90,6 +90,16 @@ public:
|
|||
return VECTOR2I( m_w, m_h ).EuclideanNorm();
|
||||
}
|
||||
|
||||
bool Collide( const SHAPE* aShape, int aClearance, VECTOR2I* aMTV ) const override
|
||||
{
|
||||
return SHAPE::Collide( aShape, aClearance, aMTV );
|
||||
}
|
||||
|
||||
bool Collide( const SHAPE* aShape, int aClearance = 0, int* aActual = nullptr ) const override
|
||||
{
|
||||
return SHAPE::Collide( aShape, aClearance, aActual );
|
||||
}
|
||||
|
||||
/// @copydoc SHAPE::Collide()
|
||||
bool Collide( const SEG& aSeg, int aClearance = 0, int* aActual = nullptr ) const override;
|
||||
|
||||
|
|
|
@ -54,6 +54,16 @@ public:
|
|||
return BOX2I( m_seg.A, m_seg.B - m_seg.A ).Inflate( aClearance + ( m_width + 1 ) / 2 );
|
||||
}
|
||||
|
||||
bool Collide( const SHAPE* aShape, int aClearance, VECTOR2I* aMTV ) const override
|
||||
{
|
||||
return SHAPE::Collide( aShape, aClearance, aMTV );
|
||||
}
|
||||
|
||||
bool Collide( const SHAPE* aShape, int aClearance = 0, int* aActual = nullptr ) const override
|
||||
{
|
||||
return SHAPE::Collide( aShape, aClearance, aActual );
|
||||
}
|
||||
|
||||
bool Collide( const SEG& aSeg, int aClearance = 0, int* aActual = nullptr ) const override
|
||||
{
|
||||
int min_dist = ( m_width + 1 ) / 2 + aClearance;
|
||||
|
|
|
@ -651,7 +651,7 @@ bool D_PAD::TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
|||
if( !drillsize.x || !drillsize.y )
|
||||
return false;
|
||||
|
||||
const std::shared_ptr<SHAPE_SEGMENT>& seg = GetEffectiveHoleShape();
|
||||
const SHAPE_SEGMENT* seg = GetEffectiveHoleShape();
|
||||
|
||||
TransformSegmentToPolygon( aCornerBuffer, (wxPoint) seg->GetSeg().A, (wxPoint) seg->GetSeg().B,
|
||||
aError, seg->GetWidth() + aInflateValue * 2 );
|
||||
|
|
|
@ -200,12 +200,12 @@ const std::vector<std::shared_ptr<SHAPE>>& D_PAD::GetEffectiveShapes() const
|
|||
}
|
||||
|
||||
|
||||
const std::shared_ptr<SHAPE_SEGMENT>& D_PAD::GetEffectiveHoleShape() const
|
||||
const SHAPE_SEGMENT* D_PAD::GetEffectiveHoleShape() const
|
||||
{
|
||||
if( m_shapesDirty )
|
||||
BuildEffectiveShapes();
|
||||
|
||||
return m_effectiveHoleShape;
|
||||
return m_effectiveHoleShape.get();
|
||||
}
|
||||
|
||||
|
||||
|
@ -761,39 +761,6 @@ void D_PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>
|
|||
}
|
||||
|
||||
|
||||
void D_PAD::GetOblongGeometry( const wxSize& aDrillOrPadSize,
|
||||
wxPoint* aStartPoint, wxPoint* aEndPoint, int* aWidth ) const
|
||||
{
|
||||
// calculates the start point, end point and width
|
||||
// of an equivalent segment which have the same position and width as the pad or hole
|
||||
int delta_cx, delta_cy;
|
||||
|
||||
wxSize halfsize = aDrillOrPadSize / 2;
|
||||
wxPoint offset;
|
||||
|
||||
if( aDrillOrPadSize.x > aDrillOrPadSize.y ) // horizontal
|
||||
{
|
||||
delta_cx = halfsize.x - halfsize.y;
|
||||
delta_cy = 0;
|
||||
*aWidth = aDrillOrPadSize.y;
|
||||
}
|
||||
else // vertical
|
||||
{
|
||||
delta_cx = 0;
|
||||
delta_cy = halfsize.y - halfsize.x;
|
||||
*aWidth = aDrillOrPadSize.x;
|
||||
}
|
||||
|
||||
RotatePoint( &delta_cx, &delta_cy, m_Orient );
|
||||
|
||||
aStartPoint->x = delta_cx + offset.x;
|
||||
aStartPoint->y = delta_cy + offset.y;
|
||||
|
||||
aEndPoint->x = - delta_cx + offset.x;
|
||||
aEndPoint->y = - delta_cy + offset.y;
|
||||
}
|
||||
|
||||
|
||||
bool D_PAD::HitTest( const wxPoint& aPosition, int aAccuracy ) const
|
||||
{
|
||||
VECTOR2I delta = aPosition - GetPosition();
|
||||
|
@ -846,6 +813,64 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con
|
|||
}
|
||||
|
||||
|
||||
bool D_PAD::Collide( const D_PAD* aPad, int aMinClearance, int* aActual )
|
||||
{
|
||||
int center2center = KiROUND( EuclideanNorm( aPad->ShapePos() - ShapePos() ) );
|
||||
|
||||
// Quick test: Clearance is OK if the bounding circles are further away than aMinClearance
|
||||
if( center2center - GetBoundingRadius() - aPad->GetBoundingRadius() >= aMinClearance )
|
||||
return false;
|
||||
|
||||
int actual = INT_MAX;
|
||||
|
||||
for( const std::shared_ptr<SHAPE>& aShape : GetEffectiveShapes() )
|
||||
{
|
||||
for( const std::shared_ptr<SHAPE>& bShape : aPad->GetEffectiveShapes() )
|
||||
{
|
||||
int this_dist;
|
||||
|
||||
if( aShape->Collide( bShape.get(), aMinClearance, &this_dist ) )
|
||||
actual = std::min( actual, this_dist );
|
||||
}
|
||||
}
|
||||
|
||||
if( actual < INT_MAX )
|
||||
{
|
||||
// returns the actual clearance (clearance < aMinClearance) for diags:
|
||||
if( aActual )
|
||||
*aActual = std::max( 0, actual );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool D_PAD::Collide( const SHAPE_SEGMENT* aSeg, int aMinClearance, int* aActual )
|
||||
{
|
||||
int actual = INT_MAX;
|
||||
|
||||
for( const std::shared_ptr<SHAPE>& shape : GetEffectiveShapes() )
|
||||
{
|
||||
int this_dist;
|
||||
|
||||
if( shape->Collide( aSeg, aMinClearance, &this_dist ) )
|
||||
actual = std::min( actual, this_dist );
|
||||
}
|
||||
|
||||
if( actual < INT_MAX )
|
||||
{
|
||||
if( aActual )
|
||||
*aActual = std::max( 0, actual );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int D_PAD::Compare( const D_PAD* padref, const D_PAD* padcmp )
|
||||
{
|
||||
int diff;
|
||||
|
|
|
@ -321,12 +321,6 @@ public:
|
|||
|
||||
bool IsDirty() const { return m_shapesDirty; }
|
||||
|
||||
/**
|
||||
* JEY TODO: temporary until Tom is done with DRC stuff....
|
||||
*/
|
||||
void GetOblongGeometry( const wxSize& aDrillOrPadSize,
|
||||
wxPoint* aStartPoint, wxPoint* aEndPoint, int* aWidth ) const;
|
||||
|
||||
void SetLayerSet( LSET aLayerMask ) { m_layerMask = aLayerMask; }
|
||||
LSET GetLayerSet() const override { return m_layerMask; }
|
||||
|
||||
|
@ -394,7 +388,7 @@ public:
|
|||
* Function GetEffectiveHoleShape
|
||||
* Returns a list of SHAPE objects representing the pad's hole.
|
||||
*/
|
||||
const std::shared_ptr<SHAPE_SEGMENT>& GetEffectiveHoleShape() const;
|
||||
const SHAPE_SEGMENT* GetEffectiveHoleShape() const;
|
||||
|
||||
/**
|
||||
* Function GetBoundingRadius
|
||||
|
@ -513,6 +507,9 @@ public:
|
|||
bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
|
||||
bool Collide( const SHAPE_SEGMENT* aSeg, int aMinClearance, int* aActual = nullptr );
|
||||
bool Collide( const D_PAD* aPad, int aMinClearance, int* aActual = nullptr );
|
||||
|
||||
wxString GetClass() const override
|
||||
{
|
||||
return wxT( "PAD" );
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <dialog_drc.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <board_commit.h>
|
||||
#include <geometry/shape_segment.h>
|
||||
#include <geometry/shape_arc.h>
|
||||
#include <drc/drc.h>
|
||||
#include <drc/drc_rule_parser.h>
|
||||
|
@ -61,6 +62,7 @@
|
|||
#include <drc/footprint_tester.h>
|
||||
#include <dialogs/panel_setup_rules.h>
|
||||
|
||||
|
||||
DRC::DRC() :
|
||||
PCB_TOOL_BASE( "pcbnew.DRCTool" ),
|
||||
m_editFrame( nullptr ),
|
||||
|
@ -538,11 +540,11 @@ void DRC::testPadClearances( BOARD_COMMIT& aCommit )
|
|||
|
||||
for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
|
||||
{
|
||||
SHAPE_SEGMENT edge( *it );
|
||||
int actual;
|
||||
|
||||
if( !checkClearanceSegmToPad( *it, 0, pad, minClearance, &actual ) )
|
||||
if( pad->Collide( &edge, minClearance, &actual ) )
|
||||
{
|
||||
actual = std::max( 0, actual );
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_COPPER_EDGE_CLEARANCE );
|
||||
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||
|
@ -906,101 +908,26 @@ void DRC::testCopperTextAndGraphics( BOARD_COMMIT& aCommit )
|
|||
|
||||
void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
|
||||
{
|
||||
EDA_RECT bbox;
|
||||
std::vector<SEG> itemShape;
|
||||
int itemWidth;
|
||||
DRAWSEGMENT* drawItem = dynamic_cast<DRAWSEGMENT*>( aItem );
|
||||
EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aItem );
|
||||
EDA_RECT bbox;
|
||||
std::vector<SHAPE*> itemShapes;
|
||||
DRAWSEGMENT* drawItem = dynamic_cast<DRAWSEGMENT*>( aItem );
|
||||
EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aItem );
|
||||
|
||||
if( drawItem )
|
||||
{
|
||||
bbox = drawItem->GetBoundingBox();
|
||||
itemWidth = drawItem->GetWidth();
|
||||
|
||||
switch( drawItem->GetShape() )
|
||||
{
|
||||
case S_ARC:
|
||||
{
|
||||
SHAPE_ARC arc( drawItem->GetCenter(), drawItem->GetArcStart(),
|
||||
(double) drawItem->GetAngle() / 10.0 );
|
||||
|
||||
SHAPE_LINE_CHAIN l = arc.ConvertToPolyline();
|
||||
|
||||
for( int i = 0; i < l.SegmentCount(); i++ )
|
||||
itemShape.push_back( l.Segment( i ) );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case S_SEGMENT:
|
||||
itemShape.emplace_back( SEG( drawItem->GetStart(), drawItem->GetEnd() ) );
|
||||
break;
|
||||
|
||||
case S_RECT:
|
||||
{
|
||||
std::vector<wxPoint> pts;
|
||||
drawItem->GetRectCorners( &pts );
|
||||
|
||||
itemShape.emplace_back( SEG( pts[0], pts[1] ) );
|
||||
itemShape.emplace_back( SEG( pts[1], pts[2] ) );
|
||||
itemShape.emplace_back( SEG( pts[2], pts[3] ) );
|
||||
itemShape.emplace_back( SEG( pts[3], pts[0] ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case S_CIRCLE:
|
||||
{
|
||||
// SHAPE_CIRCLE has no ConvertToPolyline() method, so use a 360.0 SHAPE_ARC
|
||||
SHAPE_ARC circle( drawItem->GetCenter(), drawItem->GetEnd(), 360.0 );
|
||||
|
||||
SHAPE_LINE_CHAIN l = circle.ConvertToPolyline();
|
||||
|
||||
for( int i = 0; i < l.SegmentCount(); i++ )
|
||||
itemShape.push_back( l.Segment( i ) );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case S_CURVE:
|
||||
{
|
||||
drawItem->RebuildBezierToSegmentsPointsList( drawItem->GetWidth() );
|
||||
wxPoint start_pt = drawItem->GetBezierPoints()[0];
|
||||
|
||||
for( unsigned int jj = 1; jj < drawItem->GetBezierPoints().size(); jj++ )
|
||||
{
|
||||
wxPoint end_pt = drawItem->GetBezierPoints()[jj];
|
||||
itemShape.emplace_back( SEG( start_pt, end_pt ) );
|
||||
start_pt = end_pt;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case S_POLYGON:
|
||||
{
|
||||
SHAPE_LINE_CHAIN l = drawItem->GetPolyShape().Outline( 0 );
|
||||
|
||||
for( int i = 0; i < l.SegmentCount(); i++ )
|
||||
itemShape.push_back( l.Segment( i ) );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "DRC::testCopperDrawItem unsupported DRAWSEGMENT shape: "
|
||||
+ STROKE_T_asString( drawItem->GetShape() ) );
|
||||
break;
|
||||
}
|
||||
itemShapes = drawItem->MakeEffectiveShapes();
|
||||
}
|
||||
else if( textItem )
|
||||
else if( textItem )
|
||||
{
|
||||
bbox = textItem->GetTextBox();
|
||||
itemWidth = textItem->GetEffectiveTextPenWidth();
|
||||
|
||||
std::vector<wxPoint> textShape;
|
||||
textItem->TransformTextShapeToSegmentList( textShape );
|
||||
int penWidth = textItem->GetEffectiveTextPenWidth();
|
||||
std::vector<wxPoint> pts;
|
||||
textItem->TransformTextShapeToSegmentList( pts );
|
||||
|
||||
for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
|
||||
itemShape.emplace_back( SEG( textShape[jj], textShape[jj+1] ) );
|
||||
for( unsigned jj = 0; jj < pts.size(); jj += 2 )
|
||||
itemShapes.push_back( new SHAPE_SEGMENT( pts[jj], pts[jj+1], penWidth ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1008,10 +935,7 @@ void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
|
|||
return;
|
||||
}
|
||||
|
||||
SHAPE_RECT rect_area( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
|
||||
|
||||
if( itemShape.empty() )
|
||||
return;
|
||||
SHAPE_RECT bboxShape( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
|
||||
|
||||
// Test tracks and vias
|
||||
for( auto track : m_pcb->Tracks() )
|
||||
|
@ -1019,44 +943,42 @@ void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
|
|||
if( !track->IsOnLayer( aItem->GetLayer() ) )
|
||||
continue;
|
||||
|
||||
int minClearance = track->GetClearance( aItem, &m_clearanceSource );
|
||||
int widths = ( track->GetWidth() + itemWidth ) / 2;
|
||||
int center2centerAllowed = minClearance + widths;
|
||||
int minClearance = track->GetClearance( aItem, &m_clearanceSource );
|
||||
int actual = INT_MAX;
|
||||
wxPoint pos;
|
||||
|
||||
SEG trackSeg( track->GetStart(), track->GetEnd() );
|
||||
SHAPE_SEGMENT trackSeg( track->GetStart(), track->GetEnd(), track->GetWidth() );
|
||||
|
||||
// Fast test to detect a track segment candidate inside the text bounding box
|
||||
if( !rect_area.Collide( trackSeg, center2centerAllowed ) )
|
||||
if( !bboxShape.Collide( &trackSeg, 0 ) )
|
||||
continue;
|
||||
|
||||
OPT<SEG> minSeg;
|
||||
SEG::ecoord center2center_squared = 0;
|
||||
|
||||
for( const SEG& itemSeg : itemShape )
|
||||
for( const SHAPE* shape : itemShapes )
|
||||
{
|
||||
SEG::ecoord thisDist_squared = trackSeg.SquaredDistance( itemSeg );
|
||||
int this_dist;
|
||||
|
||||
if( !minSeg || thisDist_squared < center2center_squared )
|
||||
if( shape->Collide( &trackSeg, minClearance, &this_dist ) )
|
||||
{
|
||||
minSeg = itemSeg;
|
||||
center2center_squared = thisDist_squared;
|
||||
if( this_dist < actual )
|
||||
{
|
||||
actual = this_dist;
|
||||
pos = (wxPoint) shape->Centre();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( center2center_squared < SEG::Square( center2centerAllowed ) )
|
||||
if( actual < INT_MAX )
|
||||
{
|
||||
int actual = std::max( 0.0, sqrt( center2center_squared ) - widths );
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||
m_clearanceSource,
|
||||
MessageTextFromValue( userUnits(), minClearance, true ),
|
||||
MessageTextFromValue( userUnits(), actual, true ) );
|
||||
MessageTextFromValue( userUnits(), std::max( 0, actual ), true ) );
|
||||
|
||||
drcItem->SetErrorMessage( m_msg );
|
||||
drcItem->SetItems( track, aItem );
|
||||
|
||||
wxPoint pos = GetLocation( track, minSeg.get() );
|
||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
|
||||
addMarkerToPcb( aCommit, marker );
|
||||
}
|
||||
|
@ -1073,42 +995,34 @@ void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
|
|||
continue;
|
||||
|
||||
int minClearance = pad->GetClearance( aItem, &m_clearanceSource );
|
||||
int widths = itemWidth / 2;
|
||||
int center2centerAllowed = minClearance + widths;
|
||||
int actual = INT_MAX;
|
||||
|
||||
// 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() + minClearance;
|
||||
|
||||
if( !rect_area.Collide( SEG( pad->GetPosition(), pad->GetPosition() ), bb_radius ) )
|
||||
if( !bboxShape.Collide( SEG( pad->GetPosition(), pad->GetPosition() ), bb_radius ) )
|
||||
continue;
|
||||
|
||||
SHAPE_POLY_SET padOutline;
|
||||
pad->TransformShapeWithClearanceToPolygon( padOutline, 0 );
|
||||
|
||||
OPT<SEG> minSeg;
|
||||
SEG::ecoord center2center_squared = 0;
|
||||
|
||||
for( const SEG& itemSeg : itemShape )
|
||||
for( const std::shared_ptr<SHAPE>& aShape : pad->GetEffectiveShapes() )
|
||||
{
|
||||
SEG::ecoord thisCenter2center_squared = padOutline.SquaredDistance( itemSeg );
|
||||
|
||||
if( !minSeg || thisCenter2center_squared < center2center_squared )
|
||||
for( const SHAPE* bShape : itemShapes )
|
||||
{
|
||||
minSeg = itemSeg;
|
||||
center2center_squared = thisCenter2center_squared;
|
||||
int this_dist;
|
||||
|
||||
if( aShape->Collide( bShape, minClearance, &this_dist ) )
|
||||
actual = std::min( actual, this_dist );
|
||||
}
|
||||
}
|
||||
|
||||
if( center2center_squared < SEG::Square( center2centerAllowed ) )
|
||||
if( actual < INT_MAX )
|
||||
{
|
||||
int actual = std::max( 0.0, sqrt( center2center_squared ) - widths );
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||
m_clearanceSource,
|
||||
MessageTextFromValue( userUnits(), minClearance, true ),
|
||||
MessageTextFromValue( userUnits(), actual, true ) );
|
||||
MessageTextFromValue( userUnits(), std::max( 0, actual ), true ) );
|
||||
|
||||
drcItem->SetErrorMessage( m_msg );
|
||||
drcItem->SetItems( pad, aItem );
|
||||
|
@ -1117,6 +1031,9 @@ void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
|
|||
addMarkerToPcb( aCommit, marker );
|
||||
}
|
||||
}
|
||||
|
||||
for( SHAPE* shape : itemShapes )
|
||||
delete shape;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1217,15 +1134,6 @@ bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart,
|
|||
|
||||
LSET layerMask = aRefPad->GetLayerSet() & all_cu;
|
||||
|
||||
// For hole testing we use a dummy pad which is given the shape of the hole. Note that
|
||||
// this pad must have a parent because some functions expect a non-null parent to find
|
||||
// the pad's board.
|
||||
MODULE dummymodule( m_pcb ); // Creates a dummy parent
|
||||
D_PAD dummypad( &dummymodule );
|
||||
|
||||
// Ensure the hole is on all copper layers
|
||||
dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
|
||||
|
||||
for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
|
||||
{
|
||||
D_PAD* pad = *pad_list;
|
||||
|
@ -1260,22 +1168,12 @@ bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Here, we must test clearance between holes and pads
|
||||
* dummy pad size and shape is adjusted to pad drill size and shape
|
||||
*/
|
||||
if( pad->GetDrillSize().x )
|
||||
{
|
||||
// pad under testing has a hole, test this hole against pad reference
|
||||
dummypad.SetPosition( pad->GetPosition() );
|
||||
dummypad.SetSize( pad->GetDrillSize() );
|
||||
dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
|
||||
PAD_SHAPE_OVAL : PAD_SHAPE_CIRCLE );
|
||||
dummypad.SetOrientation( pad->GetOrientation() );
|
||||
|
||||
int minClearance = aRefPad->GetClearance( nullptr, &m_clearanceSource );
|
||||
int actual;
|
||||
|
||||
if( !checkClearancePadToPad( aRefPad, &dummypad, minClearance, &actual ) )
|
||||
if( aRefPad->Collide( pad->GetEffectiveHoleShape(), minClearance, &actual ) )
|
||||
{
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||
|
||||
|
@ -1293,18 +1191,12 @@ bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart,
|
|||
}
|
||||
}
|
||||
|
||||
if( aRefPad->GetDrillSize().x ) // pad reference has a hole
|
||||
if( aRefPad->GetDrillSize().x )
|
||||
{
|
||||
dummypad.SetPosition( aRefPad->GetPosition() );
|
||||
dummypad.SetSize( aRefPad->GetDrillSize() );
|
||||
dummypad.SetShape( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
|
||||
PAD_SHAPE_OVAL : PAD_SHAPE_CIRCLE );
|
||||
dummypad.SetOrientation( aRefPad->GetOrientation() );
|
||||
|
||||
int minClearance = pad->GetClearance( nullptr, &m_clearanceSource );
|
||||
int actual;
|
||||
|
||||
if( !checkClearancePadToPad( pad, &dummypad, minClearance, &actual ) )
|
||||
if( pad->Collide( aRefPad->GetEffectiveHoleShape(), minClearance, &actual ) )
|
||||
{
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||
|
||||
|
@ -1353,7 +1245,7 @@ bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart,
|
|||
int clearanceAllowed = minClearance - m_pcb->GetDesignSettings().GetDRCEpsilon();
|
||||
int actual;
|
||||
|
||||
if( !checkClearancePadToPad( aRefPad, pad, clearanceAllowed, &actual ) )
|
||||
if( aRefPad->Collide( pad, clearanceAllowed, &actual ) )
|
||||
{
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||
|
||||
|
|
|
@ -219,38 +219,6 @@ private:
|
|||
void doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aStartIt,
|
||||
TRACKS::iterator aEndIt, bool aTestZones );
|
||||
|
||||
//-----<single tests>----------------------------------------------
|
||||
|
||||
/**
|
||||
* @param aRefPad The reference pad to check
|
||||
* @param aPad Another pad to check against
|
||||
* @param aMinClearance is the minimum allowed distance between the pads
|
||||
* @param aActualDist [out] it the actual distance
|
||||
* (only guaranteed to be set for violations)
|
||||
* @return true if clearance between aRefPad and aPad is >= aMinClearance, else false
|
||||
*/
|
||||
bool checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad,
|
||||
int aMinClearance, int* aActualDist );
|
||||
|
||||
|
||||
/**
|
||||
* Check the distance from a pad to segment. This function uses several
|
||||
* instance variable not passed in:
|
||||
* @param aPad Is the pad involved in the check
|
||||
* @param aSegmentWidth width of the segment to test
|
||||
* @param aMinDist Is the minimum clearance needed
|
||||
* @param aActualDist [out] Is the actual clearance (only guarantted to be set on violations)
|
||||
*
|
||||
* @return true distance >= dist_min,
|
||||
* false if distance < dist_min
|
||||
*/
|
||||
bool checkClearanceSegmToPad( const SEG& seg, int segWidth, const D_PAD* pad,
|
||||
int minClearance, int* aActualDist );
|
||||
|
||||
|
||||
|
||||
//-----</single tests>---------------------------------------------
|
||||
|
||||
public:
|
||||
/**
|
||||
* Load the DRC rules. Must be called after the netclasses have been read.
|
||||
|
|
|
@ -30,49 +30,10 @@
|
|||
#include <class_track.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_marker_pcb.h>
|
||||
#include <math_for_graphics.h>
|
||||
#include <geometry/polygon_test_point_inside.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <geometry/shape_rect.h>
|
||||
|
||||
|
||||
/*
|
||||
* compare a trapezoid (can be rectangle) and a segment and return true if distance > aDist
|
||||
*/
|
||||
bool poly2segmentDRC( wxPoint* aTref, int aTrefCount, wxPoint aSegStart, wxPoint aSegEnd,
|
||||
int aDist, int* aActual )
|
||||
{
|
||||
/* Test if the segment is contained in the polygon.
|
||||
* This case is not covered by the following check if the segment is
|
||||
* completely contained in the polygon (because edges don't intersect)!
|
||||
*/
|
||||
if( TestPointInsidePolygon( aTref, aTrefCount, aSegStart ) )
|
||||
{
|
||||
*aActual = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
for( int ii = 0, jj = aTrefCount-1; ii < aTrefCount; jj = ii, ii++ )
|
||||
{ // for all edges in polygon
|
||||
double d;
|
||||
|
||||
if( TestForIntersectionOfStraightLineSegments( aTref[ii].x, aTref[ii].y, aTref[jj].x,
|
||||
aTref[jj].y, aSegStart.x, aSegStart.y,
|
||||
aSegEnd.x, aSegEnd.y, NULL, NULL, &d ) )
|
||||
{
|
||||
*aActual = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( d < aDist )
|
||||
{
|
||||
*aActual = KiROUND( d );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#include <geometry/shape_segment.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
|
||||
|
||||
void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aStartIt,
|
||||
|
@ -80,12 +41,12 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
{
|
||||
BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings();
|
||||
|
||||
SEG refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
|
||||
PCB_LAYER_ID refLayer = aRefSeg->GetLayer();
|
||||
LSET refLayerSet = aRefSeg->GetLayerSet();
|
||||
SHAPE_SEGMENT refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd(), aRefSeg->GetWidth() );
|
||||
PCB_LAYER_ID refLayer = aRefSeg->GetLayer();
|
||||
LSET refLayerSet = aRefSeg->GetLayerSet();
|
||||
|
||||
EDA_RECT refSegBB = aRefSeg->GetBoundingBox();
|
||||
int refSegWidth = aRefSeg->GetWidth();
|
||||
EDA_RECT refSegBB = aRefSeg->GetBoundingBox();
|
||||
int refSegWidth = aRefSeg->GetWidth();
|
||||
|
||||
|
||||
/******************************************/
|
||||
|
@ -319,18 +280,11 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
|
||||
if( pad->GetDrillSize().x > 0 )
|
||||
{
|
||||
// For hole testing we use a dummy pad which is a copy of the current pad
|
||||
// shrunk down to nothing but its hole.
|
||||
D_PAD dummypad( *pad );
|
||||
dummypad.SetSize( pad->GetDrillSize() );
|
||||
dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
|
||||
PAD_SHAPE_OVAL : PAD_SHAPE_CIRCLE );
|
||||
// Ensure the hole is on all copper layers
|
||||
const static LSET all_cu = LSET::AllCuMask();
|
||||
dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
|
||||
const SHAPE_SEGMENT* slot = pad->GetEffectiveHoleShape();
|
||||
DRC_RULE* rule = GetRule( aRefSeg, pad, CLEARANCE_CONSTRAINT );
|
||||
|
||||
int minClearance;
|
||||
DRC_RULE* rule = GetRule( aRefSeg, &dummypad, CLEARANCE_CONSTRAINT );
|
||||
int minClearance;
|
||||
int actual;
|
||||
|
||||
if( rule )
|
||||
{
|
||||
|
@ -342,27 +296,8 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
minClearance = aRefSeg->GetClearance( nullptr, &m_clearanceSource );
|
||||
}
|
||||
|
||||
/* Treat an oval hole as a line segment along the hole's major axis,
|
||||
* shortened by half its minor axis.
|
||||
* A circular hole is just a degenerate case of an oval hole.
|
||||
*/
|
||||
wxPoint slotStart, slotEnd;
|
||||
int slotWidth;
|
||||
|
||||
pad->GetOblongGeometry( pad->GetDrillSize(), &slotStart, &slotEnd, &slotWidth );
|
||||
slotStart += pad->GetPosition();
|
||||
slotEnd += pad->GetPosition();
|
||||
|
||||
SEG slotSeg( slotStart, slotEnd );
|
||||
int widths = ( slotWidth + refSegWidth ) / 2;
|
||||
int center2centerAllowed = minClearance + widths + bds.GetDRCEpsilon();
|
||||
|
||||
// Avoid square-roots if possible (for performance)
|
||||
SEG::ecoord center2center_squared = refSeg.SquaredDistance( slotSeg );
|
||||
|
||||
if( center2center_squared < SEG::Square( center2centerAllowed ) )
|
||||
if( slot->Collide( &refSeg, minClearance + bds.GetDRCEpsilon(), &actual ) )
|
||||
{
|
||||
int actual = std::max( 0.0, sqrt( center2center_squared ) - widths );
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||
|
@ -373,7 +308,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
drcItem->SetErrorMessage( m_msg );
|
||||
drcItem->SetItems( aRefSeg, pad );
|
||||
|
||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, GetLocation( aRefSeg, slotSeg ) );
|
||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() );
|
||||
addMarkerToPcb( aCommit, marker );
|
||||
|
||||
if( !m_reportAllTrackErrors )
|
||||
|
@ -382,13 +317,10 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
}
|
||||
|
||||
int minClearance = aRefSeg->GetClearance( pad, &m_clearanceSource );
|
||||
int clearanceAllowed = minClearance - bds.GetDRCEpsilon();
|
||||
int actual;
|
||||
|
||||
if( !checkClearanceSegmToPad( refSeg, refSegWidth, pad, clearanceAllowed, &actual ) )
|
||||
if( pad->Collide( &refSeg, minClearance - bds.GetDRCEpsilon(), &actual ) )
|
||||
{
|
||||
actual = std::max( 0, actual );
|
||||
SEG padSeg( pad->GetPosition(), pad->GetPosition() );
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||
|
@ -399,7 +331,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
drcItem->SetErrorMessage( m_msg );
|
||||
drcItem->SetItems( aRefSeg, pad );
|
||||
|
||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, GetLocation( aRefSeg, padSeg ) );
|
||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() );
|
||||
addMarkerToPcb( aCommit, marker );
|
||||
|
||||
if( !m_reportAllTrackErrors )
|
||||
|
@ -451,17 +383,12 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
if( !trackBB.Intersects( refSegBB ) )
|
||||
continue;
|
||||
|
||||
int minClearance = aRefSeg->GetClearance( track, &m_clearanceSource );
|
||||
SEG trackSeg( track->GetStart(), track->GetEnd() );
|
||||
int widths = ( refSegWidth + track->GetWidth() ) / 2;
|
||||
int center2centerAllowed = minClearance + widths;
|
||||
|
||||
// Avoid square-roots if possible (for performance)
|
||||
SEG::ecoord center2center_squared = refSeg.SquaredDistance( trackSeg );
|
||||
OPT_VECTOR2I intersection = refSeg.Intersect( trackSeg );
|
||||
int minClearance = aRefSeg->GetClearance( track, &m_clearanceSource );
|
||||
int actual;
|
||||
SHAPE_SEGMENT trackSeg( track->GetStart(), track->GetEnd(), track->GetWidth() );
|
||||
|
||||
// Check two tracks crossing first as it reports a DRCE without distances
|
||||
if( intersection )
|
||||
if( OPT_VECTOR2I intersection = refSeg.GetSeg().Intersect( trackSeg.GetSeg() ) )
|
||||
{
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TRACKS_CROSSING );
|
||||
drcItem->SetErrorMessage( m_msg );
|
||||
|
@ -473,9 +400,9 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
if( !m_reportAllTrackErrors )
|
||||
return;
|
||||
}
|
||||
else if( center2center_squared < SEG::Square( center2centerAllowed ) )
|
||||
else if( refSeg.Collide( &trackSeg, minClearance, &actual ) )
|
||||
{
|
||||
int actual = std::max( 0.0, sqrt( center2center_squared ) - widths );
|
||||
wxPoint pos = GetLocation( aRefSeg, trackSeg.GetSeg() );
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||
|
@ -486,7 +413,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
drcItem->SetErrorMessage( m_msg );
|
||||
drcItem->SetItems( aRefSeg, track );
|
||||
|
||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, GetLocation( aRefSeg, trackSeg ) );
|
||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
|
||||
addMarkerToPcb( aCommit, marker );
|
||||
|
||||
if( !m_reportAllTrackErrors )
|
||||
|
@ -515,28 +442,25 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
if( zone->GetNetCode() && zone->GetNetCode() == aRefSeg->GetNetCode() )
|
||||
continue;
|
||||
|
||||
int minClearance = aRefSeg->GetClearance( zone, &m_clearanceSource );
|
||||
int widths = refSegWidth / 2;
|
||||
int center2centerAllowed = minClearance + widths;
|
||||
SHAPE_POLY_SET* outline =
|
||||
const_cast<SHAPE_POLY_SET*>( &zone->GetFilledPolysList( layer ) );
|
||||
|
||||
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( center2center_squared + THRESHOLD_DIST < SEG::Square( center2centerAllowed ) )
|
||||
int minClearance = aRefSeg->GetClearance( zone, &m_clearanceSource );
|
||||
int widths = refSegWidth / 2;
|
||||
int allowedDist = minClearance + widths + THRESHOLD_DIST;
|
||||
int actual;
|
||||
|
||||
if( zone->GetFilledPolysList( layer ).Collide( testSeg, allowedDist, &actual ) )
|
||||
{
|
||||
int actual = std::max( 0.0, sqrt( center2center_squared ) - widths );
|
||||
actual = std::max( 0, actual - widths );
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||
m_clearanceSource,
|
||||
MessageTextFromValue( userUnits(), minClearance, true ),
|
||||
MessageTextFromValue( userUnits(), actual, true ) );
|
||||
m_clearanceSource,
|
||||
MessageTextFromValue( userUnits(), minClearance, true ),
|
||||
MessageTextFromValue( userUnits(), actual, true ) );
|
||||
|
||||
drcItem->SetErrorMessage( m_msg );
|
||||
drcItem->SetItems( aRefSeg, zone );
|
||||
|
@ -616,119 +540,3 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad, int aMinClearance, int* aActual )
|
||||
{
|
||||
int center2center = KiROUND( EuclideanNorm( aPad->ShapePos() - aRefPad->ShapePos() ) );
|
||||
|
||||
// Quick test: Clearance is OK if the bounding circles are further away than aMinClearance
|
||||
if( center2center - aRefPad->GetBoundingRadius() - aPad->GetBoundingRadius() >= aMinClearance )
|
||||
return true;
|
||||
|
||||
int actual = INT_MAX;
|
||||
|
||||
for( const std::shared_ptr<SHAPE>& aShape : aRefPad->GetEffectiveShapes() )
|
||||
{
|
||||
for( const std::shared_ptr<SHAPE>& bShape : aPad->GetEffectiveShapes() )
|
||||
{
|
||||
int this_dist;
|
||||
|
||||
if( aShape->Collide( bShape.get(), aMinClearance, &this_dist ) )
|
||||
actual = std::min( actual, this_dist );
|
||||
}
|
||||
}
|
||||
|
||||
if( actual < INT_MAX )
|
||||
{
|
||||
// returns the actual clearance (clearance < aMinClearance) for diags:
|
||||
if( aActual )
|
||||
*aActual = std::max( 0, actual );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Test if distance between a segment and a pad is > minClearance. Return the actual
|
||||
* distance if it is less.
|
||||
*/
|
||||
bool DRC::checkClearanceSegmToPad( const SEG& refSeg, int refSegWidth, const D_PAD* pad,
|
||||
int minClearance, int* aActualDist )
|
||||
{
|
||||
if( ( pad->GetShape() == PAD_SHAPE_CIRCLE || pad->GetShape() == PAD_SHAPE_OVAL ) )
|
||||
{
|
||||
/* Treat an oval pad as a line segment along the hole's major axis,
|
||||
* shortened by half its minor axis.
|
||||
* A circular pad is just a degenerate case of an oval hole.
|
||||
*/
|
||||
wxPoint padStart, padEnd;
|
||||
int padWidth;
|
||||
|
||||
pad->GetOblongGeometry( pad->GetSize(), &padStart, &padEnd, &padWidth );
|
||||
padStart += pad->ShapePos();
|
||||
padEnd += pad->ShapePos();
|
||||
|
||||
SEG padSeg( padStart, padEnd );
|
||||
int widths = ( padWidth + refSegWidth ) / 2;
|
||||
int center2centerAllowed = minClearance + widths;
|
||||
|
||||
// Avoid square-roots if possible (for performance)
|
||||
SEG::ecoord center2center_squared = refSeg.SquaredDistance( padSeg );
|
||||
|
||||
if( center2center_squared < SEG::Square( center2centerAllowed ) )
|
||||
{
|
||||
*aActualDist = std::max( 0.0, sqrt( center2center_squared ) - widths );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if( ( pad->GetShape() == PAD_SHAPE_RECT || pad->GetShape() == PAD_SHAPE_ROUNDRECT )
|
||||
&& ( (int) pad->GetOrientation() % 900 == 0 ) )
|
||||
{
|
||||
EDA_RECT padBBox = pad->GetBoundingBox();
|
||||
int widths = refSegWidth / 2;
|
||||
|
||||
// Note a ROUNDRECT pad with a corner radius = r can be treated as a smaller
|
||||
// RECT (size - 2*r) with a clearance increased by r
|
||||
if( pad->GetShape() == PAD_SHAPE_ROUNDRECT )
|
||||
{
|
||||
padBBox.Inflate( - pad->GetRoundRectCornerRadius() );
|
||||
widths += pad->GetRoundRectCornerRadius();
|
||||
}
|
||||
|
||||
SHAPE_RECT padShape( padBBox.GetPosition(), padBBox.GetWidth(), padBBox.GetHeight() );
|
||||
int actual;
|
||||
|
||||
if( padShape.Collide( refSeg, minClearance + widths, &actual ) )
|
||||
{
|
||||
*aActualDist = std::max( 0, actual - widths );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else // Convert the rest to polygons
|
||||
{
|
||||
SHAPE_POLY_SET polyset;
|
||||
|
||||
BOARD* board = pad->GetBoard();
|
||||
int maxError = board ? board->GetDesignSettings().m_MaxError : ARC_HIGH_DEF;
|
||||
|
||||
pad->TransformShapeWithClearanceToPolygon( polyset, 0, maxError );
|
||||
|
||||
const SHAPE_LINE_CHAIN& refpoly = polyset.COutline( 0 );
|
||||
int widths = refSegWidth / 2;
|
||||
int actual;
|
||||
|
||||
if( !poly2segmentDRC( (wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(),
|
||||
(wxPoint) refSeg.A, (wxPoint) refSeg.B,
|
||||
minClearance + widths, &actual ) )
|
||||
{
|
||||
*aActualDist = std::max( 0, actual - widths );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,12 +23,11 @@
|
|||
|
||||
|
||||
#include <drc/drc_keepout_tester.h>
|
||||
|
||||
#include <geometry/shape_segment.h>
|
||||
#include <class_module.h>
|
||||
#include <drc/drc.h>
|
||||
#include <drc/drc_item.h>
|
||||
|
||||
|
||||
DRC_KEEPOUT_TESTER::DRC_KEEPOUT_TESTER( MARKER_HANDLER aMarkerHandler ) :
|
||||
DRC_TEST_PROVIDER( std::move( aMarkerHandler ) ),
|
||||
m_units( EDA_UNITS::MILLIMETRES ),
|
||||
|
@ -91,11 +90,9 @@ bool DRC_KEEPOUT_TESTER::checkTracksAndVias()
|
|||
if( !m_zone->IsOnLayer( segm->GetLayer() ) )
|
||||
continue;
|
||||
|
||||
int widths = segm->GetWidth() / 2;
|
||||
SEG trackSeg( segm->GetStart(), segm->GetEnd() );
|
||||
SEG::ecoord center2center_squared = m_zone->Outline()->SquaredDistance( trackSeg );
|
||||
SEG trackSeg( segm->GetStart(), segm->GetEnd() );
|
||||
|
||||
if( center2center_squared <= SEG::Square( widths) )
|
||||
if( m_zone->Outline()->Collide( trackSeg, segm->GetWidth() / 2 ) )
|
||||
{
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_KEEPOUT );
|
||||
|
||||
|
@ -111,42 +108,37 @@ bool DRC_KEEPOUT_TESTER::checkTracksAndVias()
|
|||
}
|
||||
else if( segm->Type() == PCB_VIA_T && ( m_keepoutFlags & CHECK_VIAS_MASK ) != 0 )
|
||||
{
|
||||
VIA* via = static_cast<VIA*>( segm );
|
||||
int sourceId = 0;
|
||||
VIA* via = static_cast<VIA*>( segm );
|
||||
SEG seg( via->GetPosition(), via->GetPosition() );
|
||||
int test = 0;
|
||||
int clearance = via->GetWidth() / 2;
|
||||
|
||||
if( ( m_keepoutFlags & DISALLOW_VIAS ) > 0 )
|
||||
{
|
||||
sourceId = DISALLOW_VIAS;
|
||||
test = DISALLOW_VIAS;
|
||||
}
|
||||
else if( via->GetViaType() == VIATYPE::MICROVIA
|
||||
&& ( m_keepoutFlags & DISALLOW_MICRO_VIAS ) > 0 )
|
||||
{
|
||||
sourceId = DISALLOW_MICRO_VIAS;
|
||||
test = DISALLOW_MICRO_VIAS;
|
||||
}
|
||||
else if( via->GetViaType() == VIATYPE::BLIND_BURIED
|
||||
&& ( m_keepoutFlags & DISALLOW_BB_VIAS ) > 0 )
|
||||
{
|
||||
sourceId = DISALLOW_BB_VIAS;
|
||||
test = DISALLOW_BB_VIAS;
|
||||
}
|
||||
else if( ( m_keepoutFlags & DISALLOW_HOLES ) > 0 )
|
||||
{
|
||||
sourceId = DISALLOW_HOLES;
|
||||
test = DISALLOW_HOLES;
|
||||
clearance = via->GetDrillValue() / 2;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
int widths = via->GetWidth() / 2;
|
||||
wxPoint viaPos = via->GetPosition();
|
||||
|
||||
if( sourceId == DISALLOW_HOLES )
|
||||
widths = via->GetDrillValue() / 2;
|
||||
|
||||
SEG::ecoord center2center_squared = m_zone->Outline()->SquaredDistance( viaPos );
|
||||
|
||||
if( center2center_squared <= SEG::Square( widths ) )
|
||||
if( m_zone->Outline()->Collide( seg, clearance ) )
|
||||
{
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_KEEPOUT );
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), m_sources.at( sourceId ) );
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s)" ), m_sources.at( test ) );
|
||||
drcItem->SetErrorMessage( m_msg );
|
||||
drcItem->SetItems( segm, m_zone );
|
||||
|
||||
|
@ -259,18 +251,9 @@ bool DRC_KEEPOUT_TESTER::checkPads( MODULE* aModule )
|
|||
}
|
||||
else if( ( m_keepoutFlags & DISALLOW_HOLES ) > 0 )
|
||||
{
|
||||
wxPoint slotStart, slotEnd;
|
||||
int slotWidth;
|
||||
const SHAPE_SEGMENT* slot = pad->GetEffectiveHoleShape();
|
||||
|
||||
pad->GetOblongGeometry( pad->GetDrillSize(), &slotStart, &slotEnd, &slotWidth );
|
||||
slotStart += pad->GetPosition();
|
||||
slotEnd += pad->GetPosition();
|
||||
|
||||
SEG slotSeg( slotStart, slotEnd );
|
||||
SHAPE_POLY_SET* outline = m_zone->Outline();
|
||||
SEG::ecoord center2center_sq = outline->SquaredDistance( slotSeg );
|
||||
|
||||
if( center2center_sq <= SEG::Square( slotWidth) )
|
||||
if( m_zone->Outline()->Collide( slot->GetSeg(), slot->GetWidth() / 2 ) )
|
||||
{
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_KEEPOUT );
|
||||
|
||||
|
|
|
@ -765,8 +765,7 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer )
|
|||
// Choose drawing settings depending on if we are drawing a pad itself or a hole
|
||||
if( aLayer == LAYER_PADS_PLATEDHOLES || aLayer == LAYER_NON_PLATEDHOLES )
|
||||
{
|
||||
const std::shared_ptr<SHAPE_SEGMENT>& seg = aPad->GetEffectiveHoleShape();
|
||||
|
||||
const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape();
|
||||
m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, seg->GetWidth() );
|
||||
}
|
||||
else
|
||||
|
|
|
@ -698,7 +698,7 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||
else
|
||||
{
|
||||
// Note: small drill marks have no significance when applied to slots
|
||||
const std::shared_ptr<SHAPE_SEGMENT>& seg = pad->GetEffectiveHoleShape();
|
||||
const SHAPE_SEGMENT* seg = pad->GetEffectiveHoleShape();
|
||||
aPlotter->ThickSegment( (wxPoint) seg->GetSeg().A,
|
||||
(wxPoint) seg->GetSeg().B,
|
||||
seg->GetWidth(), SKETCH, NULL );
|
||||
|
|
Loading…
Reference in New Issue