From 2c8ada42a09022714032ad329c5a04cfb6c52ca9 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Thu, 9 Apr 2020 10:37:17 +0200 Subject: [PATCH] Arc shaped track segments: fix 3D viewer and track to polygon converter. --- 3d-viewer/3d_canvas/board_adapter.h | 3 +- .../3d_canvas/create_3Dgraphic_brd_items.cpp | 94 +++++++++++++------ 3d-viewer/3d_canvas/create_layer_items.cpp | 2 +- ...board_items_to_polygon_shape_transform.cpp | 19 +++- 4 files changed, 80 insertions(+), 38 deletions(-) diff --git a/3d-viewer/3d_canvas/board_adapter.h b/3d-viewer/3d_canvas/board_adapter.h index 2fd7267ae4..34ec1ab492 100644 --- a/3d-viewer/3d_canvas/board_adapter.h +++ b/3d-viewer/3d_canvas/board_adapter.h @@ -426,7 +426,8 @@ class BOARD_ADAPTER void destroyLayers(); // 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, CGENERICCONTAINER2D *aDstContainer, diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index c1d2357f08..f9121d5efe 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -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: 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 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, - int aClearanceValue ) const +void BOARD_ADAPTER::createNewTrack( const TRACK* aTrack, CGENERICCONTAINER2D *aDstContainer, + int aClearanceValue ) { SFVEC2F start3DU( aTrack->GetStart().x * m_biuTo3Dunits, -aTrack->GetStart().y * m_biuTo3Dunits ); // y coord is inverted @@ -238,38 +237,72 @@ COBJECT2D *BOARD_ADAPTER::createNewTrack( const TRACK* aTrack, switch( aTrack->Type() ) { case PCB_VIA_T: - { + { 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( 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; 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; } - - return NULL; } @@ -686,8 +719,7 @@ void BOARD_ADAPTER::TransformArcToSegments( const wxPoint &aCentre, } else { - aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, - end3DU, + aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, end3DU, aWidth * m_biuTo3Dunits, aBoardItem ) ); } diff --git a/3d-viewer/3d_canvas/create_layer_items.cpp b/3d-viewer/3d_canvas/create_layer_items.cpp index 2cca8ab56e..bb66cc2e1e 100644 --- a/3d-viewer/3d_canvas/create_layer_items.cpp +++ b/3d-viewer/3d_canvas/create_layer_items.cpp @@ -234,7 +234,7 @@ void BOARD_ADAPTER::createLayers( REPORTER *aStatusTextReporter ) continue; // Add object item to layer container - layerContainer->Add( createNewTrack( track, 0.0f ) ); + createNewTrack( track, layerContainer, 0.0f ); } } diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index a794aa66bc..8d410da019 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -520,20 +520,29 @@ void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, { wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for tracks." ); + int width = m_Width + ( 2 * aClearanceValue ); + switch( Type() ) { case PCB_VIA_T: - { + { int radius = ( m_Width / 2 ) + aClearanceValue; TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aError ); - } + } + break; + + case PCB_ARC_T: + { + const ARC* arc = static_cast( this ); + VECTOR2D center( arc->GetCenter() ); + double arc_angle = arc->GetAngle(); + TransformArcToPolygon( aCornerBuffer, wxPoint( center.x, center.y ), + GetStart(), arc_angle, aError, width ); + } break; default: - { - int width = m_Width + ( 2 * aClearanceValue ); TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError ); - } break; } }