Break a track when placing a via on it.
Fixes: lp:1737349 * https://bugs.launchpad.net/kicad/+bug/1737349
This commit is contained in:
parent
d54a252eaa
commit
a597ebc85e
|
@ -48,6 +48,7 @@
|
|||
#include <hotkeys.h>
|
||||
#include <painter.h>
|
||||
#include <status_popup.h>
|
||||
#include "grid_helper.h"
|
||||
|
||||
#include <preview_items/arc_assistant.h>
|
||||
|
||||
|
@ -1418,20 +1419,36 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
|||
{
|
||||
struct VIA_PLACER : public INTERACTIVE_PLACER_BASE
|
||||
{
|
||||
GRID_HELPER m_gridHelper;
|
||||
|
||||
VIA_PLACER( PCB_EDIT_FRAME* aFrame ) : m_gridHelper( aFrame )
|
||||
{}
|
||||
|
||||
TRACK* findTrack( VIA* aVia )
|
||||
{
|
||||
const LSET lset = aVia->GetLayerSet();
|
||||
|
||||
for( TRACK* track : m_board->Tracks() )
|
||||
{
|
||||
if( !(track->GetLayerSet() & lset ).any() )
|
||||
continue;
|
||||
|
||||
if( TestSegmentHit( aVia->GetPosition(), track->GetStart(), track->GetEnd(),
|
||||
( track->GetWidth() + aVia->GetWidth() ) / 2 ) )
|
||||
return track;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int findStitchedZoneNet( VIA* aVia )
|
||||
{
|
||||
const auto pos = aVia->GetPosition();
|
||||
const auto lset = aVia->GetLayerSet();
|
||||
|
||||
for( auto tv : m_board->Tracks() ) // fixme: move to BOARD class?
|
||||
{
|
||||
if( tv->HitTest( pos ) && ( tv->GetLayerSet() & lset ).any() )
|
||||
return -1;
|
||||
}
|
||||
|
||||
for( auto mod : m_board->Modules() )
|
||||
{
|
||||
for( auto pad : mod->Pads() )
|
||||
for( D_PAD* pad : mod->Pads() )
|
||||
{
|
||||
if( pad->HitTest( pos ) && ( pad->GetLayerSet() & lset ).any() )
|
||||
return -1;
|
||||
|
@ -1470,15 +1487,55 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
|||
return -1;
|
||||
}
|
||||
|
||||
bool PlaceItem( BOARD_ITEM* aItem ) override
|
||||
void SnapItem( BOARD_ITEM *aItem ) override
|
||||
{
|
||||
#if 0
|
||||
// If you place a Via on a track but not on its centerline, the current
|
||||
// connectivity algorithm will require us to put a kink in the track when
|
||||
// we break it (so that each of the two segments ends on the via center).
|
||||
// That's not ideal, and is in fact probably worse than forcing snap in
|
||||
// this situation.
|
||||
if( m_frame->Settings().m_magneticTracks == CAPTURE_CURSOR_IN_TRACK_TOOL
|
||||
|| m_frame->Settings().m_magneticTracks == CAPTURE_ALWAYS )
|
||||
#endif
|
||||
{
|
||||
auto via = static_cast<VIA*>( aItem );
|
||||
int newNet = findStitchedZoneNet( via );
|
||||
wxPoint pos = via->GetPosition();
|
||||
TRACK* track = findTrack( via );
|
||||
|
||||
if( track )
|
||||
{
|
||||
SEG trackSeg( track->GetStart(), track->GetEnd() );
|
||||
VECTOR2I snap = m_gridHelper.AlignToSegment( pos, trackSeg );
|
||||
|
||||
aItem->SetPosition( wxPoint( snap.x, snap.y ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PlaceItem( BOARD_ITEM* aItem, BOARD_COMMIT& aCommit ) override
|
||||
{
|
||||
auto via = static_cast<VIA*>( aItem );
|
||||
int newNet;
|
||||
TRACK* track = findTrack( via );
|
||||
|
||||
if( track )
|
||||
{
|
||||
aCommit.Modify( track );
|
||||
TRACK* newTrack = dynamic_cast<TRACK*>( track->Clone() );
|
||||
track->SetEnd( via->GetPosition() );
|
||||
newTrack->SetStart( via->GetPosition() );
|
||||
aCommit.Add( newTrack );
|
||||
|
||||
newNet = track->GetNetCode();
|
||||
}
|
||||
else
|
||||
newNet = findStitchedZoneNet( via );
|
||||
|
||||
if( newNet > 0 )
|
||||
via->SetNetCode( newNet );
|
||||
|
||||
return false;
|
||||
aCommit.Add( aItem );
|
||||
}
|
||||
|
||||
std::unique_ptr<BOARD_ITEM> CreateItem() override
|
||||
|
@ -1550,7 +1607,7 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
};
|
||||
|
||||
VIA_PLACER placer;
|
||||
VIA_PLACER placer( frame() );
|
||||
|
||||
frame()->SetToolID( ID_PCB_DRAW_VIA_BUTT, wxCURSOR_PENCIL, _( "Add vias" ) );
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ void PCB_TOOL::doInteractiveItemPlacement( INTERACTIVE_PLACER_BASE* aPlacer,
|
|||
newItem->ClearFlags();
|
||||
preview.Remove( newItem.get() );
|
||||
|
||||
aPlacer->PlaceItem( newItem.get() );
|
||||
aPlacer->PlaceItem( newItem.get(), commit );
|
||||
|
||||
if( newItem->Type() == PCB_MODULE_T )
|
||||
{
|
||||
|
@ -139,7 +139,7 @@ void PCB_TOOL::doInteractiveItemPlacement( INTERACTIVE_PLACER_BASE* aPlacer,
|
|||
module->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Remove, &preview, _1 ) );
|
||||
}
|
||||
|
||||
commit.Add( newItem.release() );
|
||||
newItem.release();
|
||||
commit.Push( aCommitMessage );
|
||||
|
||||
controls()->CaptureCursor( false );
|
||||
|
@ -186,6 +186,7 @@ void PCB_TOOL::doInteractiveItemPlacement( INTERACTIVE_PLACER_BASE* aPlacer,
|
|||
{
|
||||
// track the cursor
|
||||
newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||
aPlacer->SnapItem( newItem.get() );
|
||||
|
||||
// Show a preview of the item
|
||||
view()->Update( &preview );
|
||||
|
@ -228,3 +229,14 @@ SELECTION& PCB_TOOL::selection()
|
|||
auto& selection = selTool->GetSelection();
|
||||
return selection;
|
||||
}
|
||||
|
||||
|
||||
void INTERACTIVE_PLACER_BASE::SnapItem( BOARD_ITEM *aItem )
|
||||
{
|
||||
// Base implementation performs no snapping
|
||||
}
|
||||
|
||||
void INTERACTIVE_PLACER_BASE::PlaceItem( BOARD_ITEM *aItem, BOARD_COMMIT& aCommit )
|
||||
{
|
||||
aCommit.Add( aItem );
|
||||
}
|
||||
|
|
|
@ -52,7 +52,8 @@ class SELECTION;
|
|||
struct INTERACTIVE_PLACER_BASE
|
||||
{
|
||||
virtual std::unique_ptr<BOARD_ITEM> CreateItem() = 0;
|
||||
virtual bool PlaceItem( BOARD_ITEM *aItem ) { return false; }
|
||||
virtual void SnapItem( BOARD_ITEM *aItem );
|
||||
virtual void PlaceItem( BOARD_ITEM *aItem, BOARD_COMMIT& aCommit );
|
||||
|
||||
PCB_EDIT_FRAME* m_frame;
|
||||
BOARD* m_board;
|
||||
|
|
Loading…
Reference in New Issue