PNS: Fix several issues with arc dragging
Do not merge vertices that belong to different arcs Fix start segment identification after arcs Fix free-angle drag after arc Fixes https://gitlab.com/kicad/code/kicad/-/issues/8173 Fixes https://gitlab.com/kicad/code/kicad/-/issues/8150
This commit is contained in:
parent
7d58c53e42
commit
a26fc6d65d
|
@ -305,11 +305,36 @@ void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const SHAPE_LINE
|
|||
if( aStartIndex < 0 )
|
||||
aStartIndex += PointCount();
|
||||
|
||||
// We only process lines in order in this house
|
||||
wxASSERT( aStartIndex <= aEndIndex );
|
||||
|
||||
SHAPE_LINE_CHAIN newLine = aLine;
|
||||
|
||||
// It's possible that the start or end lands on the end of an arc. If so, we'd better have a
|
||||
// replacement line that matches up to the same coordinates, as we can't break the arc(s).
|
||||
ssize_t startShape = m_shapes[aStartIndex];
|
||||
ssize_t endShape = m_shapes[aEndIndex];
|
||||
|
||||
if( startShape >= 0 )
|
||||
{
|
||||
wxASSERT( newLine.m_points.front() == m_points[aStartIndex] &&
|
||||
aStartIndex < m_points.size() - 1 );
|
||||
aStartIndex++;
|
||||
newLine.Remove( 0 );
|
||||
}
|
||||
|
||||
if( endShape >= 0 )
|
||||
{
|
||||
wxASSERT( newLine.m_points.back() == m_points[aEndIndex] && aEndIndex > 0 );
|
||||
aEndIndex--;
|
||||
newLine.Remove( -1 );
|
||||
}
|
||||
|
||||
Remove( aStartIndex, aEndIndex );
|
||||
|
||||
// The total new arcs index is added to the new arc indices
|
||||
size_t prev_arc_count = m_arcs.size();
|
||||
std::vector<ssize_t> new_shapes = aLine.m_shapes;
|
||||
size_t prev_arc_count = m_arcs.size();
|
||||
std::vector<ssize_t> new_shapes = newLine.m_shapes;
|
||||
|
||||
for( ssize_t& shape : new_shapes )
|
||||
{
|
||||
|
@ -318,8 +343,9 @@ void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const SHAPE_LINE
|
|||
}
|
||||
|
||||
m_shapes.insert( m_shapes.begin() + aStartIndex, new_shapes.begin(), new_shapes.end() );
|
||||
m_points.insert( m_points.begin() + aStartIndex, aLine.m_points.begin(), aLine.m_points.end() );
|
||||
m_arcs.insert( m_arcs.end(), aLine.m_arcs.begin(), aLine.m_arcs.end() );
|
||||
m_points.insert( m_points.begin() + aStartIndex, newLine.m_points.begin(),
|
||||
newLine.m_points.end() );
|
||||
m_arcs.insert( m_arcs.end(), newLine.m_arcs.begin(), newLine.m_arcs.end() );
|
||||
|
||||
assert( m_shapes.size() == m_points.size() );
|
||||
}
|
||||
|
@ -328,6 +354,7 @@ void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const SHAPE_LINE
|
|||
void SHAPE_LINE_CHAIN::Remove( int aStartIndex, int aEndIndex )
|
||||
{
|
||||
assert( m_shapes.size() == m_points.size() );
|
||||
|
||||
if( aEndIndex < 0 )
|
||||
aEndIndex += PointCount();
|
||||
|
||||
|
@ -1025,7 +1052,7 @@ SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify( bool aRemoveColinear )
|
|||
const VECTOR2I p1 = pts_unique[i + 1];
|
||||
int n = i;
|
||||
|
||||
if( aRemoveColinear )
|
||||
if( aRemoveColinear && shapes_unique[i] < 0 && shapes_unique[i + 1] < 0 )
|
||||
{
|
||||
while( n < np - 2
|
||||
&& ( SEG( p0, p1 ).LineDistance( pts_unique[n + 2] ) <= 1
|
||||
|
|
|
@ -89,15 +89,23 @@ bool DRAGGER::startDragSegment( const VECTOR2D& aP, SEGMENT* aSeg )
|
|||
else if( distB <= w2 )
|
||||
{
|
||||
//todo (snh) Adjust segment for arcs
|
||||
m_draggedSegmentIndex++;
|
||||
m_mode = DM_CORNER;
|
||||
}
|
||||
else if ( m_freeAngleMode )
|
||||
{
|
||||
if( distB < distA )
|
||||
if( ( m_draggedSegmentIndex < m_draggedLine.PointCount() - 1 ) &&
|
||||
( m_draggedLine.CLine().CShapes()[ m_draggedSegmentIndex + 1 ] < 0 ) )
|
||||
{
|
||||
m_draggedSegmentIndex++;
|
||||
}
|
||||
|
||||
m_mode = DM_CORNER;
|
||||
}
|
||||
else if( m_freeAngleMode )
|
||||
{
|
||||
if( distB < distA &&
|
||||
( m_draggedSegmentIndex < m_draggedLine.PointCount() - 1 ) &&
|
||||
( m_draggedLine.CLine().CShapes()[ m_draggedSegmentIndex + 1 ] < 0 ) )
|
||||
{
|
||||
m_draggedSegmentIndex++;
|
||||
}
|
||||
|
||||
m_mode = DM_CORNER;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -587,6 +587,22 @@ void LINE::dragCorner45( const VECTOR2I& aP, int aIndex )
|
|||
|
||||
void LINE::dragCornerFree( const VECTOR2I& aP, int aIndex )
|
||||
{
|
||||
const std::vector<ssize_t>& shapes = m_line.CShapes();
|
||||
|
||||
// If we're asked to drag the end of an arc, insert a new vertex to drag instead
|
||||
if( shapes[aIndex] >= 0 )
|
||||
{
|
||||
if( aIndex > 0 && shapes[aIndex - 1] == -1 )
|
||||
m_line.Insert( aIndex, m_line.GetPoint( aIndex ) );
|
||||
else if( aIndex < shapes.size() - 1 && shapes[aIndex + 1] == -1 )
|
||||
{
|
||||
aIndex++;
|
||||
m_line.Insert( aIndex, m_line.GetPoint( aIndex ) );
|
||||
}
|
||||
else
|
||||
wxASSERT_MSG( false, "Attempt to dragCornerFree in the middle of an arc!" );
|
||||
}
|
||||
|
||||
m_line.SetPoint( aIndex, aP );
|
||||
m_line.Simplify();
|
||||
}
|
||||
|
|
|
@ -943,13 +943,15 @@ const LINE NODE::AssembleLine( LINKED_ITEM* aSeg, int* aOriginSegmentIndex,
|
|||
LINKED_ITEM* prev_seg = NULL;
|
||||
bool originSet = false;
|
||||
|
||||
SHAPE_LINE_CHAIN& line = pl.Line();
|
||||
|
||||
for( int i = i_start + 1; i < i_end; i++ )
|
||||
{
|
||||
const VECTOR2I& p = corners[i];
|
||||
LINKED_ITEM* li = segs[i];
|
||||
|
||||
if( !li || li->Kind() != ITEM::ARC_T )
|
||||
pl.Line().Append( p );
|
||||
line.Append( p );
|
||||
|
||||
if( li && prev_seg != li )
|
||||
{
|
||||
|
@ -960,11 +962,17 @@ const LINE NODE::AssembleLine( LINKED_ITEM* aSeg, int* aOriginSegmentIndex,
|
|||
const ARC* arc = static_cast<const ARC*>( li );
|
||||
const SHAPE_ARC* sa = static_cast<const SHAPE_ARC*>( arc->Shape() );
|
||||
|
||||
int nSegs = pl.Line().SegmentCount();
|
||||
int nSegs = line.PointCount();
|
||||
VECTOR2I last = line.CPoint( -1 );
|
||||
ssize_t lastShape = line.CShapes()[nSegs - 1];
|
||||
|
||||
pl.Line().Append( arcReversed[i] ? sa->Reversed() : *sa );
|
||||
line.Append( arcReversed[i] ? sa->Reversed() : *sa );
|
||||
|
||||
segIdxIncrement = pl.Line().SegmentCount() - nSegs - 1;
|
||||
segIdxIncrement = line.PointCount() - nSegs - 1;
|
||||
|
||||
// Are we adding an arc after an arc? add the hidden segment
|
||||
if( lastShape >= 0 )
|
||||
segIdxIncrement++;
|
||||
}
|
||||
|
||||
pl.Link( li );
|
||||
|
|
|
@ -561,7 +561,8 @@ bool OPTIMIZER::mergeFull( LINE* aLine )
|
|||
|
||||
bool OPTIMIZER::mergeColinear( LINE* aLine )
|
||||
{
|
||||
SHAPE_LINE_CHAIN& line = aLine->Line();
|
||||
SHAPE_LINE_CHAIN& line = aLine->Line();
|
||||
const std::vector<ssize_t> shapes = line.CShapes();
|
||||
|
||||
int nSegs = line.SegmentCount();
|
||||
|
||||
|
@ -570,7 +571,7 @@ bool OPTIMIZER::mergeColinear( LINE* aLine )
|
|||
SEG s1 = line.CSegment( segIdx );
|
||||
SEG s2 = line.CSegment( segIdx + 1 );
|
||||
|
||||
if( s1.Collinear( s2 ) )
|
||||
if( shapes[segIdx] < 0 && shapes[segIdx + 1] < 0 && s1.Collinear( s2 ) )
|
||||
line.Replace( segIdx, segIdx + 1, s1.A );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue