diff --git a/libs/kimath/include/geometry/shape_line_chain.h b/libs/kimath/include/geometry/shape_line_chain.h index dae2782bf5..919b67daac 100644 --- a/libs/kimath/include/geometry/shape_line_chain.h +++ b/libs/kimath/include/geometry/shape_line_chain.h @@ -298,6 +298,11 @@ public: int ShapeCount() const; + /** + * Remove the duplicate points from the line chain. + */ + void RemoveDuplicatePoints(); + /** * Simplify the line chain by removing colinear adjacent segments and duplicate vertices. * diff --git a/libs/kimath/src/geometry/shape_line_chain.cpp b/libs/kimath/src/geometry/shape_line_chain.cpp index 819501b421..538a71bfa3 100644 --- a/libs/kimath/src/geometry/shape_line_chain.cpp +++ b/libs/kimath/src/geometry/shape_line_chain.cpp @@ -2087,6 +2087,68 @@ double SHAPE_LINE_CHAIN::Area( bool aAbsolute ) const } +void SHAPE_LINE_CHAIN::RemoveDuplicatePoints() +{ + std::vector pts_unique; + std::vector> shapes_unique; + + // Always try to keep at least 2 points otherwise, we're not really a line + if( PointCount() < 3 ) + { + return; + } + else if( PointCount() == 3 ) + { + if( m_points[0] == m_points[1] ) + Remove( 1 ); + + return; + } + + int i = 0; + + while( i < PointCount() ) + { + int j = i + 1; + + // We can eliminate duplicate vertices as long as they are part of the same shape, OR if + // one of them is part of a shape and one is not. + while( j < PointCount() && m_points[i] == m_points[j] && + ( m_shapes[i] == m_shapes[j] || + m_shapes[i] == SHAPES_ARE_PT || + m_shapes[j] == SHAPES_ARE_PT ) ) + { + j++; + } + + std::pair shapeToKeep = m_shapes[i]; + + if( shapeToKeep == SHAPES_ARE_PT ) + shapeToKeep = m_shapes[j - 1]; + + assert( shapeToKeep.first < static_cast( m_arcs.size() ) ); + assert( shapeToKeep.second < static_cast( m_arcs.size() ) ); + + pts_unique.push_back( CPoint( i ) ); + shapes_unique.push_back( shapeToKeep ); + + i = j; + } + + m_points.clear(); + m_shapes.clear(); + + for( size_t ii = 0; ii < pts_unique.size(); ++ii ) + { + const VECTOR2I p0 = pts_unique[ii]; + + m_points.push_back( p0 ); + m_shapes.push_back( shapes_unique[ii] ); + } +} + + + void SHAPE_LINE_CHAIN::Simplify( int aMaxError ) { if( PointCount() < 3 ) diff --git a/pcbnew/router/pns_node.cpp b/pcbnew/router/pns_node.cpp index cb71b95cd0..6f971e2c56 100644 --- a/pcbnew/router/pns_node.cpp +++ b/pcbnew/router/pns_node.cpp @@ -1085,7 +1085,7 @@ const LINE NODE::AssembleLine( LINKED_ITEM* aSeg, int* aOriginSegmentIndex, } // Remove duplicate verts, but do NOT remove colinear segments here! - pl.Line().Simplify( false ); + pl.Line().RemoveDuplicatePoints(); // TODO: maintain actual segment index under simplification system if( aOriginSegmentIndex && *aOriginSegmentIndex >= pl.SegmentCount() )