Support arcs in Break Track.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16712
This commit is contained in:
Alex 2024-01-24 05:47:36 +03:00
parent a46d409ec6
commit ed00cb3304
5 changed files with 61 additions and 11 deletions

View File

@ -2,7 +2,7 @@
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2017 CERN
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors.
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
@ -1292,6 +1292,38 @@ bool LINE_PLACER::SplitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I
}
bool LINE_PLACER::SplitAdjacentArcs( NODE* aNode, ITEM* aArc, const VECTOR2I& aP )
{
if( !aArc )
return false;
if( !aArc->OfKind( ITEM::ARC_T ) )
return false;
const JOINT* jt = aNode->FindJoint( aP, aArc );
if( jt && jt->LinkCount() >= 1 )
return false;
ARC* a_old = static_cast<ARC*>( aArc );
const SHAPE_ARC& o_arc = a_old->Arc();
std::unique_ptr<ARC> a_new[2] = { Clone( *a_old ), Clone( *a_old ) };
a_new[0]->Arc().ConstructFromStartEndCenter( o_arc.GetP0(), aP, o_arc.GetCenter(),
o_arc.IsClockwise(), o_arc.GetWidth() );
a_new[1]->Arc().ConstructFromStartEndCenter( aP, o_arc.GetP1(), o_arc.GetCenter(),
o_arc.IsClockwise(), o_arc.GetWidth() );
aNode->Remove( a_old );
aNode->Add( std::move( a_new[0] ), true );
aNode->Add( std::move( a_new[1] ), true );
return true;
}
bool LINE_PLACER::SetLayer( int aLayer )
{
if( m_idle )

View File

@ -2,7 +2,7 @@
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2017 CERN
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
@ -206,11 +206,17 @@ public:
void GetModifiedNets( std::vector<NET_HANDLE>& aNets ) const override;
/**
* Check if point \a aP lies on segment \a aSeg. If so, splits the segment in two, forming a
* Snaps the point \a aP to segment \a aSeg. Splits the segment in two, forming a
* joint at \a aP and stores updated topology in node \a aNode.
*/
bool SplitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I& aP );
/**
* Snaps the point \a aP to arc \a aArc. Splits the arc in two, forming a
* joint at \a aP and stores updated topology in node \a aNode.
*/
bool SplitAdjacentArcs( NODE* aNode, ITEM* aArc, const VECTOR2I& aP );
private:
/**
* Re-route the current track to point aP. Returns true, when routing has completed

View File

@ -1039,13 +1039,20 @@ void ROUTER::SetInterface( ROUTER_IFACE *aIface )
}
void ROUTER::BreakSegment( ITEM *aItem, const VECTOR2I& aP )
void ROUTER::BreakSegmentOrArc( ITEM *aItem, const VECTOR2I& aP )
{
NODE *node = m_world->Branch();
LINE_PLACER placer( this );
if( placer.SplitAdjacentSegments( node, aItem, aP ) )
bool ret = false;
if( aItem->OfKind( ITEM::SEGMENT_T ) )
ret = placer.SplitAdjacentSegments( node, aItem, aP );
else if( aItem->OfKind( ITEM::ARC_T ) )
ret = placer.SplitAdjacentArcs( node, aItem, aP );
if( ret )
{
CommitRouting( node );
}

View File

@ -150,7 +150,7 @@ public:
bool Finish();
bool ContinueFromEnd( ITEM** aNewStartItem );
bool FixRoute( const VECTOR2I& aP, ITEM* aItem, bool aForceFinish, bool aForceCommit );
void BreakSegment( ITEM *aItem, const VECTOR2I& aP );
void BreakSegmentOrArc( ITEM *aItem, const VECTOR2I& aP );
std::optional<VECTOR2I> UndoLastSegment();
void CommitRouting();

View File

@ -1563,8 +1563,11 @@ bool ROUTER_TOOL::RoutingInProgress()
void ROUTER_TOOL::breakTrack()
{
if( m_startItem && m_startItem->OfKind( PNS::ITEM::SEGMENT_T ) )
m_router->BreakSegment( m_startItem, m_startSnapPoint );
if( !m_startItem )
return;
if( m_startItem->OfKind( PNS::ITEM::SEGMENT_T | PNS::ITEM::ARC_T ) )
m_router->BreakSegmentOrArc( m_startItem, m_startSnapPoint );
}
@ -2501,7 +2504,7 @@ int ROUTER_TOOL::InlineBreakTrack( const TOOL_EVENT& aEvent )
const BOARD_CONNECTED_ITEM* item =
static_cast<const BOARD_CONNECTED_ITEM*>( selection.Front() );
if( item->Type() != PCB_TRACE_T )
if( item->Type() != PCB_TRACE_T && item->Type() != PCB_ARC_T )
return 0;
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear );
@ -2516,6 +2519,8 @@ int ROUTER_TOOL::InlineBreakTrack( const TOOL_EVENT& aEvent )
m_gridHelper->SetUseGrid( gal->GetGridSnapping() && !aEvent.DisableGridSnapping() );
m_gridHelper->SetSnap( !aEvent.Modifier( MD_SHIFT ) );
controls()->ForceCursorPosition( false );
if( toolManager->IsContextMenuActive() )
{
// If we're here from a context menu then we need to get the position of the