Fix a degeneracy bug in arc collisions.
This also fixes a failure to use the correct effective width for shapes (which might, for instance, inherit their widths from schematic defaults, netclasses, etc.). Fixes https://gitlab.com/kicad/code/kicad/issues/11358
This commit is contained in:
parent
722b2588f4
commit
007906cd16
|
@ -1086,16 +1086,16 @@ void EDA_SHAPE::SetPolyPoints( const std::vector<VECTOR2I>& aPoints )
|
||||||
std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes( bool aEdgeOnly ) const
|
std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes( bool aEdgeOnly ) const
|
||||||
{
|
{
|
||||||
std::vector<SHAPE*> effectiveShapes;
|
std::vector<SHAPE*> effectiveShapes;
|
||||||
|
int width = GetEffectiveWidth();
|
||||||
|
|
||||||
switch( m_shape )
|
switch( m_shape )
|
||||||
{
|
{
|
||||||
case SHAPE_T::ARC:
|
case SHAPE_T::ARC:
|
||||||
effectiveShapes.emplace_back( new SHAPE_ARC( m_arcCenter, m_start, GetArcAngle(),
|
effectiveShapes.emplace_back( new SHAPE_ARC( m_arcCenter, m_start, GetArcAngle(), width ) );
|
||||||
GetWidth() ) );
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SHAPE_T::SEGMENT:
|
case SHAPE_T::SEGMENT:
|
||||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( m_start, m_end, GetWidth() ) );
|
effectiveShapes.emplace_back( new SHAPE_SEGMENT( m_start, m_end, width ) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SHAPE_T::RECT:
|
case SHAPE_T::RECT:
|
||||||
|
@ -1105,12 +1105,12 @@ std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes( bool aEdgeOnly ) const
|
||||||
if( IsFilled() && !aEdgeOnly )
|
if( IsFilled() && !aEdgeOnly )
|
||||||
effectiveShapes.emplace_back( new SHAPE_SIMPLE( pts ) );
|
effectiveShapes.emplace_back( new SHAPE_SIMPLE( pts ) );
|
||||||
|
|
||||||
if( GetWidth() > 0 || !IsFilled() || aEdgeOnly )
|
if( width > 0 || !IsFilled() || aEdgeOnly )
|
||||||
{
|
{
|
||||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[0], pts[1], GetWidth() ) );
|
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[0], pts[1], width ) );
|
||||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[1], pts[2], GetWidth() ) );
|
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[1], pts[2], width ) );
|
||||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[2], pts[3], GetWidth() ) );
|
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[2], pts[3], width ) );
|
||||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[3], pts[0], GetWidth() ) );
|
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[3], pts[0], width ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1120,21 +1120,21 @@ std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes( bool aEdgeOnly ) const
|
||||||
if( IsFilled() && !aEdgeOnly )
|
if( IsFilled() && !aEdgeOnly )
|
||||||
effectiveShapes.emplace_back( new SHAPE_CIRCLE( getCenter(), GetRadius() ) );
|
effectiveShapes.emplace_back( new SHAPE_CIRCLE( getCenter(), GetRadius() ) );
|
||||||
|
|
||||||
if( GetWidth() > 0 || !IsFilled() || aEdgeOnly )
|
if( width > 0 || !IsFilled() || aEdgeOnly )
|
||||||
effectiveShapes.emplace_back( new SHAPE_ARC( getCenter(), GetEnd(), ANGLE_360 ) );
|
effectiveShapes.emplace_back( new SHAPE_ARC( getCenter(), GetEnd(), ANGLE_360, width ) );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SHAPE_T::BEZIER:
|
case SHAPE_T::BEZIER:
|
||||||
{
|
{
|
||||||
std::vector<VECTOR2I> bezierPoints = buildBezierToSegmentsPointsList( GetWidth() );
|
std::vector<VECTOR2I> bezierPoints = buildBezierToSegmentsPointsList( width );
|
||||||
VECTOR2I start_pt = bezierPoints[0];
|
VECTOR2I start_pt = bezierPoints[0];
|
||||||
|
|
||||||
for( unsigned int jj = 1; jj < bezierPoints.size(); jj++ )
|
for( unsigned int jj = 1; jj < bezierPoints.size(); jj++ )
|
||||||
{
|
{
|
||||||
VECTOR2I end_pt = bezierPoints[jj];
|
VECTOR2I end_pt = bezierPoints[jj];
|
||||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( start_pt, end_pt, GetWidth() ) );
|
effectiveShapes.emplace_back( new SHAPE_SEGMENT( start_pt, end_pt, width ) );
|
||||||
start_pt = end_pt;
|
start_pt = end_pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1154,10 +1154,10 @@ std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes( bool aEdgeOnly ) const
|
||||||
if( IsFilled() && !aEdgeOnly )
|
if( IsFilled() && !aEdgeOnly )
|
||||||
effectiveShapes.emplace_back( new SHAPE_SIMPLE( l ) );
|
effectiveShapes.emplace_back( new SHAPE_SIMPLE( l ) );
|
||||||
|
|
||||||
if( GetWidth() > 0 || !IsFilled() || aEdgeOnly )
|
if( width > 0 || !IsFilled() || aEdgeOnly )
|
||||||
{
|
{
|
||||||
for( int i = 0; i < l.SegmentCount(); i++ )
|
for( int i = 0; i < l.SegmentCount(); i++ )
|
||||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( l.Segment( i ), GetWidth() ) );
|
effectiveShapes.emplace_back( new SHAPE_SEGMENT( l.Segment( i ), width ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1194,7 +1194,7 @@ bool EDA_SHAPE::IsPolyShapeValid() const
|
||||||
if( GetPolyShape().OutlineCount() == 0 )
|
if( GetPolyShape().OutlineCount() == 0 )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const SHAPE_LINE_CHAIN& outline = ( (SHAPE_POLY_SET&)GetPolyShape() ).Outline( 0 );
|
const SHAPE_LINE_CHAIN& outline = static_cast<const SHAPE_POLY_SET&>( GetPolyShape() ).Outline( 0 );
|
||||||
|
|
||||||
return outline.PointCount() > 2;
|
return outline.PointCount() > 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,8 @@ public:
|
||||||
|
|
||||||
int GetPenWidth() const override;
|
int GetPenWidth() const override;
|
||||||
|
|
||||||
|
int GetEffectiveWidth() const override { return GetPenWidth(); }
|
||||||
|
|
||||||
bool HasLineStroke() const override { return true; }
|
bool HasLineStroke() const override { return true; }
|
||||||
STROKE_PARAMS GetStroke() const override { return m_stroke; }
|
STROKE_PARAMS GetStroke() const override { return m_stroke; }
|
||||||
void SetStroke( const STROKE_PARAMS& aStroke ) override;
|
void SetStroke( const STROKE_PARAMS& aStroke ) override;
|
||||||
|
@ -77,9 +79,9 @@ public:
|
||||||
|
|
||||||
VECTOR2I GetCenter() const { return getCenter(); }
|
VECTOR2I GetCenter() const { return getCenter(); }
|
||||||
|
|
||||||
void BeginEdit( const VECTOR2I& aStartPoint ) { beginEdit( aStartPoint ); }
|
void BeginEdit( const VECTOR2I& aStartPoint ) { beginEdit( aStartPoint ); }
|
||||||
bool ContinueEdit( const VECTOR2I& aPosition ) { return continueEdit( aPosition ); }
|
bool ContinueEdit( const VECTOR2I& aPosition ) { return continueEdit( aPosition ); }
|
||||||
void CalcEdit( const VECTOR2I& aPosition ) { calcEdit( aPosition ); }
|
void CalcEdit( const VECTOR2I& aPosition ) { calcEdit( aPosition ); }
|
||||||
void EndEdit() { endEdit(); }
|
void EndEdit() { endEdit(); }
|
||||||
void SetEditState( int aState ) { setEditState( aState ); }
|
void SetEditState( int aState ) { setEditState( aState ); }
|
||||||
|
|
||||||
|
|
|
@ -104,9 +104,10 @@ public:
|
||||||
|
|
||||||
void SetWidth( int aWidth ) { m_stroke.SetWidth( aWidth ); }
|
void SetWidth( int aWidth ) { m_stroke.SetWidth( aWidth ); }
|
||||||
int GetWidth() const { return m_stroke.GetWidth(); }
|
int GetWidth() const { return m_stroke.GetWidth(); }
|
||||||
|
virtual int GetEffectiveWidth() const { return GetWidth(); }
|
||||||
|
|
||||||
void SetShape( SHAPE_T aShape ) { m_shape = aShape; }
|
void SetShape( SHAPE_T aShape ) { m_shape = aShape; }
|
||||||
SHAPE_T GetShape() const { return m_shape; }
|
SHAPE_T GetShape() const { return m_shape; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the starting point of the graphic.
|
* Return the starting point of the graphic.
|
||||||
|
|
|
@ -369,7 +369,7 @@ bool SHAPE_ARC::IsClockwise() const
|
||||||
bool SHAPE_ARC::Collide( const VECTOR2I& aP, int aClearance, int* aActual,
|
bool SHAPE_ARC::Collide( const VECTOR2I& aP, int aClearance, int* aActual,
|
||||||
VECTOR2I* aLocation ) const
|
VECTOR2I* aLocation ) const
|
||||||
{
|
{
|
||||||
int minDist = aClearance + m_width / 2;
|
int minDist = aClearance + std::max( m_width / 2, 1 );
|
||||||
auto bbox = BBox( minDist );
|
auto bbox = BBox( minDist );
|
||||||
|
|
||||||
// Fast check using bounding box:
|
// Fast check using bounding box:
|
||||||
|
|
Loading…
Reference in New Issue