Performance enhancements for DRC.

This commit is contained in:
Jeff Young 2020-09-17 17:32:42 +01:00
parent 8e530db633
commit 0f3d2147aa
5 changed files with 49 additions and 63 deletions

View File

@ -1582,14 +1582,11 @@ SEG::ecoord SHAPE_POLY_SET::SquaredDistanceToPolygon( VECTOR2I aPoint, int aPoly
CONST_SEGMENT_ITERATOR iterator = CIterateSegmentsWithHoles( aPolygonIndex );
SEG polygonEdge = *iterator;
SEG::ecoord minDistance = polygonEdge.SquaredDistance( aPoint );
SEG::ecoord minDistance = (*iterator).SquaredDistance( aPoint );
for( iterator++; iterator && minDistance > 0; iterator++ )
{
polygonEdge = *iterator;
SEG::ecoord currentDistance = polygonEdge.SquaredDistance( aPoint );
SEG::ecoord currentDistance = (*iterator).SquaredDistance( aPoint );
if( currentDistance < minDistance )
minDistance = currentDistance;
@ -1609,14 +1606,11 @@ SEG::ecoord SHAPE_POLY_SET::SquaredDistanceToPolygon( const SEG& aSegment, int a
return 0;
CONST_SEGMENT_ITERATOR iterator = CIterateSegmentsWithHoles( aPolygonIndex );
SEG polygonEdge = *iterator;
SEG::ecoord minDistance = polygonEdge.SquaredDistance( aSegment );
SEG::ecoord minDistance = (*iterator).SquaredDistance( aSegment );
for( iterator++; iterator && minDistance > 0; iterator++ )
{
polygonEdge = *iterator;
SEG::ecoord currentDistance = polygonEdge.SquaredDistance( aSegment );
SEG::ecoord currentDistance = (*iterator).SquaredDistance( aSegment );
if( currentDistance < minDistance )
minDistance = currentDistance;

View File

@ -252,15 +252,6 @@ void D_PAD::SetChamferRectRatio( double aChamferScale )
}
const std::vector<std::shared_ptr<SHAPE>>& D_PAD::GetEffectiveShapes( PCB_LAYER_ID aLayer ) const
{
if( m_shapesDirty )
BuildEffectiveShapes( aLayer );
return m_effectiveShapes;
}
const std::shared_ptr<SHAPE_POLY_SET>& D_PAD::GetEffectivePolygon( PCB_LAYER_ID aLayer ) const
{
if( m_shapesDirty )
@ -272,15 +263,10 @@ const std::shared_ptr<SHAPE_POLY_SET>& D_PAD::GetEffectivePolygon( PCB_LAYER_ID
std::shared_ptr<SHAPE> D_PAD::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
{
std::shared_ptr<SHAPE_COMPOUND> shape( new SHAPE_COMPOUND );
if( m_shapesDirty )
BuildEffectiveShapes( aLayer );
for( std::shared_ptr<SHAPE>& s : m_effectiveShapes )
shape->AddShape( s->Clone() ); // fixme: use COMPOUND everywhere
return shape;
return m_effectiveShape;
}
@ -304,12 +290,12 @@ int D_PAD::GetBoundingRadius() const
void D_PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
{
m_effectiveShapes.clear();
m_effectiveShape = std::make_shared<SHAPE_COMPOUND>();
m_effectiveHoleShape = nullptr;
auto add = [this]( SHAPE* aShape )
{
m_effectiveShapes.emplace_back( aShape );
m_effectiveShape->AddShape( aShape );
};
wxPoint shapePos = ShapePos(); // Fetch only once; rotation involves trig
@ -448,15 +434,10 @@ void D_PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
m_effectiveBoundingRadius += 1;
// reset the bbox to uninitialized state to prepare for merging
m_effectiveBoundingBox = EDA_RECT();
BOX2I bbox = m_effectiveShape->BBox();
m_effectiveBoundingBox = EDA_RECT( (wxPoint) bbox.GetPosition(),
wxSize( bbox.GetWidth(), bbox.GetHeight() ) );
for( const std::shared_ptr<SHAPE>& shape : m_effectiveShapes )
{
BOX2I r = shape->BBox();
m_effectiveBoundingBox.Merge( EDA_RECT( (wxPoint) r.GetOrigin(),
wxSize( r.GetWidth(), r.GetHeight() ) ) );
}
// Hole shape
//
wxSize half_size = m_drill / 2;

View File

@ -382,13 +382,11 @@ public:
// @copydoc BOARD_ITEM::GetEffectiveShape
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
const std::vector<std::shared_ptr<SHAPE>>& GetEffectiveShapes( PCB_LAYER_ID = UNDEFINED_LAYER ) const;
const std::shared_ptr<SHAPE_POLY_SET>& GetEffectivePolygon( PCB_LAYER_ID = UNDEFINED_LAYER ) const;
/**
* Function GetEffectiveHoleShape
* Returns a list of SHAPE objects representing the pad's hole.
* Returns a SHAPE object representing the pad's hole.
*/
const SHAPE_SEGMENT* GetEffectiveHoleShape() const;
@ -644,14 +642,14 @@ private:
* Editing definitions of primitives for custom pad shapes. In local coordinates relative
* to m_Pos (NOT shapePos) at orient 0.
*/
std::vector<std::shared_ptr<DRAWSEGMENT>> m_editPrimitives;
std::vector<std::shared_ptr<DRAWSEGMENT>> m_editPrimitives;
mutable bool m_shapesDirty;
mutable int m_effectiveBoundingRadius;
mutable EDA_RECT m_effectiveBoundingBox;
mutable std::vector<std::shared_ptr<SHAPE>> m_effectiveShapes;
mutable std::shared_ptr<SHAPE_SEGMENT> m_effectiveHoleShape;
mutable std::shared_ptr<SHAPE_POLY_SET> m_effectivePolygon;
mutable bool m_shapesDirty;
mutable int m_effectiveBoundingRadius;
mutable EDA_RECT m_effectiveBoundingBox;
mutable std::shared_ptr<SHAPE_COMPOUND> m_effectiveShape;
mutable std::shared_ptr<SHAPE_SEGMENT> m_effectiveHoleShape;
mutable std::shared_ptr<SHAPE_POLY_SET> m_effectivePolygon;
/*
* How to build the custom shape in zone, to create the clearance area:

View File

@ -292,7 +292,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* aItem )
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
{
// This is the number of tests between 2 calls to the progress bar
const int delta = m_drcEngine->GetTestTracksAgainstZones() ? 50 : 250;
const int delta = m_drcEngine->GetTestTracksAgainstZones() ? 25 : 100;
int count = m_board->Tracks().size();
reportProgress( 0.0 );
@ -322,9 +322,11 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, PCB_LAYER_I
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
SHAPE_SEGMENT refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd(), aRefSeg->GetWidth() );
EDA_RECT refSegBB = aRefSeg->GetBoundingBox();
EDA_RECT refSegInflatedBB = aRefSeg->GetBoundingBox();
int refSegWidth = aRefSeg->GetWidth();
refSegInflatedBB.Inflate( m_largestClearance );
/******************************************/
/* Phase 1 : test DRC track to pads : */
/******************************************/
@ -345,10 +347,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, PCB_LAYER_I
break;
// Preflight based on bounding boxes.
EDA_RECT inflatedBB = refSegBB;
inflatedBB.Inflate( pad->GetBoundingRadius() + m_largestClearance );
if( !inflatedBB.Contains( pad->GetPosition() ) )
if( !refSegInflatedBB.Intersects( pad->GetBoundingBox() ) )
continue;
/// Skip checking pad copper when it has been removed
@ -398,18 +397,23 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, PCB_LAYER_I
TRACK* track = *it;
if( track->Type() == PCB_VIA_T )
{
if( !track->GetLayerSet().test( aLayer ) )
continue;
}
else
{
if( track->GetLayer() != aLayer )
continue;
}
// No problem if segments have the same net code:
if( aRefSeg->GetNetCode() == track->GetNetCode() )
continue;
if( !track->GetLayerSet().test( aLayer ) )
continue;
// Preflight based on worst-case inflated bounding boxes:
EDA_RECT trackBB = track->GetBoundingBox();
trackBB.Inflate( m_largestClearance );
if( !trackBB.Intersects( refSegBB ) )
if( !refSegInflatedBB.Intersects( track->GetBoundingBox() ) )
continue;
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE,
@ -482,6 +486,9 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, PCB_LAYER_I
if( zone->GetFilledPolysList( aLayer ).IsEmpty() )
continue;
if( !refSegInflatedBB.Intersects( zone->GetBoundingBox() ) )
continue;
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE,
aRefSeg, zone, aLayer );
int minClearance = constraint.GetValue().Min();
@ -561,8 +568,11 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( int aRefPadIdx,
const static LSET all_cu = LSET::AllCuMask();
const BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
D_PAD* refPad = aSortedPadsList[aRefPadIdx];
LSET layerMask = refPad->GetLayerSet() & all_cu;
D_PAD* refPad = aSortedPadsList[aRefPadIdx];
LSET layerMask = refPad->GetLayerSet() & all_cu;
EDA_RECT refPadInflatedBB = refPad->GetBoundingBox();
refPadInflatedBB.Inflate( m_largestClearance );
for( int idx = aRefPadIdx; idx < (int)aSortedPadsList.size(); ++idx )
{
@ -616,6 +626,9 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( int aRefPadIdx,
continue;
}
if( !refPadInflatedBB.Intersects( pad->GetBoundingBox() ) )
continue;
for( PCB_LAYER_ID layer : refPad->GetLayerSet().Seq() )
{
if( exceedClearance )

View File

@ -200,7 +200,7 @@ void DRC_TEST_PROVIDER_HOLE_CLEARANCE::testPads2Holes()
D_PAD* pad = sortedPads[idx];
int x_limit = pad->GetPosition().x + pad->GetBoundingRadius() + max_size;
drc_dbg( 10,"-> %p\n", pad );
drc_dbg( 10, "-> %p\n", pad );
if( idx % delta == 0 || idx == (int) sortedPads.size() - 1 )
reportProgress( (double) idx / (double) sortedPads.size() );
@ -236,7 +236,7 @@ bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( int aRefPadIdx,
// drc_dbg( 10," chk2 against -> %p ds %d %d\n",
// pad, pad->GetDrillSize().x, refPad->GetDrillSize().x );
drc_dbg( 10," chk1 against -> %p x0 %d x2 %d\n",
drc_dbg( 10, " chk1 against -> %p x0 %d x2 %d\n",
pad, pad->GetDrillSize().x, refPad->GetDrillSize().x );
// No problem if pads which are on copper layers are on different copper layers,
@ -261,7 +261,7 @@ bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( int aRefPadIdx,
continue;
}
drc_dbg(10," chk3 against -> %p x0 %d x2 %d\n", pad, pad->GetDrillSize().x, refPad->GetDrillSize().x );
drc_dbg(10, " chk3 against -> %p x0 %d x2 %d\n", pad, pad->GetDrillSize().x, refPad->GetDrillSize().x );
if( pad->GetDrillSize().x ) // test pad has a hole
{