geometry: more robust colinearity test in SHAPE_LINE_CHAIN::Simplify()
We now test the midpoint (B) of the 3 consecutive polyline points (A, B, C), since (assuming the angle between AB and BC is > 90 degrees) AC is always longer than AB or BC. This minimizes the distance computation rounding error (in the previous algorithm, taking the point C for colineraity test) if AB is short and BC is very long, the test would often fail due to rouding error in projection/line distance computation
This commit is contained in:
parent
e6ebc2b9b9
commit
3aed13278d
|
@ -1740,46 +1740,36 @@ SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify( bool aRemoveColinear )
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
// stage 2: eliminate colinear segments
|
// stage 2: eliminate colinear segments
|
||||||
while( i < np - 2 )
|
for( i = 1 ; i < np - 1 ; i ++ )
|
||||||
{
|
{
|
||||||
const VECTOR2I p0 = pts_unique[i];
|
const VECTOR2I p_prev = pts_unique[i - 1];
|
||||||
const VECTOR2I p1 = pts_unique[i + 1];
|
const VECTOR2I midpoint = pts_unique[i];
|
||||||
int n = i;
|
const VECTOR2I p_next = pts_unique[i + 1];
|
||||||
|
|
||||||
if( aRemoveColinear && shapes_unique[i] == SHAPES_ARE_PT
|
|
||||||
&& shapes_unique[i + 1] == SHAPES_ARE_PT )
|
if( aRemoveColinear && shapes_unique[i - 1] == SHAPES_ARE_PT
|
||||||
|
&& shapes_unique[i] == SHAPES_ARE_PT )
|
||||||
{
|
{
|
||||||
while( n < np - 2
|
const auto distToMidpoint = SEG( p_prev, p_next ).LineDistance( midpoint );
|
||||||
&& ( SEG( p0, p1 ).LineDistance( pts_unique[n + 2] ) <= 1
|
const auto isMidpointColinear = SEG( p_prev, p_next ).Collinear( SEG( p_prev, midpoint ) );
|
||||||
|| SEG( p0, p1 ).Collinear( SEG( p1, pts_unique[n + 2] ) ) ) )
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_points.push_back( p0 );
|
if( distToMidpoint <= 1 || isMidpointColinear )
|
||||||
|
{
|
||||||
|
pts_unique.erase( pts_unique.begin() + i );
|
||||||
|
shapes_unique.erase( shapes_unique.begin() + i );
|
||||||
|
i--;
|
||||||
|
np--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i = 0 ; i < np; i ++ )
|
||||||
|
{
|
||||||
|
m_points.push_back( pts_unique[i] );
|
||||||
m_shapes.push_back( shapes_unique[i] );
|
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() );
|
assert( m_points.size() == m_shapes.size() );
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
|
Loading…
Reference in New Issue