Arc shaped track segments: fix 3D viewer and track to polygon converter.

This commit is contained in:
jean-pierre charras 2020-04-09 10:37:17 +02:00
parent e016b629d3
commit 2c8ada42a0
4 changed files with 80 additions and 38 deletions

View File

@ -426,7 +426,8 @@ class BOARD_ADAPTER
void destroyLayers(); void destroyLayers();
// Helper functions to create the board // Helper functions to create the board
COBJECT2D *createNewTrack( const TRACK* aTrack , int aClearanceValue ) const; void createNewTrack( const TRACK* aTrack, CGENERICCONTAINER2D *aDstContainer,
int aClearanceValue );
void createNewPadWithClearance( const D_PAD *aPad, void createNewPadWithClearance( const D_PAD *aPad,
CGENERICCONTAINER2D *aDstContainer, CGENERICCONTAINER2D *aDstContainer,

View File

@ -45,6 +45,7 @@
#include <class_text_mod.h> #include <class_text_mod.h>
#include <convert_basic_shapes_to_polygon.h> #include <convert_basic_shapes_to_polygon.h>
#include <trigo.h> #include <trigo.h>
#include <geometry/geometry_utils.h>
#include <gr_text.h> #include <gr_text.h>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -62,8 +63,6 @@ static const BOARD_ITEM *s_boardItem = NULL;
// This is a call back function, used by GRText to draw the 3D text shape: // This is a call back function, used by GRText to draw the 3D text shape:
void addTextSegmToContainer( int x0, int y0, int xf, int yf, void* aData ) void addTextSegmToContainer( int x0, int y0, int xf, int yf, void* aData )
{ {
wxASSERT( s_dstcontainer != NULL );
const SFVEC2F start3DU( x0 * s_biuTo3Dunits, -y0 * s_biuTo3Dunits ); const SFVEC2F start3DU( x0 * s_biuTo3Dunits, -y0 * s_biuTo3Dunits );
const SFVEC2F end3DU ( xf * s_biuTo3Dunits, -yf * s_biuTo3Dunits ); const SFVEC2F end3DU ( xf * s_biuTo3Dunits, -yf * s_biuTo3Dunits );
@ -229,8 +228,8 @@ void BOARD_ADAPTER::AddGraphicsShapesWithClearanceToContainer( const MODULE* aMo
} }
COBJECT2D *BOARD_ADAPTER::createNewTrack( const TRACK* aTrack, void BOARD_ADAPTER::createNewTrack( const TRACK* aTrack, CGENERICCONTAINER2D *aDstContainer,
int aClearanceValue ) const int aClearanceValue )
{ {
SFVEC2F start3DU( aTrack->GetStart().x * m_biuTo3Dunits, SFVEC2F start3DU( aTrack->GetStart().x * m_biuTo3Dunits,
-aTrack->GetStart().y * m_biuTo3Dunits ); // y coord is inverted -aTrack->GetStart().y * m_biuTo3Dunits ); // y coord is inverted
@ -238,38 +237,72 @@ COBJECT2D *BOARD_ADAPTER::createNewTrack( const TRACK* aTrack,
switch( aTrack->Type() ) switch( aTrack->Type() )
{ {
case PCB_VIA_T: case PCB_VIA_T:
{ {
const float radius = ( ( aTrack->GetWidth() / 2 ) + aClearanceValue ) * m_biuTo3Dunits; const float radius = ( ( aTrack->GetWidth() / 2 ) + aClearanceValue ) * m_biuTo3Dunits;
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU, radius, *aTrack ) );
}
break;
return new CFILLEDCIRCLE2D( start3DU, radius, *aTrack ); case PCB_ARC_T:
} {
const ARC* arc = static_cast<const ARC*>( aTrack );
VECTOR2D center( arc->GetCenter() );
double arc_angle = arc->GetAngle();
double radius = arc->GetRadius();
int arcsegcount = GetArcToSegmentCount( radius, Millimeter2iu( 0.005), arc_angle/10 );
int circlesegcount;
// We need a circle to segment count. However, the arc angle can be small, and the
// radius very big. so we calculate a reasonable value for circlesegcount.
if( arcsegcount <= 1 ) // The arc will be approximated by a segment
circlesegcount = 1;
else
{
double cnt = arcsegcount * 3600/std::abs( arc_angle );
#define SEG_CNT_MAX 128
if( cnt < SEG_CNT_MAX )
{
circlesegcount = (int)cnt;
if( circlesegcount == 0 )
circlesegcount = 1;
}
else
circlesegcount = SEG_CNT_MAX;
}
TransformArcToSegments( wxPoint( center.x, center.y ), arc->GetStart(),
arc_angle, circlesegcount,
arc->GetWidth() + 2 * aClearanceValue, aDstContainer,
*arc );
}
break;
case PCB_TRACE_T: // Track is a usual straight segment
{
SFVEC2F end3DU ( aTrack->GetEnd().x * m_biuTo3Dunits,
-aTrack->GetEnd().y * m_biuTo3Dunits );
// Cannot add segments that have the same start and end point
if( Is_segment_a_circle( start3DU, end3DU ) )
{
const float radius = ((aTrack->GetWidth() / 2) + aClearanceValue) * m_biuTo3Dunits;
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU, radius, *aTrack ) );
}
else
{
const float width = (aTrack->GetWidth() + 2 * aClearanceValue ) * m_biuTo3Dunits;
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, end3DU, width, *aTrack ) );
}
}
break; break;
default: default:
{
wxASSERT( aTrack->Type() == PCB_TRACE_T );
SFVEC2F end3DU ( aTrack->GetEnd().x * m_biuTo3Dunits,
-aTrack->GetEnd().y * m_biuTo3Dunits );
// Cannot add segments that have the same start and end point
if( Is_segment_a_circle( start3DU, end3DU ) )
{
const float radius = ((aTrack->GetWidth() / 2) + aClearanceValue) * m_biuTo3Dunits;
return new CFILLEDCIRCLE2D( start3DU, radius, *aTrack );
}
else
{
const float width = (aTrack->GetWidth() + 2 * aClearanceValue ) * m_biuTo3Dunits;
return new CROUNDSEGMENT2D( start3DU, end3DU, width, *aTrack );
}
}
break; break;
} }
return NULL;
} }
@ -686,8 +719,7 @@ void BOARD_ADAPTER::TransformArcToSegments( const wxPoint &aCentre,
} }
else else
{ {
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, end3DU,
end3DU,
aWidth * m_biuTo3Dunits, aWidth * m_biuTo3Dunits,
aBoardItem ) ); aBoardItem ) );
} }

View File

@ -234,7 +234,7 @@ void BOARD_ADAPTER::createLayers( REPORTER *aStatusTextReporter )
continue; continue;
// Add object item to layer container // Add object item to layer container
layerContainer->Add( createNewTrack( track, 0.0f ) ); createNewTrack( track, layerContainer, 0.0f );
} }
} }

View File

@ -520,20 +520,29 @@ void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
{ {
wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for tracks." ); wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for tracks." );
int width = m_Width + ( 2 * aClearanceValue );
switch( Type() ) switch( Type() )
{ {
case PCB_VIA_T: case PCB_VIA_T:
{ {
int radius = ( m_Width / 2 ) + aClearanceValue; int radius = ( m_Width / 2 ) + aClearanceValue;
TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aError ); TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aError );
} }
break;
case PCB_ARC_T:
{
const ARC* arc = static_cast<const ARC*>( this );
VECTOR2D center( arc->GetCenter() );
double arc_angle = arc->GetAngle();
TransformArcToPolygon( aCornerBuffer, wxPoint( center.x, center.y ),
GetStart(), arc_angle, aError, width );
}
break; break;
default: default:
{
int width = m_Width + ( 2 * aClearanceValue );
TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError ); TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError );
}
break; break;
} }
} }