Guard 3D viewer against degenerate shapes.
Fixes https://gitlab.com/kicad/code/kicad/issues/13693
This commit is contained in:
parent
1ee9d538da
commit
203f0f66fb
|
@ -112,8 +112,13 @@ void BOARD_ADAPTER::addText( const EDA_TEXT* aText, CONTAINER_2D_BASE* aContaine
|
||||||
const SFVEC2F pt1_3DU = TO_SFVEC2F( aPt1 );
|
const SFVEC2F pt1_3DU = TO_SFVEC2F( aPt1 );
|
||||||
const SFVEC2F pt2_3DU = TO_SFVEC2F( aPt2 );
|
const SFVEC2F pt2_3DU = TO_SFVEC2F( aPt2 );
|
||||||
|
|
||||||
if( Is_segment_a_circle( pt1_3DU, pt2_3DU ) )
|
if( penWidth_3DU == 0.0 )
|
||||||
{
|
{
|
||||||
|
// Don't attempt to render degenerate shapes
|
||||||
|
}
|
||||||
|
else if( Is_segment_a_circle( pt1_3DU, pt2_3DU ) )
|
||||||
|
{
|
||||||
|
// Cannot add segments that have the same start and end point
|
||||||
aContainer->Add( new FILLED_CIRCLE_2D( pt1_3DU, penWidth_3DU / 2,
|
aContainer->Add( new FILLED_CIRCLE_2D( pt1_3DU, penWidth_3DU / 2,
|
||||||
*aOwner ) );
|
*aOwner ) );
|
||||||
}
|
}
|
||||||
|
@ -253,7 +258,10 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
|
||||||
case PCB_VIA_T:
|
case PCB_VIA_T:
|
||||||
{
|
{
|
||||||
const float radius3DU = TO_3DU( aTrack->GetWidth() / 2 );
|
const float radius3DU = TO_3DU( aTrack->GetWidth() / 2 );
|
||||||
aDstContainer->Add( new FILLED_CIRCLE_2D( start3DU, radius3DU, *aTrack ) );
|
|
||||||
|
if( radius3DU > 0.0 )
|
||||||
|
aDstContainer->Add( new FILLED_CIRCLE_2D( start3DU, radius3DU, *aTrack ) );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,9 +294,13 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
|
||||||
|
|
||||||
case PCB_TRACE_T: // Track is a usual straight segment
|
case PCB_TRACE_T: // Track is a usual straight segment
|
||||||
{
|
{
|
||||||
// Cannot add segments that have the same start and end point
|
if( aTrack->GetWidth() == 0 )
|
||||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
|
||||||
{
|
{
|
||||||
|
// Don't attempt to render degenerate shapes
|
||||||
|
}
|
||||||
|
else if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||||
|
{
|
||||||
|
// Cannot add segments that have the same start and end point
|
||||||
aDstContainer->Add( new FILLED_CIRCLE_2D( start3DU, TO_3DU( aTrack->GetWidth() / 2 ),
|
aDstContainer->Add( new FILLED_CIRCLE_2D( start3DU, TO_3DU( aTrack->GetWidth() / 2 ),
|
||||||
*aTrack ) );
|
*aTrack ) );
|
||||||
}
|
}
|
||||||
|
@ -350,13 +362,22 @@ void BOARD_ADAPTER::createPadWithMargin( const PAD* aPad, CONTAINER_2D_BASE* aCo
|
||||||
const SFVEC2F b3DU = TO_SFVEC2F( seg->GetSeg().B );
|
const SFVEC2F b3DU = TO_SFVEC2F( seg->GetSeg().B );
|
||||||
const double width3DU = TO_3DU( seg->GetWidth() + clearance.x * 2 );
|
const double width3DU = TO_3DU( seg->GetWidth() + clearance.x * 2 );
|
||||||
|
|
||||||
// Cannot add segments that have the same start and end point
|
if( width3DU == 0.0 )
|
||||||
if( Is_segment_a_circle( a3DU, b3DU ) )
|
{
|
||||||
|
// Don't attempt to render degenerate shapes
|
||||||
|
}
|
||||||
|
else if( Is_segment_a_circle( a3DU, b3DU ) )
|
||||||
|
{
|
||||||
|
// Cannot add segments that have the same start and end point
|
||||||
aContainer->Add( new FILLED_CIRCLE_2D( a3DU, width3DU / 2, *aPad ) );
|
aContainer->Add( new FILLED_CIRCLE_2D( a3DU, width3DU / 2, *aPad ) );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
aContainer->Add( new ROUND_SEGMENT_2D( a3DU, b3DU, width3DU, *aPad ) );
|
aContainer->Add( new ROUND_SEGMENT_2D( a3DU, b3DU, width3DU, *aPad ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case SH_CIRCLE:
|
case SH_CIRCLE:
|
||||||
{
|
{
|
||||||
|
@ -366,10 +387,11 @@ void BOARD_ADAPTER::createPadWithMargin( const PAD* aPad, CONTAINER_2D_BASE* aCo
|
||||||
const SFVEC2F center3DU = TO_SFVEC2F( circle->GetCenter() );
|
const SFVEC2F center3DU = TO_SFVEC2F( circle->GetCenter() );
|
||||||
|
|
||||||
// Don't render zero radius circles
|
// Don't render zero radius circles
|
||||||
if( radius3DU != 0.0 )
|
if( radius3DU > 0.0 )
|
||||||
aContainer->Add( new FILLED_CIRCLE_2D( center3DU, radius3DU, *aPad ) );
|
aContainer->Add( new FILLED_CIRCLE_2D( center3DU, radius3DU, *aPad ) );
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case SH_RECT:
|
case SH_RECT:
|
||||||
{
|
{
|
||||||
|
@ -380,8 +402,8 @@ void BOARD_ADAPTER::createPadWithMargin( const PAD* aPad, CONTAINER_2D_BASE* aCo
|
||||||
poly.Append( rect->GetPosition().x + rect->GetSize().x, rect->GetPosition().y );
|
poly.Append( rect->GetPosition().x + rect->GetSize().x, rect->GetPosition().y );
|
||||||
poly.Append( rect->GetPosition() + rect->GetSize() );
|
poly.Append( rect->GetPosition() + rect->GetSize() );
|
||||||
poly.Append( rect->GetPosition().x, rect->GetPosition().y + rect->GetSize().y );
|
poly.Append( rect->GetPosition().x, rect->GetPosition().y + rect->GetSize().y );
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case SH_SIMPLE:
|
case SH_SIMPLE:
|
||||||
poly.AddOutline( static_cast<const SHAPE_SIMPLE*>( shape )->Vertices() );
|
poly.AddOutline( static_cast<const SHAPE_SIMPLE*>( shape )->Vertices() );
|
||||||
|
@ -403,14 +425,23 @@ void BOARD_ADAPTER::createPadWithMargin( const PAD* aPad, CONTAINER_2D_BASE* aCo
|
||||||
const SFVEC2F b3DU = TO_SFVEC2F( seg.GetSeg().B );
|
const SFVEC2F b3DU = TO_SFVEC2F( seg.GetSeg().B );
|
||||||
const double width3DU = TO_3DU( arc->GetWidth() + clearance.x * 2 );
|
const double width3DU = TO_3DU( arc->GetWidth() + clearance.x * 2 );
|
||||||
|
|
||||||
// Cannot add segments that have the same start and end point
|
if( width3DU == 0.0 )
|
||||||
if( Is_segment_a_circle( a3DU, b3DU ) )
|
{
|
||||||
|
// Don't attempt to render degenerate shapes
|
||||||
|
}
|
||||||
|
else if( Is_segment_a_circle( a3DU, b3DU ) )
|
||||||
|
{
|
||||||
|
// Cannot add segments that have the same start and end point
|
||||||
aContainer->Add( new FILLED_CIRCLE_2D( a3DU, width3DU / 2, *aPad ) );
|
aContainer->Add( new FILLED_CIRCLE_2D( a3DU, width3DU / 2, *aPad ) );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
aContainer->Add( new ROUND_SEGMENT_2D( a3DU, b3DU, width3DU, *aPad ) );
|
aContainer->Add( new ROUND_SEGMENT_2D( a3DU, b3DU, width3DU, *aPad ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED_FOR( SHAPE_TYPE_asString( shape->Type() ) );
|
UNIMPLEMENTED_FOR( SHAPE_TYPE_asString( shape->Type() ) );
|
||||||
|
@ -543,6 +574,10 @@ void BOARD_ADAPTER::transformArcToSegments( const VECTOR2I& aCentre, const VECTO
|
||||||
int aWidth, CONTAINER_2D_BASE* aContainer,
|
int aWidth, CONTAINER_2D_BASE* aContainer,
|
||||||
const BOARD_ITEM& aOwner )
|
const BOARD_ITEM& aOwner )
|
||||||
{
|
{
|
||||||
|
// Don't attempt to render degenerate shapes
|
||||||
|
if( aWidth == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
VECTOR2I arc_start, arc_end;
|
VECTOR2I arc_start, arc_end;
|
||||||
EDA_ANGLE arcAngle( aArcAngle );
|
EDA_ANGLE arcAngle( aArcAngle );
|
||||||
EDA_ANGLE delta = ANGLE_360 / aCircleToSegmentsCount; // rotate angle
|
EDA_ANGLE delta = ANGLE_360 / aCircleToSegmentsCount; // rotate angle
|
||||||
|
@ -610,12 +645,22 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
|
||||||
float outer_radius3DU = TO_3DU( aShape->GetRadius() + linewidth / 2 );
|
float outer_radius3DU = TO_3DU( aShape->GetRadius() + linewidth / 2 );
|
||||||
|
|
||||||
if( inner_radius3DU < 0 )
|
if( inner_radius3DU < 0 )
|
||||||
inner_radius3DU = 0;
|
inner_radius3DU = 0.0;
|
||||||
|
|
||||||
if( aShape->IsFilled() )
|
if( outer_radius3DU == 0.0 )
|
||||||
aContainer->Add( new FILLED_CIRCLE_2D( center3DU, outer_radius3DU, *aOwner ) );
|
{
|
||||||
|
// Don't attempt to render degenerate shapes
|
||||||
|
}
|
||||||
|
else if( aShape->IsFilled() )
|
||||||
|
{
|
||||||
|
aContainer->Add( new FILLED_CIRCLE_2D( center3DU, outer_radius3DU,
|
||||||
|
*aOwner ) );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
aContainer->Add( new RING_2D( center3DU, inner_radius3DU, outer_radius3DU, *aOwner ) );
|
{
|
||||||
|
aContainer->Add( new RING_2D( center3DU, inner_radius3DU, outer_radius3DU,
|
||||||
|
*aOwner ) );
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -653,8 +698,8 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
|
||||||
|
|
||||||
transformArcToSegments( aShape->GetCenter(), aShape->GetStart(), aShape->GetArcAngle(),
|
transformArcToSegments( aShape->GetCenter(), aShape->GetStart(), aShape->GetArcAngle(),
|
||||||
segCount, linewidth, aContainer, *aOwner );
|
segCount, linewidth, aContainer, *aOwner );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case SHAPE_T::SEGMENT:
|
case SHAPE_T::SEGMENT:
|
||||||
{
|
{
|
||||||
|
@ -662,12 +707,22 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
|
||||||
const SFVEC2F end3DU = TO_SFVEC2F( aShape->GetEnd() );
|
const SFVEC2F end3DU = TO_SFVEC2F( aShape->GetEnd() );
|
||||||
const double linewidth3DU = TO_3DU( linewidth );
|
const double linewidth3DU = TO_3DU( linewidth );
|
||||||
|
|
||||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
if( linewidth3DU == 0.0 )
|
||||||
|
{
|
||||||
|
// Don't attempt to render degenerate shapes
|
||||||
|
}
|
||||||
|
else if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||||
|
{
|
||||||
|
// Cannot add segments that have the same start and end point
|
||||||
aContainer->Add( new FILLED_CIRCLE_2D( start3DU, linewidth3DU / 2, *aOwner ) );
|
aContainer->Add( new FILLED_CIRCLE_2D( start3DU, linewidth3DU / 2, *aOwner ) );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
aContainer->Add( new ROUND_SEGMENT_2D( start3DU, end3DU, linewidth3DU, *aOwner ) );
|
aContainer->Add( new ROUND_SEGMENT_2D( start3DU, end3DU, linewidth3DU, *aOwner ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case SHAPE_T::BEZIER:
|
case SHAPE_T::BEZIER:
|
||||||
case SHAPE_T::POLY:
|
case SHAPE_T::POLY:
|
||||||
|
@ -681,8 +736,8 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ConvertPolygonToTriangles( polyList, *aContainer, m_biuTo3Dunits, *aOwner );
|
ConvertPolygonToTriangles( polyList, *aContainer, m_biuTo3Dunits, *aOwner );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
wxFAIL_MSG( wxT( "BOARD_ADAPTER::addShape no implementation for " )
|
wxFAIL_MSG( wxT( "BOARD_ADAPTER::addShape no implementation for " )
|
||||||
|
@ -690,7 +745,7 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if( linewidth > 0 )
|
||||||
{
|
{
|
||||||
std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapes( true );
|
std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapes( true );
|
||||||
SFVEC2F a3DU;
|
SFVEC2F a3DU;
|
||||||
|
@ -757,9 +812,18 @@ void BOARD_ADAPTER::buildPadOutlineAsSegments( const PAD* aPad, CONTAINER_2D_BAS
|
||||||
SFVEC2F start3DU = TO_SFVEC2F( path.CPoint( j ) );
|
SFVEC2F start3DU = TO_SFVEC2F( path.CPoint( j ) );
|
||||||
SFVEC2F end3DU = TO_SFVEC2F( path.CPoint( j + 1 ) );
|
SFVEC2F end3DU = TO_SFVEC2F( path.CPoint( j + 1 ) );
|
||||||
|
|
||||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
if( aWidth == 0 )
|
||||||
|
{
|
||||||
|
// Don't attempt to render degenerate shapes
|
||||||
|
}
|
||||||
|
else if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||||
|
{
|
||||||
|
// Cannot add segments that have the same start and end point
|
||||||
aContainer->Add( new FILLED_CIRCLE_2D( start3DU, TO_3DU( aWidth / 2 ), *aPad ) );
|
aContainer->Add( new FILLED_CIRCLE_2D( start3DU, TO_3DU( aWidth / 2 ), *aPad ) );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
aContainer->Add( new ROUND_SEGMENT_2D( start3DU, end3DU, TO_3DU( aWidth ), *aPad ) );
|
aContainer->Add( new ROUND_SEGMENT_2D( start3DU, end3DU, TO_3DU( aWidth ), *aPad ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,7 +279,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||||
|
|
||||||
if( viatype != VIATYPE::THROUGH )
|
if( viatype != VIATYPE::THROUGH )
|
||||||
{
|
{
|
||||||
|
|
||||||
// Add hole objects
|
// Add hole objects
|
||||||
BVH_CONTAINER_2D *layerHoleContainer = nullptr;
|
BVH_CONTAINER_2D *layerHoleContainer = nullptr;
|
||||||
|
|
||||||
|
@ -311,15 +310,21 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||||
hole_inner_radius + thickness,
|
hole_inner_radius + thickness,
|
||||||
*track ) );
|
*track ) );
|
||||||
|
|
||||||
if( m_Cfg->m_Render.clip_silk_on_via_annulus && m_Cfg->m_Render.realistic )
|
if( m_Cfg->m_Render.clip_silk_on_via_annulus
|
||||||
|
&& m_Cfg->m_Render.realistic
|
||||||
|
&& ring_radius > 0.0 )
|
||||||
{
|
{
|
||||||
m_throughHoleAnnularRings.Add( new FILLED_CIRCLE_2D( via_center,
|
m_throughHoleAnnularRings.Add( new FILLED_CIRCLE_2D( via_center,
|
||||||
ring_radius,
|
ring_radius,
|
||||||
*track ) );
|
*track ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_throughHoleIds.Add( new FILLED_CIRCLE_2D( via_center, hole_inner_radius,
|
if( hole_inner_radius > 0.0 )
|
||||||
*track ) );
|
{
|
||||||
|
m_throughHoleIds.Add( new FILLED_CIRCLE_2D( via_center,
|
||||||
|
hole_inner_radius,
|
||||||
|
*track ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue