PNS: Pick up segments directly between pads when dragging components

Fixes https://gitlab.com/kicad/code/kicad/-/issues/7601
This commit is contained in:
Jon Evans 2021-07-03 19:50:04 -04:00
parent ab38dfd7ae
commit 91ea4a0569
3 changed files with 65 additions and 5 deletions

View File

@ -111,6 +111,9 @@ public:
OPT_BOX2I ChangedArea( const ARC* aOther ) const;
SHAPE_ARC& Arc() { return m_arc; }
const SHAPE_ARC& CArc() const { return m_arc; }
private:
SHAPE_ARC m_arc;
};

View File

@ -20,6 +20,7 @@
#include <memory>
#include "pns_arc.h"
#include "pns_line.h"
#include "pns_solid.h"
#include "pns_router.h"
@ -52,13 +53,30 @@ bool COMPONENT_DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
std::unordered_set<LINKED_ITEM*> seenItems;
auto addLinked =
[&]( SOLID* aSolid, LINKED_ITEM* aItem, VECTOR2I aOffset = {} )
[&]( SOLID* aSolid, JOINT* aJoint, LINKED_ITEM* aItem, VECTOR2I aOffset = {} )
{
if( seenItems.count( aItem ) )
return;
seenItems.insert( aItem );
// Segments that go directly between two linked pads are special-cased
VECTOR2I otherEnd = ( aJoint->Pos() == aItem->Anchor( 0 ) ) ?
aItem->Anchor( 1 ) : aItem->Anchor( 0 );
JOINT* otherJoint = m_world->FindJoint( otherEnd, aItem->Layer(), aItem->Net() );
if( otherJoint && otherJoint->LinkCount( ITEM::SOLID_T ) )
{
for( const ITEM_SET::ENTRY& otherItem : otherJoint->LinkList() )
{
if( aPrimitives.Contains( otherItem.item ) )
{
m_fixedItems.insert( aItem );
return;
}
}
}
int segIndex;
DRAGGED_CONNECTION cn;
@ -85,7 +103,7 @@ bool COMPONENT_DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
for( auto link : jt->LinkList() )
{
if( link.item->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
addLinked( solid, static_cast<LINKED_ITEM*>( link.item ) );
addLinked( solid, jt, static_cast<LINKED_ITEM*>( link.item ) );
}
std::vector<JOINT*> extraJoints;
@ -100,7 +118,7 @@ bool COMPONENT_DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
LINKED_ITEM* li = static_cast<LINKED_ITEM*>( extraJoint->LinkList()[0].item );
if( li->Collide( solid, nullptr, m_world ) )
addLinked( solid, li, extraJoint->Pos() - solid->Pos() );
addLinked( solid, extraJoint, li, extraJoint->Pos() - solid->Pos() );
}
}
}
@ -138,6 +156,44 @@ bool COMPONENT_DRAGGER::Drag( const VECTOR2I& aP )
}
}
for( ITEM* item : m_fixedItems )
{
m_currentNode->Remove( item );
switch( item->Kind() )
{
case ITEM::SEGMENT_T:
{
SEGMENT* s = static_cast<SEGMENT*>( item );
std::unique_ptr<SEGMENT> s_new( s->Clone() );
SEG orig = s->Seg();
s_new->SetEnds( aP - m_p0 + orig.A, aP - m_p0 + orig.B );
m_draggedItems.Add( s_new.get() );
m_currentNode->Add( std::move( s_new ) );
break;
}
case ITEM::ARC_T:
{
ARC* a = static_cast<ARC*>( item );
std::unique_ptr<ARC> a_new( a->Clone() );
SHAPE_ARC& arc = a_new->Arc();
arc.Move( aP - m_p0 );
m_draggedItems.Add( a_new.get() );
m_currentNode->Add( std::move( a_new ) );
break;
}
default:
wxFAIL_MSG( "Unexpected item type in COMPONENT_DRAGGER::m_fixedItems" );
}
}
for( auto& cn : m_conns )
{
auto l_new( cn.origLine );

View File

@ -113,8 +113,9 @@ private:
VECTOR2I offset;
};
std::set<SOLID*> m_solids;
std::vector<DRAGGED_CONNECTION> m_conns;
std::set<SOLID*> m_solids; // Pads being dragged
std::set<ITEM*> m_fixedItems; // Items being moved along with pads
std::vector<DRAGGED_CONNECTION> m_conns; // Lines being dragged with pads
bool m_dragStatus;
ITEM_SET m_draggedItems;