pcbnew: Disallow new via where DRC is violated
Prior to placing the via, we check if the resulting via will pass too close to different nets on different layers. Fixes: lp:1718827 * https://bugs.launchpad.net/kicad/+bug/1718827
This commit is contained in:
parent
86263d6bb3
commit
4247e32cd6
|
@ -1504,20 +1504,86 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
|||
TRACK* findTrack( VIA* aVia )
|
||||
{
|
||||
const LSET lset = aVia->GetLayerSet();
|
||||
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> items;
|
||||
BOX2I bbox = aVia->GetBoundingBox();
|
||||
auto view = m_frame->GetGalCanvas()->GetView();
|
||||
|
||||
for( TRACK* track : m_board->Tracks() )
|
||||
view->Query( bbox, items );
|
||||
|
||||
for( auto it : items )
|
||||
{
|
||||
if( !(track->GetLayerSet() & lset ).any() )
|
||||
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it.first );
|
||||
|
||||
if( !(item->GetLayerSet() & lset ).any() )
|
||||
continue;
|
||||
|
||||
if( TestSegmentHit( aVia->GetPosition(), track->GetStart(), track->GetEnd(),
|
||||
( track->GetWidth() + aVia->GetWidth() ) / 2 ) )
|
||||
return track;
|
||||
if( auto track = dyn_cast<TRACK*>( item ) )
|
||||
{
|
||||
if( TestSegmentHit( aVia->GetPosition(), track->GetStart(), track->GetEnd(),
|
||||
( track->GetWidth() + aVia->GetWidth() ) / 2 ) )
|
||||
return track;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool hasDRCViolation( VIA* aVia )
|
||||
{
|
||||
const LSET lset = aVia->GetLayerSet();
|
||||
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> items;
|
||||
int net = 0;
|
||||
int clearance = 0;
|
||||
BOX2I bbox = aVia->GetBoundingBox();
|
||||
auto view = m_frame->GetGalCanvas()->GetView();
|
||||
|
||||
view->Query( bbox, items );
|
||||
|
||||
for( auto it : items )
|
||||
{
|
||||
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it.first );
|
||||
|
||||
if( !(item->GetLayerSet() & lset ).any() )
|
||||
continue;
|
||||
|
||||
if( auto track = dyn_cast<TRACK*>( item ) )
|
||||
{
|
||||
int max_clearance = std::max( clearance, track->GetClearance() );
|
||||
|
||||
if( TestSegmentHit( aVia->GetPosition(), track->GetStart(), track->GetEnd(),
|
||||
( track->GetWidth() + aVia->GetWidth() ) / 2 + max_clearance ) )
|
||||
{
|
||||
if( net && track->GetNetCode() != net )
|
||||
return true;
|
||||
|
||||
net = track->GetNetCode();
|
||||
clearance = track->GetClearance();
|
||||
}
|
||||
}
|
||||
|
||||
if( auto mod = dyn_cast<MODULE*>( item ) )
|
||||
{
|
||||
for( auto pad : mod->Pads() )
|
||||
{
|
||||
int max_clearance = std::max( clearance, pad->GetClearance() );
|
||||
|
||||
if( pad->HitTest( aVia->GetBoundingBox(), false, max_clearance ) )
|
||||
{
|
||||
if( net && pad->GetNetCode() != net )
|
||||
return true;
|
||||
|
||||
net = pad->GetNetCode();
|
||||
clearance = pad->GetClearance();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int findStitchedZoneNet( VIA* aVia )
|
||||
{
|
||||
const auto pos = aVia->GetPosition();
|
||||
|
@ -1572,8 +1638,6 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
|||
// That's not ideal, and is in fact probably worse than forcing snap in
|
||||
// this situation.
|
||||
|
||||
// bool do_snap = ( m_frame->Settings().m_magneticTracks == CAPTURE_CURSOR_IN_TRACK_TOOL
|
||||
// || m_frame->Settings().m_magneticTracks == CAPTURE_ALWAYS );
|
||||
m_gridHelper.SetSnap( !( m_modifiers & MD_SHIFT ) );
|
||||
auto via = static_cast<VIA*>( aItem );
|
||||
wxPoint pos = via->GetPosition();
|
||||
|
@ -1588,12 +1652,15 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
}
|
||||
|
||||
void PlaceItem( BOARD_ITEM* aItem, BOARD_COMMIT& aCommit ) override
|
||||
bool PlaceItem( BOARD_ITEM* aItem, BOARD_COMMIT& aCommit ) override
|
||||
{
|
||||
auto via = static_cast<VIA*>( aItem );
|
||||
int newNet;
|
||||
TRACK* track = findTrack( via );
|
||||
|
||||
if( hasDRCViolation( via ) )
|
||||
return false;
|
||||
|
||||
if( track )
|
||||
{
|
||||
aCommit.Modify( track );
|
||||
|
@ -1611,6 +1678,7 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
|||
via->SetNetCode( newNet );
|
||||
|
||||
aCommit.Add( aItem );
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<BOARD_ITEM> CreateItem() override
|
||||
|
|
|
@ -109,7 +109,7 @@ int MODULE_EDITOR_TOOLS::PlacePad( const TOOL_EVENT& aEvent )
|
|||
return std::unique_ptr<BOARD_ITEM>( pad );
|
||||
}
|
||||
|
||||
void PlaceItem( BOARD_ITEM *aItem, BOARD_COMMIT& aCommit ) override
|
||||
bool PlaceItem( BOARD_ITEM *aItem, BOARD_COMMIT& aCommit ) override
|
||||
{
|
||||
D_PAD* pad = dynamic_cast<D_PAD*>( aItem );
|
||||
|
||||
|
@ -118,7 +118,10 @@ int MODULE_EDITOR_TOOLS::PlacePad( const TOOL_EVENT& aEvent )
|
|||
m_frame->Export_Pad_Settings( pad );
|
||||
pad->SetLocalCoord();
|
||||
aCommit.Add( aItem );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -132,10 +132,16 @@ void PCB_TOOL::doInteractiveItemPlacement( INTERACTIVE_PLACER_BASE* aPlacer,
|
|||
}
|
||||
else
|
||||
{
|
||||
auto oldFlags = newItem->GetFlags();
|
||||
newItem->ClearFlags();
|
||||
preview.Remove( newItem.get() );
|
||||
|
||||
aPlacer->PlaceItem( newItem.get(), commit );
|
||||
if( !aPlacer->PlaceItem( newItem.get(), commit ) )
|
||||
{
|
||||
newItem->SetFlags( oldFlags );
|
||||
continue;
|
||||
}
|
||||
|
||||
preview.Remove( newItem.get() );
|
||||
|
||||
if( newItem->Type() == PCB_MODULE_T )
|
||||
{
|
||||
|
@ -262,7 +268,8 @@ void INTERACTIVE_PLACER_BASE::SnapItem( BOARD_ITEM *aItem )
|
|||
// Base implementation performs no snapping
|
||||
}
|
||||
|
||||
void INTERACTIVE_PLACER_BASE::PlaceItem( BOARD_ITEM *aItem, BOARD_COMMIT& aCommit )
|
||||
bool INTERACTIVE_PLACER_BASE::PlaceItem( BOARD_ITEM *aItem, BOARD_COMMIT& aCommit )
|
||||
{
|
||||
aCommit.Add( aItem );
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ struct INTERACTIVE_PLACER_BASE
|
|||
{
|
||||
virtual std::unique_ptr<BOARD_ITEM> CreateItem() = 0;
|
||||
virtual void SnapItem( BOARD_ITEM *aItem );
|
||||
virtual void PlaceItem( BOARD_ITEM *aItem, BOARD_COMMIT& aCommit );
|
||||
virtual bool PlaceItem( BOARD_ITEM *aItem, BOARD_COMMIT& aCommit );
|
||||
|
||||
PCB_EDIT_FRAME* m_frame;
|
||||
BOARD* m_board;
|
||||
|
|
Loading…
Reference in New Issue