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 <hotkeys.h>
|
||||||
#include <painter.h>
|
#include <painter.h>
|
||||||
#include <status_popup.h>
|
#include <status_popup.h>
|
||||||
|
#include "grid_helper.h"
|
||||||
|
|
||||||
#include <preview_items/arc_assistant.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
|
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 )
|
int findStitchedZoneNet( VIA* aVia )
|
||||||
{
|
{
|
||||||
const auto pos = aVia->GetPosition();
|
const auto pos = aVia->GetPosition();
|
||||||
const auto lset = aVia->GetLayerSet();
|
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 mod : m_board->Modules() )
|
||||||
{
|
{
|
||||||
for( auto pad : mod->Pads() )
|
for( D_PAD* pad : mod->Pads() )
|
||||||
{
|
{
|
||||||
if( pad->HitTest( pos ) && ( pad->GetLayerSet() & lset ).any() )
|
if( pad->HitTest( pos ) && ( pad->GetLayerSet() & lset ).any() )
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1470,15 +1487,55 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
||||||
return -1;
|
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 );
|
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 )
|
if( newNet > 0 )
|
||||||
via->SetNetCode( newNet );
|
via->SetNetCode( newNet );
|
||||||
|
|
||||||
return false;
|
aCommit.Add( aItem );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<BOARD_ITEM> CreateItem() override
|
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" ) );
|
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();
|
newItem->ClearFlags();
|
||||||
preview.Remove( newItem.get() );
|
preview.Remove( newItem.get() );
|
||||||
|
|
||||||
aPlacer->PlaceItem( newItem.get() );
|
aPlacer->PlaceItem( newItem.get(), commit );
|
||||||
|
|
||||||
if( newItem->Type() == PCB_MODULE_T )
|
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 ) );
|
module->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Remove, &preview, _1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
commit.Add( newItem.release() );
|
newItem.release();
|
||||||
commit.Push( aCommitMessage );
|
commit.Push( aCommitMessage );
|
||||||
|
|
||||||
controls()->CaptureCursor( false );
|
controls()->CaptureCursor( false );
|
||||||
|
@ -186,6 +186,7 @@ void PCB_TOOL::doInteractiveItemPlacement( INTERACTIVE_PLACER_BASE* aPlacer,
|
||||||
{
|
{
|
||||||
// track the cursor
|
// track the cursor
|
||||||
newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
|
newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||||
|
aPlacer->SnapItem( newItem.get() );
|
||||||
|
|
||||||
// Show a preview of the item
|
// Show a preview of the item
|
||||||
view()->Update( &preview );
|
view()->Update( &preview );
|
||||||
|
@ -228,3 +229,14 @@ SELECTION& PCB_TOOL::selection()
|
||||||
auto& selection = selTool->GetSelection();
|
auto& selection = selTool->GetSelection();
|
||||||
return selection;
|
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
|
struct INTERACTIVE_PLACER_BASE
|
||||||
{
|
{
|
||||||
virtual std::unique_ptr<BOARD_ITEM> CreateItem() = 0;
|
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;
|
PCB_EDIT_FRAME* m_frame;
|
||||||
BOARD* m_board;
|
BOARD* m_board;
|
||||||
|
|
Loading…
Reference in New Issue