Pcbnew: fix some issues with very small arcs (size a few internal units)
these very small arcs do not allow to calculate a reliable center position, and therefore a reliable radius. So handle them as a very small segments to fix plotting/drawing issues. From master branch. Fixes #15639 https://gitlab.com/kicad/code/kicad/-/issues/15639
This commit is contained in:
parent
86beb339b7
commit
6eeca9aa90
|
@ -261,6 +261,19 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
|
||||||
{
|
{
|
||||||
const PCB_ARC* arc = static_cast<const PCB_ARC*>( aTrack );
|
const PCB_ARC* arc = static_cast<const PCB_ARC*>( aTrack );
|
||||||
|
|
||||||
|
if( arc->IsDegenerated() )
|
||||||
|
{
|
||||||
|
// Draw this very small arc like a track segment (a PCB_TRACE_T)
|
||||||
|
PCB_TRACK track( arc->GetParent() );
|
||||||
|
track.SetStart( arc->GetStart() );
|
||||||
|
track.SetEnd( arc->GetEnd() );
|
||||||
|
track.SetWidth( arc->GetWidth() );
|
||||||
|
track.SetLayer( arc->GetLayer() );
|
||||||
|
|
||||||
|
createTrack( &track, aDstContainer );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VECTOR2D center( arc->GetCenter() );
|
VECTOR2D center( arc->GetCenter() );
|
||||||
EDA_ANGLE arc_angle = arc->GetAngle();
|
EDA_ANGLE arc_angle = arc->GetAngle();
|
||||||
double radius = arc->GetRadius();
|
double radius = arc->GetRadius();
|
||||||
|
|
|
@ -1170,6 +1170,17 @@ EDA_ANGLE PCB_ARC::GetArcAngleEnd() const
|
||||||
return angleEnd.Normalize();
|
return angleEnd.Normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PCB_ARC::IsDegenerated( int aThreshold ) const
|
||||||
|
{
|
||||||
|
// Too small arcs cannot be really handled: arc center (and arc radius)
|
||||||
|
// cannot be safely computed if the distance between mid and end points
|
||||||
|
// is too small (a few internal units)
|
||||||
|
|
||||||
|
// len of both segments must be < aThreshold to be a very small degenerated arc
|
||||||
|
return ( GetMid() - GetStart() ).EuclideanNorm() < aThreshold
|
||||||
|
&& ( GetMid() - GetEnd() ).EuclideanNorm() < aThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PCB_TRACK::cmp_tracks::operator() ( const PCB_TRACK* a, const PCB_TRACK* b ) const
|
bool PCB_TRACK::cmp_tracks::operator() ( const PCB_TRACK* a, const PCB_TRACK* b ) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -357,6 +357,14 @@ public:
|
||||||
|
|
||||||
EDA_ITEM* Clone() const override;
|
EDA_ITEM* Clone() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the arc is too small to allow a safe calculation
|
||||||
|
* of center position and arc angles i.e if distance between m_Mid and each arc end
|
||||||
|
* is only a few internal units.
|
||||||
|
* @param aThreshold is the minimal dist in internal units. Default id 5 IU
|
||||||
|
*/
|
||||||
|
bool IsDegenerated( int aThreshold = 5 ) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||||
|
|
||||||
|
|
|
@ -638,6 +638,16 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
||||||
{
|
{
|
||||||
const PCB_ARC* arc = static_cast<const PCB_ARC*>( track );
|
const PCB_ARC* arc = static_cast<const PCB_ARC*>( track );
|
||||||
|
|
||||||
|
// Too small arcs cannot be really handled: arc center (and arc radius)
|
||||||
|
// cannot be safely computed
|
||||||
|
if( arc->IsDegenerated( 10 /* in IU */ ) )
|
||||||
|
{
|
||||||
|
// Approximate this very small arc by a segment.
|
||||||
|
aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode,
|
||||||
|
&gbr_metadata );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// ThickArc expects only positive angle arcs, so flip start/end if
|
// ThickArc expects only positive angle arcs, so flip start/end if
|
||||||
// we are negative
|
// we are negative
|
||||||
if( arc->GetAngle() < ANGLE_0 )
|
if( arc->GetAngle() < ANGLE_0 )
|
||||||
|
@ -651,6 +661,7 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
||||||
width, plotMode, &gbr_metadata );
|
width, plotMode, &gbr_metadata );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode,
|
aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode,
|
||||||
|
|
Loading…
Reference in New Issue