Share more of the courtyard collision highlighting code.

This commit is contained in:
Jeff Young 2022-10-14 10:42:07 +01:00
parent 11dc5424cb
commit de5980b92e
4 changed files with 97 additions and 108 deletions

View File

@ -73,8 +73,8 @@ void DRC_INTERACTIVE_COURTYARD_CLEARANCE::testCourtyardClearances()
if( frontA.Collide( &frontB, clearance, &actual, &pos ) ) if( frontA.Collide( &frontB, clearance, &actual, &pos ) )
{ {
m_ItemsInConflict.insert( fpA ); m_itemsInConflict.insert( fpA );
m_ItemsInConflict.insert( fpB ); m_itemsInConflict.insert( fpB );
} }
} }
@ -88,8 +88,8 @@ void DRC_INTERACTIVE_COURTYARD_CLEARANCE::testCourtyardClearances()
if( backA.Collide( &backB, clearance, &actual, &pos ) ) if( backA.Collide( &backB, clearance, &actual, &pos ) )
{ {
m_ItemsInConflict.insert( fpA ); m_itemsInConflict.insert( fpA );
m_ItemsInConflict.insert( fpB ); m_itemsInConflict.insert( fpB );
} }
} }
@ -122,8 +122,8 @@ void DRC_INTERACTIVE_COURTYARD_CLEARANCE::testCourtyardClearances()
{ {
if( testPadAgainstCourtyards( padB, fpA ) ) if( testPadAgainstCourtyards( padB, fpA ) )
{ {
m_ItemsInConflict.insert( fpA ); m_itemsInConflict.insert( fpA );
m_ItemsInConflict.insert( fpB ); m_itemsInConflict.insert( fpB );
skipNextCmp = true; skipNextCmp = true;
break; break;
} }
@ -140,8 +140,8 @@ void DRC_INTERACTIVE_COURTYARD_CLEARANCE::testCourtyardClearances()
{ {
if( testPadAgainstCourtyards( padA, fpB ) ) if( testPadAgainstCourtyards( padA, fpB ) )
{ {
m_ItemsInConflict.insert( fpA ); m_itemsInConflict.insert( fpA );
m_ItemsInConflict.insert( fpB ); m_itemsInConflict.insert( fpB );
break; break;
} }
} }
@ -167,8 +167,8 @@ void DRC_INTERACTIVE_COURTYARD_CLEARANCE::testCourtyardClearances()
{ {
if( zone->Outline()->Collide( &frontCourtyard.Outline( 0 ) ) ) if( zone->Outline()->Collide( &frontCourtyard.Outline( 0 ) ) )
{ {
m_ItemsInConflict.insert( fp ); m_itemsInConflict.insert( fp );
m_ItemsInConflict.insert( zone ); m_itemsInConflict.insert( zone );
break; break;
} }
} }
@ -182,8 +182,8 @@ void DRC_INTERACTIVE_COURTYARD_CLEARANCE::testCourtyardClearances()
{ {
if( zone->Outline()->Collide( &backCourtyard.Outline( 0 ) ) ) if( zone->Outline()->Collide( &backCourtyard.Outline( 0 ) ) )
{ {
m_ItemsInConflict.insert( fp ); m_itemsInConflict.insert( fp );
m_ItemsInConflict.insert( zone ); m_itemsInConflict.insert( zone );
break; break;
} }
} }
@ -208,7 +208,7 @@ void DRC_INTERACTIVE_COURTYARD_CLEARANCE::Init( BOARD* aBoard )
bool DRC_INTERACTIVE_COURTYARD_CLEARANCE::Run() bool DRC_INTERACTIVE_COURTYARD_CLEARANCE::Run()
{ {
m_ItemsInConflict.clear(); m_itemsInConflict.clear();
m_largestCourtyardClearance = 0; m_largestCourtyardClearance = 0;
DRC_CONSTRAINT constraint; DRC_CONSTRAINT constraint;
@ -220,3 +220,46 @@ bool DRC_INTERACTIVE_COURTYARD_CLEARANCE::Run()
return true; return true;
} }
void DRC_INTERACTIVE_COURTYARD_CLEARANCE::UpdateConflicts( KIGFX::VIEW* aView,
bool aHighlightMoved )
{
// Ensure the "old" conflicts are cleared
for( BOARD_ITEM* item: m_lastItemsInConflict )
{
item->ClearFlags(COURTYARD_CONFLICT );
aView->Update( item );
aView->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
}
m_lastItemsInConflict.clear();
for( BOARD_ITEM* item: m_itemsInConflict )
{
if( aHighlightMoved || !alg::contains( m_FpInMove, item ) )
{
if( !item->HasFlag( COURTYARD_CONFLICT ) )
{
item->SetFlags( COURTYARD_CONFLICT );
aView->Update( item );
aView->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
}
m_lastItemsInConflict.push_back( item );
}
}
}
void DRC_INTERACTIVE_COURTYARD_CLEARANCE::ClearConflicts( KIGFX::VIEW* aView )
{
for( BOARD_ITEM* item: m_lastItemsInConflict )
{
item->ClearFlags( COURTYARD_CONFLICT );
aView->Update( item );
aView->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
}
}

View File

@ -32,11 +32,12 @@
class DRC_INTERACTIVE_COURTYARD_CLEARANCE : public DRC_TEST_PROVIDER_CLEARANCE_BASE class DRC_INTERACTIVE_COURTYARD_CLEARANCE : public DRC_TEST_PROVIDER_CLEARANCE_BASE
{ {
public: public:
DRC_INTERACTIVE_COURTYARD_CLEARANCE() : DRC_INTERACTIVE_COURTYARD_CLEARANCE( const std::shared_ptr<DRC_ENGINE>& aDRCEngine ) :
DRC_TEST_PROVIDER_CLEARANCE_BASE(), DRC_TEST_PROVIDER_CLEARANCE_BASE(),
m_largestCourtyardClearance( 0 ) m_largestCourtyardClearance( 0 )
{ {
m_isRuleDriven = false; m_isRuleDriven = false;
SetDRCEngine( aDRCEngine.get() );
} }
virtual ~DRC_INTERACTIVE_COURTYARD_CLEARANCE () virtual ~DRC_INTERACTIVE_COURTYARD_CLEARANCE ()
@ -57,15 +58,20 @@ public:
return wxT( "Tests footprints' courtyard collisions" ); return wxT( "Tests footprints' courtyard collisions" );
} }
void UpdateConflicts( KIGFX::VIEW* aView, bool aHighlightMoved );
void ClearConflicts( KIGFX::VIEW* aView );
public: public:
std::vector<FOOTPRINT*> m_FpInMove; // The list of moved footprints std::vector<FOOTPRINT*> m_FpInMove; // The list of moved footprints
std::set<BOARD_ITEM*> m_ItemsInConflict; // The list of items in conflict
private: private:
void testCourtyardClearances(); void testCourtyardClearances();
private: private:
int m_largestCourtyardClearance; int m_largestCourtyardClearance;
std::set<BOARD_ITEM*> m_itemsInConflict; // The list of items in conflict
std::vector<BOARD_ITEM*> m_lastItemsInConflict; // The list of items last highlighted
}; };
#endif // DRC_INTERACTIVE_COURTYARD_CLEARANCE_H #endif // DRC_INTERACTIVE_COURTYARD_CLEARANCE_H

View File

@ -1962,16 +1962,17 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
PNS::ITEM_SET itemsToDrag; PNS::ITEM_SET itemsToDrag;
FOOTPRINT* footprint = nullptr; FOOTPRINT* footprint = nullptr;
// Courtyard conflicts will be tested only if the LAYER_CONFLICTS_SHADOW gal layer is visible
bool showCourtyardConflicts = frame()->GetBoard()->IsElementVisible( LAYER_CONFLICTS_SHADOW );
std::shared_ptr<DRC_ENGINE> drcEngine = m_toolMgr->GetTool<DRC_TOOL>()->GetDRCEngine();
DRC_INTERACTIVE_COURTYARD_CLEARANCE courtyardClearanceDRC( drcEngine );
std::shared_ptr<CONNECTIVITY_DATA> connectivityData = board()->GetConnectivity(); std::shared_ptr<CONNECTIVITY_DATA> connectivityData = board()->GetConnectivity();
std::vector<BOARD_ITEM*> dynamicItems; std::vector<BOARD_ITEM*> dynamicItems;
std::unique_ptr<CONNECTIVITY_DATA> dynamicData = nullptr; std::unique_ptr<CONNECTIVITY_DATA> dynamicData = nullptr;
VECTOR2I lastOffset; VECTOR2I lastOffset;
// Courtyard conflicts will be tested only if the LAYER_CONFLICTS_SHADOW gal layer is visible
bool showCourtyardConflicts = frame()->GetBoard()->IsElementVisible( LAYER_CONFLICTS_SHADOW );
DRC_INTERACTIVE_COURTYARD_CLEARANCE courtyardClearanceDRC;
std::vector<BOARD_ITEM*> lastItemsInConflict;
if( item->Type() == PCB_FOOTPRINT_T ) if( item->Type() == PCB_FOOTPRINT_T )
{ {
footprint = static_cast<FOOTPRINT*>( item ); footprint = static_cast<FOOTPRINT*>( item );
@ -1990,9 +1991,11 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
} }
} }
if( showCourtyardConflicts )
{
courtyardClearanceDRC.Init( board() ); courtyardClearanceDRC.Init( board() );
courtyardClearanceDRC.SetDRCEngine( m_toolMgr->GetTool<DRC_TOOL>()->GetDRCEngine().get() );
courtyardClearanceDRC.m_FpInMove.push_back( footprint ); courtyardClearanceDRC.m_FpInMove.push_back( footprint );
}
dynamicData = std::make_unique<CONNECTIVITY_DATA>( dynamicItems, true ); dynamicData = std::make_unique<CONNECTIVITY_DATA>( dynamicItems, true );
connectivityData->BlockRatsnestItems( dynamicItems ); connectivityData->BlockRatsnestItems( dynamicItems );
@ -2166,32 +2169,8 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
{ {
footprint->Move( offset ); footprint->Move( offset );
courtyardClearanceDRC.Run(); courtyardClearanceDRC.Run();
courtyardClearanceDRC.UpdateConflicts( getView(), false );
footprint->Move( -offset ); footprint->Move( -offset );
// Ensure the "old" conflicts are cleared
for( BOARD_ITEM* conflict: lastItemsInConflict )
{
conflict->ClearFlags( COURTYARD_CONFLICT );
getView()->Update( conflict );
getView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
}
lastItemsInConflict.clear();
for( BOARD_ITEM* conflict: courtyardClearanceDRC.m_ItemsInConflict )
{
if( conflict != footprint )
{
if( !conflict->HasFlag( COURTYARD_CONFLICT ) )
{
conflict->SetFlags( COURTYARD_CONFLICT );
getView()->Update( conflict );
getView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
}
lastItemsInConflict.push_back( conflict );
}
}
} }
// Update ratsnest // Update ratsnest
@ -2250,11 +2229,7 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
} }
// Clear temporary COURTYARD_CONFLICT flag and ensure the conflict shadow is cleared // Clear temporary COURTYARD_CONFLICT flag and ensure the conflict shadow is cleared
for( BOARD_ITEM* conflict: lastItemsInConflict ) courtyardClearanceDRC.ClearConflicts( getView() );
{
conflict->ClearFlags( COURTYARD_CONFLICT );
getView()->Update( conflict );
}
if( m_router->RoutingInProgress() ) if( m_router->RoutingInProgress() )
m_router->StopRouting(); m_router->StopRouting();

View File

@ -301,16 +301,15 @@ VECTOR2I EDIT_TOOL::getSafeMovement( const VECTOR2I& aMovement, const BOX2I& aSo
// Constrain moving bounding box to coordinates limits // Constrain moving bounding box to coordinates limits
VECTOR2D tryMovement( aMovement ); VECTOR2D tryMovement( aMovement );
VECTOR2D bBoxOrigin( aSourceBBox.GetPosition() + aBBoxOffset );
VECTOR2D clampedBBoxOrigin = GetClampedCoords( bBoxOrigin + tryMovement, COORDS_PADDING );
VECTOR2D clampedBBoxOrigin = GetClampedCoords( tryMovement = clampedBBoxOrigin - bBoxOrigin;
VECTOR2D( aSourceBBox.GetPosition() ) + aBBoxOffset + tryMovement, COORDS_PADDING );
tryMovement = clampedBBoxOrigin - aBBoxOffset - aSourceBBox.GetPosition(); VECTOR2D bBoxEnd( aSourceBBox.GetEnd() + aBBoxOffset );
VECTOR2D clampedBBoxEnd = GetClampedCoords( bBoxEnd + tryMovement, COORDS_PADDING );
VECTOR2D clampedBBoxEnd = GetClampedCoords( tryMovement = clampedBBoxEnd - bBoxEnd;
VECTOR2D( aSourceBBox.GetEnd() ) + aBBoxOffset + tryMovement, COORDS_PADDING );
tryMovement = clampedBBoxEnd - aBBoxOffset - aSourceBBox.GetEnd();
return GetClampedCoords<double, int>( tryMovement ); return GetClampedCoords<double, int>( tryMovement );
} }
@ -387,7 +386,6 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference )
std::vector<BOARD_ITEM*> sel_items; // All the items operated on by the move below std::vector<BOARD_ITEM*> sel_items; // All the items operated on by the move below
std::vector<BOARD_ITEM*> orig_items; // All the original items in the selection std::vector<BOARD_ITEM*> orig_items; // All the original items in the selection
std::vector<BOARD_ITEM*> lastItemsInConflict; // last footprints with courtyard overlapping
for( EDA_ITEM* item : selection ) for( EDA_ITEM* item : selection )
{ {
@ -432,16 +430,14 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference )
bool showCourtyardConflicts = !m_isFootprintEditor bool showCourtyardConflicts = !m_isFootprintEditor
&& board->IsElementVisible( LAYER_CONFLICTS_SHADOW ); && board->IsElementVisible( LAYER_CONFLICTS_SHADOW );
displayConstraintsMessage( hv45Mode );
// Used to test courtyard overlaps // Used to test courtyard overlaps
DRC_INTERACTIVE_COURTYARD_CLEARANCE drc_on_move; std::shared_ptr<DRC_ENGINE> drcEngine = m_toolMgr->GetTool<DRC_TOOL>()->GetDRCEngine();
DRC_INTERACTIVE_COURTYARD_CLEARANCE drc_on_move( drcEngine );
if( showCourtyardConflicts ) if( showCourtyardConflicts )
{
drc_on_move.Init( board ); drc_on_move.Init( board );
drc_on_move.SetDRCEngine( m_toolMgr->GetTool<DRC_TOOL>()->GetDRCEngine().get() );
} displayConstraintsMessage( hv45Mode );
// Prime the pump // Prime the pump
m_toolMgr->RunAction( ACTIONS::refreshPreview ); m_toolMgr->RunAction( ACTIONS::refreshPreview );
@ -545,34 +541,7 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference )
if( showCourtyardConflicts && drc_on_move.m_FpInMove.size() ) if( showCourtyardConflicts && drc_on_move.m_FpInMove.size() )
{ {
drc_on_move.Run(); drc_on_move.Run();
drc_on_move.UpdateConflicts( m_toolMgr->GetView(), true );
bool need_redraw = false; // will be set to true if a COURTYARD_CONFLICT
// has changed
// Ensure the "old" conflicts are cleared
for( BOARD_ITEM* item: lastItemsInConflict )
{
item->ClearFlags( COURTYARD_CONFLICT );
m_toolMgr->GetView()->Update( item );
need_redraw = true;
}
lastItemsInConflict.clear();
for( BOARD_ITEM* item: drc_on_move.m_ItemsInConflict )
{
if( !item->HasFlag( COURTYARD_CONFLICT ) )
{
item->SetFlags( COURTYARD_CONFLICT );
m_toolMgr->GetView()->Update( item );
need_redraw = true;
}
lastItemsInConflict.push_back( item );
}
if( need_redraw )
m_toolMgr->GetView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
} }
m_toolMgr->PostEvent( EVENTS::SelectedItemsMoved ); m_toolMgr->PostEvent( EVENTS::SelectedItemsMoved );
@ -768,11 +737,7 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference )
} while( ( evt = Wait() ) ); // Assignment (instead of equality test) is intentional } while( ( evt = Wait() ) ); // Assignment (instead of equality test) is intentional
// Clear temporary COURTYARD_CONFLICT flag and ensure the conflict shadow is cleared // Clear temporary COURTYARD_CONFLICT flag and ensure the conflict shadow is cleared
for( BOARD_ITEM* item: lastItemsInConflict ) drc_on_move.ClearConflicts( m_toolMgr->GetView() );
{
m_toolMgr->GetView()->Update( item );
item->ClearFlags( COURTYARD_CONFLICT );
}
controls->ForceCursorPosition( false ); controls->ForceCursorPosition( false );
controls->ShowCursor( false ); controls->ShowCursor( false );