Add cache for insideArea() and insideCourtyard().
Fixes https://gitlab.com/kicad/code/kicad/issues/7720
This commit is contained in:
parent
451d7c117a
commit
f226373324
|
@ -267,7 +267,13 @@ public:
|
|||
*/
|
||||
BOARD_USE GetBoardUse() const { return m_boardUse; }
|
||||
|
||||
void IncrementTimeStamp() { m_timeStamp++; }
|
||||
void IncrementTimeStamp()
|
||||
{
|
||||
m_timeStamp++;
|
||||
m_InsideAreaCache.clear();
|
||||
m_InsideCourtyardCache.clear();
|
||||
}
|
||||
|
||||
int GetTimeStamp() { return m_timeStamp; }
|
||||
|
||||
/**
|
||||
|
@ -1130,5 +1136,10 @@ public:
|
|||
* @return bit field of legal ops.
|
||||
*/
|
||||
GroupLegalOpsField GroupLegalOps( const PCB_SELECTION& selection ) const;
|
||||
|
||||
public:
|
||||
// While this is a significant encapsulation leak, it's also a significant performance win.
|
||||
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool> m_InsideCourtyardCache;
|
||||
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool> m_InsideAreaCache;
|
||||
};
|
||||
#endif // CLASS_BOARD_H_
|
||||
|
|
|
@ -678,6 +678,8 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
|
|||
m_errorLimits[ ii ] = INT_MAX;
|
||||
}
|
||||
|
||||
m_board->IncrementTimeStamp(); // Invalidate all caches
|
||||
|
||||
for( ZONE* zone : m_board->Zones() )
|
||||
{
|
||||
zone->CacheBoundingBox();
|
||||
|
|
|
@ -151,27 +151,26 @@ static void insideCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||
return;
|
||||
}
|
||||
|
||||
PCB_EXPR_VAR_REF* vref = static_cast<PCB_EXPR_VAR_REF*>( self );
|
||||
BOARD_ITEM* item = vref ? vref->GetObject( aCtx ) : nullptr;
|
||||
EDA_RECT itemBBox;
|
||||
std::shared_ptr<SHAPE> shape;
|
||||
PCB_EXPR_VAR_REF* vref = static_cast<PCB_EXPR_VAR_REF*>( self );
|
||||
BOARD_ITEM* item = vref ? vref->GetObject( aCtx ) : nullptr;
|
||||
|
||||
if( !item )
|
||||
return;
|
||||
|
||||
BOARD* board = item->GetBoard();
|
||||
EDA_RECT itemBBox;
|
||||
std::shared_ptr<SHAPE> shape;
|
||||
|
||||
if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
|
||||
itemBBox = static_cast<ZONE*>( item )->GetCachedBoundingBox();
|
||||
else
|
||||
itemBBox = item->GetBoundingBox();
|
||||
|
||||
auto insideFootprint =
|
||||
auto realInsideFootprint =
|
||||
[&]( FOOTPRINT* footprint ) -> bool
|
||||
{
|
||||
SHAPE_POLY_SET footprintCourtyard;
|
||||
|
||||
if( !footprint )
|
||||
return false;
|
||||
|
||||
if( footprint->IsFlipped() )
|
||||
footprintCourtyard = footprint->GetPolyCourtyardBack();
|
||||
else
|
||||
|
@ -195,6 +194,24 @@ static void insideCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||
return footprintCourtyard.Collide( shape.get() );
|
||||
};
|
||||
|
||||
auto insideFootprint =
|
||||
[&]( FOOTPRINT* footprint ) -> bool
|
||||
{
|
||||
if( !footprint )
|
||||
return false;
|
||||
|
||||
std::pair<BOARD_ITEM*, BOARD_ITEM*> key( footprint, item );
|
||||
auto i = board->m_InsideCourtyardCache.find( key );
|
||||
|
||||
if( i != board->m_InsideCourtyardCache.end() )
|
||||
return i->second;
|
||||
|
||||
bool result = realInsideFootprint( footprint );
|
||||
|
||||
board->m_InsideCourtyardCache[ key ] = result;
|
||||
return result;
|
||||
};
|
||||
|
||||
if( arg->AsString() == "A" )
|
||||
{
|
||||
if( insideFootprint( dynamic_cast<FOOTPRINT*>( context->GetItem( 0 ) ) ) )
|
||||
|
@ -207,7 +224,7 @@ static void insideCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||
}
|
||||
else
|
||||
{
|
||||
for( FOOTPRINT* candidate : item->GetBoard()->Footprints() )
|
||||
for( FOOTPRINT* candidate : board->Footprints() )
|
||||
{
|
||||
if( candidate->GetReference().Matches( arg->AsString() ) )
|
||||
{
|
||||
|
@ -238,25 +255,24 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||
return;
|
||||
}
|
||||
|
||||
PCB_EXPR_VAR_REF* vref = static_cast<PCB_EXPR_VAR_REF*>( self );
|
||||
BOARD_ITEM* item = vref ? vref->GetObject( aCtx ) : nullptr;
|
||||
EDA_RECT itemBBox;
|
||||
std::shared_ptr<SHAPE> shape;
|
||||
PCB_EXPR_VAR_REF* vref = static_cast<PCB_EXPR_VAR_REF*>( self );
|
||||
BOARD_ITEM* item = vref ? vref->GetObject( aCtx ) : nullptr;
|
||||
|
||||
if( !item )
|
||||
return;
|
||||
|
||||
BOARD* board = item->GetBoard();
|
||||
EDA_RECT itemBBox;
|
||||
std::shared_ptr<SHAPE> shape;
|
||||
|
||||
if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
|
||||
itemBBox = static_cast<ZONE*>( item )->GetCachedBoundingBox();
|
||||
else
|
||||
itemBBox = item->GetBoundingBox();
|
||||
|
||||
auto insideZone =
|
||||
auto realInsideZone =
|
||||
[&]( ZONE* zone ) -> bool
|
||||
{
|
||||
if( !zone || zone == item || zone->GetParent() == item )
|
||||
return false;
|
||||
|
||||
if( !zone->GetCachedBoundingBox().Intersects( itemBBox ) )
|
||||
return false;
|
||||
|
||||
|
@ -355,6 +371,24 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||
}
|
||||
};
|
||||
|
||||
auto insideZone =
|
||||
[&]( ZONE* zone ) -> bool
|
||||
{
|
||||
if( !zone || zone == item || zone->GetParent() == item )
|
||||
return false;
|
||||
|
||||
std::pair<BOARD_ITEM*, BOARD_ITEM*> key( zone, item );
|
||||
auto i = board->m_InsideAreaCache.find( key );
|
||||
|
||||
if( i != board->m_InsideAreaCache.end() )
|
||||
return i->second;
|
||||
|
||||
bool result = realInsideZone( zone );
|
||||
|
||||
board->m_InsideCourtyardCache[ key ] = result;
|
||||
return result;
|
||||
};
|
||||
|
||||
if( arg->AsString() == "A" )
|
||||
{
|
||||
if( insideZone( dynamic_cast<ZONE*>( context->GetItem( 0 ) ) ) )
|
||||
|
@ -369,7 +403,7 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||
{
|
||||
KIID target( arg->AsString() );
|
||||
|
||||
for( ZONE* candidate : item->GetBoard()->Zones() )
|
||||
for( ZONE* candidate : board->Zones() )
|
||||
{
|
||||
// Only a single zone can match the UUID; exit once we find a match whether
|
||||
// "inside" or not
|
||||
|
@ -382,7 +416,7 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||
}
|
||||
}
|
||||
|
||||
for( FOOTPRINT* footprint : item->GetBoard()->Footprints() )
|
||||
for( FOOTPRINT* footprint : board->Footprints() )
|
||||
{
|
||||
for( ZONE* candidate : footprint->Zones() )
|
||||
{
|
||||
|
@ -400,7 +434,7 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||
}
|
||||
else // Match on zone name
|
||||
{
|
||||
for( ZONE* candidate : item->GetBoard()->Zones() )
|
||||
for( ZONE* candidate : board->Zones() )
|
||||
{
|
||||
if( candidate->GetZoneName().Matches( arg->AsString() ) )
|
||||
{
|
||||
|
@ -413,7 +447,7 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||
}
|
||||
}
|
||||
|
||||
for( FOOTPRINT* footprint : item->GetBoard()->Footprints() )
|
||||
for( FOOTPRINT* footprint : board->Footprints() )
|
||||
{
|
||||
for( ZONE* candidate : footprint->Zones() )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue