7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-11 10:00:13 +00:00

kimath: bring back the legacy SHAPE_LINE_CHAIN::Simplify() function

It looks like the new variant (with aMaxError) behaves in a subtly different way, resulting in router hiccups.

This needs more in-depth investigation, but for the moment, the older function does the job.
This commit is contained in:
Tomasz Wlostowski 2024-10-25 00:32:39 +02:00
parent 731cc1eb1a
commit f7e37bf9f2
2 changed files with 106 additions and 0 deletions
libs/kimath
include/geometry
src/geometry

View File

@ -344,6 +344,10 @@ public:
*/
void Simplify( int aMaxError = 0 );
// legacy function, used by the router. Please do not remove until I'll figure out
// the root cause of rounding errors - Tom
SHAPE_LINE_CHAIN& Simplify2( bool aRemoveColinear = true );
/**
* Return the number of points (vertices) in this line chain.
*

View File

@ -2713,6 +2713,108 @@ void SHAPE_LINE_CHAIN::Split( const VECTOR2I& aStart, const VECTOR2I& aEnd, SHAP
}
SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify2( bool aRemoveColinear )
{
std::vector<VECTOR2I> pts_unique;
std::vector<std::pair<ssize_t, ssize_t>> shapes_unique;
// Always try to keep at least 2 points otherwise, we're not really a line
if( PointCount() < 3 )
{
return *this;
}
else if( PointCount() == 3 )
{
if( m_points[0] == m_points[1] )
Remove( 1 );
return *this;
}
int i = 0;
int np = PointCount();
// stage 1: eliminate duplicate vertices
while( i < np )
{
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 < np && 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<ssize_t,ssize_t> shapeToKeep = m_shapes[i];
if( shapeToKeep == SHAPES_ARE_PT )
shapeToKeep = m_shapes[j - 1];
assert( shapeToKeep.first < static_cast<int>( m_arcs.size() ) );
assert( shapeToKeep.second < static_cast<int>( m_arcs.size() ) );
pts_unique.push_back( CPoint( i ) );
shapes_unique.push_back( shapeToKeep );
i = j;
}
m_points.clear();
m_shapes.clear();
np = pts_unique.size();
i = 0;
// stage 2: eliminate colinear segments
while( i < np - 2 )
{
const VECTOR2I p0 = pts_unique[i];
int n = i;
if( aRemoveColinear && shapes_unique[i] == SHAPES_ARE_PT
&& shapes_unique[i + 1] == SHAPES_ARE_PT )
{
while( n < np - 2
&& ( SEG( p0, pts_unique[n + 2] ).LineDistance( pts_unique[n + 1] ) <= 1
|| SEG( p0, pts_unique[n + 2] ).Collinear( SEG( p0, pts_unique[n + 1] ) ) ) )
n++;
}
m_points.push_back( p0 );
m_shapes.push_back( shapes_unique[i] );
if( n > i )
i = n;
if( n == np - 2 )
{
m_points.push_back( pts_unique[np - 1] );
m_shapes.push_back( shapes_unique[np - 1] );
return *this;
}
i++;
}
if( np > 1 )
{
m_points.push_back( pts_unique[np - 2] );
m_shapes.push_back( shapes_unique[np - 2] );
}
m_points.push_back( pts_unique[np - 1] );
m_shapes.push_back( shapes_unique[np - 1] );
assert( m_points.size() == m_shapes.size() );
return *this;
}
bool SHAPE_LINE_CHAIN::OffsetLine( int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError,
SHAPE_LINE_CHAIN& aLeft, SHAPE_LINE_CHAIN& aRight,
bool aSimplify ) const