36#include "../3d_rendering/raytracing/shapes2D/filled_circle_2d.h"
58#ifdef PRINT_STATISTICS_3D_VIEWER
69 int aWidth,
int aMaxError,
ERROR_LOC aErrorLoc )
74 aWidth, aMaxError, aErrorLoc );
81 for(
int ii = 0; ii <
path.PointCount(); ++ii )
99 if( item->GetLayer() == aLayer )
100 item->TransformShapeToPolygon( aBuffer, aLayer, 0, aMaxError, aErrorLoc );
108#define DELETE_AND_FREE( ptr ) \
114#define DELETE_AND_FREE_MAP( map ) \
116 for( auto& [ layer, poly ] : map ) \
160#ifdef PRINT_STATISTICS_3D_VIEWER
163 int64_t start_Time = stats_startCopperLayersTime;
181 std::vector<const PCB_TRACK*> trackList;
198 trackList.push_back( track );
220 std::vector<PCB_LAYER_ID> layer_ids;
229 layer_ids.push_back( layer );
258 if( aStatusReporter )
259 aStatusReporter->
Report(
_(
"Create tracks and vias" ) );
268 for(
const PCB_TRACK* track : trackList )
271 if( !track->IsOnLayer( layer ) )
290 unsigned int nTracks = trackList.size();
292 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
294 const PCB_TRACK *track = trackList[trackIdx];
309 const float thickness =
static_cast<float>( plating / 2.0f );
310 const float hole_inner_radius =
static_cast<float>( holediameter / 2.0f );
311 const float ring_radius =
static_cast<float>( viasize / 2.0f );
316 if( viatype != VIATYPE::THROUGH )
336 hole_inner_radius + thickness,
339 else if( layer == layer_ids[0] )
350 if( hole_inner_radius > 0.0 )
372 const unsigned int nTracks = trackList.size();
374 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
376 const PCB_TRACK *track = trackList[trackIdx];
387 if( viatype != VIATYPE::THROUGH )
417 const int holediameter =
via->GetDrillValue();
426 else if( layer == layer_ids[0] )
428 const int holediameter =
via->GetDrillValue();
430 const int hole_outer_ring_radius =
KiROUND(
via->GetWidth( layer ) / 2.0 );
460 unsigned int nTracks = trackList.size();
462 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
464 const PCB_TRACK *track = trackList[trackIdx];
485 for(
PAD*
pad : footprint->Pads() )
495 if(
pad->GetAttribute () != PAD_ATTRIB::NPTH )
499 double holeDiameter = (
pad->GetDrillSize().x +
pad->GetDrillSize().y ) / 2.0;
517 for(
PAD*
pad : footprint->Pads() )
527 if(
pad->GetAttribute () != PAD_ATTRIB::NPTH )
576 footprint->TransformPadsToPolySet( *layerPoly, layer, 0, maxError,
ERROR_INSIDE,
607 if( !item->IsOnLayer( layer ) )
610 switch( item->Type() )
637 wxLogTrace(
m_logTrace, wxT(
"createLayers: item type: %d not implemented" ),
647 if( layer ==
F_Cu || layer ==
B_Cu )
659 text_box->PCB_SHAPE::TransformShapeToPolygon( *platedCopperPolys, layer,
664 static_cast<PCB_TEXT*
>( item )->TransformTextToPolySet(
688 if( !item->IsOnLayer( layer ) )
691 switch( item->Type() )
694 item->TransformShapeToPolygon( *layerPoly, layer, 0, maxError,
ERROR_INSIDE );
718 wxLogTrace(
m_logTrace, wxT(
"createLayers: item type: %d not implemented" ),
728 if( aStatusReporter )
729 aStatusReporter->
Report(
_(
"Create zones" ) );
731 std::vector<std::pair<ZONE*, PCB_LAYER_ID>> zones;
732 std::unordered_map<PCB_LAYER_ID, std::unique_ptr<std::mutex>> layer_lock;
738 zones.emplace_back( std::make_pair( zone, layer ) );
739 layer_lock.emplace( layer, std::make_unique<std::mutex>() );
755 std::atomic<size_t> nextZone( 0 );
756 std::atomic<size_t> threadsFinished( 0 );
758 size_t parallelThreadCount = std::min<size_t>( zones.size(),
759 std::max<size_t>( std::thread::hardware_concurrency(), 2 ) );
761 for(
size_t ii = 0; ii < parallelThreadCount; ++ii )
763 std::thread t = std::thread( [&]()
765 for(
size_t areaId = nextZone.fetch_add( 1 );
766 areaId < zones.size();
767 areaId = nextZone.fetch_add( 1 ) )
769 ZONE* zone = zones[areaId].first;
771 if( zone == nullptr )
774 PCB_LAYER_ID layer = zones[areaId].second;
776 auto layerContainer = m_layerMap.find( layer );
777 auto layerPolyContainer = m_layers_poly.find( layer );
779 if( layerContainer != m_layerMap.end() )
780 addSolidAreasShapes( zone, layerContainer->second, layer );
782 if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL
783 && layerPolyContainer != m_layers_poly.end() )
785 auto mut_it = layer_lock.find( layer );
787 std::lock_guard< std::mutex > lock( *( mut_it->second ) );
788 zone->TransformSolidAreasShapesToPolygon( layer, *layerPolyContainer->second );
798 while( threadsFinished < parallelThreadCount )
799 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
804 m_TH_ODPolys.Simplify();
805 m_NPTH_ODPolys.Simplify();
806 m_viaTH_ODPolys.Simplify();
807 m_viaAnnuliPolys.Simplify();
812 if( aStatusReporter )
813 aStatusReporter->Report(
_(
"Build Tech layers" ) );
834 std::bitset<LAYER_3D_END> enabledFlags = visibilityFlags;
836 if( cfg.subtract_mask_from_silk || cfg.DifferentiatePlatedCopper() )
844 if( aStatusReporter )
845 aStatusReporter->Report( wxString::Format(
_(
"Build Tech layer %d" ), (
int) layer ) );
847 if( !Is3dLayerEnabled( layer, enabledFlags ) )
851 m_layerMap[layer] = layerContainer;
854 m_layers_poly[layer] = layerPoly;
856 if( Is3dLayerEnabled( layer, visibilityFlags ) )
861 if( !item->IsOnLayer( layer ) )
864 switch( item->Type() )
867 addShape(
static_cast<PCB_SHAPE*
>( item ), layerContainer, item, layer );
871 addText(
static_cast<PCB_TEXT*
>( item ), layerContainer, item );
875 addShape(
static_cast<PCB_TEXTBOX*
>( item ), layerContainer, item );
898 for(
PCB_TRACK* track : m_board->Tracks() )
900 if( !track->IsOnLayer( layer ) )
910 int maskExpansion = track->GetSolderMaskExpansion();
911 createTrackWithMargin( track, layerContainer, layer, maskExpansion );
916 for(
FOOTPRINT* footprint : m_board->Footprints() )
920 int linewidth = m_board->GetDesignSettings().m_LineThickness[
LAYER_CLASS_SILK ];
922 for(
PAD*
pad : footprint->Pads() )
924 if( !
pad->IsOnLayer( layer ) )
927 buildPadOutlineAsSegments(
pad, layer, layerContainer, linewidth );
932 addPads( footprint, layerContainer, layer,
false,
false );
935 addFootprintShapes( footprint, layerContainer, layer, visibilityFlags );
941 for(
ZONE* zone : m_board->Zones() )
943 if( zone->IsOnLayer( layer ) )
944 addSolidAreasShapes( zone, layerContainer, layer );
952 || ( cfg.DifferentiatePlatedCopper() && ( layer ==
F_Mask || layer ==
B_Mask ) ) )
957 if( !item->IsOnLayer( layer ) )
960 switch( item->Type() )
963 item->TransformShapeToPolygon( *layerPoly, layer, 0, maxError,
ERROR_INSIDE );
996 for(
PCB_TRACK* track : m_board->Tracks() )
1002 track->TransformShapeToPolygon( *layerPoly, layer, maskExpansion, maxError,
1009 for(
FOOTPRINT* footprint : m_board->Footprints() )
1013 int linewidth = m_board->GetDesignSettings().m_LineThickness[
LAYER_CLASS_SILK ];
1015 for(
PAD*
pad : footprint->Pads() )
1017 if(
pad->IsOnLayer( layer ) )
1026 footprint->TransformPadsToPolySet( *layerPoly, layer, 0, maxError,
ERROR_INSIDE );
1030 footprint->TransformFPTextToPolySet( *layerPoly, layer, 0, maxError,
ERROR_INSIDE );
1036 if( cfg.show_zones || layer ==
F_Mask || layer ==
B_Mask )
1038 for(
ZONE* zone : m_board->Zones() )
1040 if( zone->IsOnLayer( layer ) )
1041 zone->TransformSolidAreasShapesToPolygon( layer, *layerPoly );
1053 if( cfg.show_off_board_silk )
1055 BOX2I boardBBox = m_board_poly.BBox();
1057 for(
FOOTPRINT* footprint : m_board->Footprints() )
1059 if( !footprint->GetBoundingBox().Intersects( boardBBox ) )
1061 if( footprint->IsFlipped() )
1062 addPads( footprint, m_offboardPadsBack,
B_Cu,
false,
false );
1064 addPads( footprint, m_offboardPadsFront,
F_Cu,
false,
false );
1068 m_offboardPadsFront->BuildBVH();
1069 m_offboardPadsBack->BuildBVH();
1074 if( aStatusReporter )
1075 aStatusReporter->Report(
_(
"Simplifying copper layer polygons" ) );
1077 if( cfg.DifferentiatePlatedCopper() )
1079 if( aStatusReporter )
1080 aStatusReporter->Report(
_(
"Calculating plated copper" ) );
1083 if( m_layers_poly.find(
F_Mask ) != m_layers_poly.end() )
1085 m_frontPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at(
F_Mask ) );
1088 if( m_layers_poly.find(
B_Mask ) != m_layers_poly.end() )
1090 m_backPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at(
B_Mask ) );
1094 bool hasF_Cu =
false;
1095 bool hasB_Cu =
false;
1097 if( m_layers_poly.find(
F_Cu ) != m_layers_poly.end() )
1099 m_layers_poly[
F_Cu]->BooleanSubtract( *m_frontPlatedPadAndGraphicPolys );
1100 m_layers_poly[
F_Cu]->BooleanSubtract( *m_frontPlatedCopperPolys );
1104 if( m_layers_poly.find(
B_Cu ) != m_layers_poly.end() )
1106 m_layers_poly[
B_Cu]->BooleanSubtract( *m_backPlatedPadAndGraphicPolys );
1107 m_layers_poly[
B_Cu]->BooleanSubtract( *m_backPlatedCopperPolys );
1112 if( hasF_Cu && m_frontPlatedCopperPolys->OutlineCount() )
1113 m_frontPlatedPadAndGraphicPolys->Append( *m_frontPlatedCopperPolys );
1115 if( hasB_Cu && m_backPlatedCopperPolys->OutlineCount() )
1116 m_backPlatedPadAndGraphicPolys->Append( *m_backPlatedCopperPolys );
1118 m_frontPlatedPadAndGraphicPolys->Simplify();
1119 m_backPlatedPadAndGraphicPolys->Simplify();
1120 m_frontPlatedCopperPolys->Simplify();
1121 m_backPlatedCopperPolys->Simplify();
1124 for(
FOOTPRINT* footprint : m_board->Footprints() )
1126 addPads( footprint, m_platedPadsFront,
F_Cu,
false,
true );
1127 addPads( footprint, m_platedPadsBack,
B_Cu,
false,
true );
1132 *m_board->GetItem(
niluuid ) );
1135 *m_board->GetItem(
niluuid ) );
1137 m_platedPadsFront->BuildBVH();
1138 m_platedPadsBack->BuildBVH();
1143 std::vector<PCB_LAYER_ID> &selected_layer_id = layer_ids;
1144 std::vector<PCB_LAYER_ID> layer_id_without_F_and_B;
1146 if( cfg.DifferentiatePlatedCopper() )
1148 layer_id_without_F_and_B.clear();
1149 layer_id_without_F_and_B.reserve( layer_ids.size() );
1153 if( layer !=
F_Cu && layer !=
B_Cu )
1154 layer_id_without_F_and_B.push_back( layer );
1157 selected_layer_id = layer_id_without_F_and_B;
1160 if( selected_layer_id.size() > 0 )
1162 if( aStatusReporter )
1164 aStatusReporter->Report( wxString::Format(
_(
"Simplifying %d copper layers" ),
1165 (
int) selected_layer_id.size() ) );
1168 std::atomic<size_t> nextItem( 0 );
1169 std::atomic<size_t> threadsFinished( 0 );
1171 size_t parallelThreadCount = std::min<size_t>(
1172 std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
1173 selected_layer_id.size() );
1175 for(
size_t ii = 0; ii < parallelThreadCount; ++ii )
1177 std::thread t = std::thread(
1178 [&nextItem, &threadsFinished, &selected_layer_id,
this]()
1180 for(
size_t i = nextItem.fetch_add( 1 );
1181 i < selected_layer_id.size();
1182 i = nextItem.fetch_add( 1 ) )
1184 auto layerPoly = m_layers_poly.find( selected_layer_id[i] );
1186 if( layerPoly != m_layers_poly.end() )
1189 layerPoly->second->ClearArcs();
1190 layerPoly->second->Simplify();
1200 while( threadsFinished < parallelThreadCount )
1201 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1206 if( aStatusReporter )
1207 aStatusReporter->Report(
_(
"Simplify holes contours" ) );
1211 if( m_layerHoleOdPolys.find( layer ) != m_layerHoleOdPolys.end() )
1217 wxASSERT( m_layerHoleIdPolys.find( layer ) != m_layerHoleIdPolys.end() );
1219 polyLayer = m_layerHoleIdPolys[layer];
1226 if( aStatusReporter )
1227 aStatusReporter->Report(
_(
"Build BVH for holes and vias" ) );
1229 m_TH_IDs.BuildBVH();
1230 m_TH_ODs.BuildBVH();
1231 m_viaAnnuli.BuildBVH();
1233 if( !m_layerHoleMap.empty() )
1235 for( std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& hole : m_layerHoleMap )
1236 hole.second->BuildBVH();
1242 m_layerMap[
B_Mask]->BuildBVH();
1245 m_layerMap[
F_Mask]->BuildBVH();
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
MAP_CONTAINER_2D_BASE m_layerHoleMap
Holes for each layer.
double BiuTo3dUnits() const noexcept
Board integer units To 3D units.
BVH_CONTAINER_2D * m_offboardPadsBack
void createLayers(REPORTER *aStatusReporter)
SHAPE_POLY_SET m_TH_ODPolys
PTH outer diameters.
void createTrackWithMargin(const PCB_TRACK *aTrack, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayer, int aMargin=0)
MAP_POLY m_layerHoleOdPolys
Hole outer diameters (per layer)
SHAPE_POLY_SET * m_frontPlatedCopperPolys
MAP_CONTAINER_2D_BASE m_layerMap
2D elements for each layer.
BVH_CONTAINER_2D m_TH_ODs
List of PTH outer diameters.
SHAPE_POLY_SET * m_frontPlatedPadAndGraphicPolys
unsigned int m_trackCount
float m_averageTrackWidth
std::bitset< LAYER_3D_END > GetVisibleLayers() const
void addFootprintShapes(const FOOTPRINT *aFootprint, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayerId, const std::bitset< LAYER_3D_END > &aVisibilityFlags)
MAP_POLY m_layerHoleIdPolys
Hole inner diameters (per layer)
int GetHolePlatingThickness() const noexcept
Get the hole plating thickness (NB: in BOARD UNITS!).
SHAPE_POLY_SET m_viaAnnuliPolys
Via annular ring outer diameters.
BVH_CONTAINER_2D * m_offboardPadsFront
float m_averageViaHoleDiameter
BVH_CONTAINER_2D m_viaTH_ODs
List of via hole outer diameters.
float m_averageHoleDiameter
SHAPE_POLY_SET m_viaTH_ODPolys
Via hole outer diameters.
void addPads(const FOOTPRINT *aFootprint, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads)
BVH_CONTAINER_2D * m_platedPadsBack
void createPadWithHole(const PAD *aPad, CONTAINER_2D_BASE *aDstContainer, int aInflateValue)
MAP_POLY m_layers_poly
Amalgamated polygon contours for various types of items.
SHAPE_POLY_SET * m_backPlatedCopperPolys
EDA_3D_VIEWER_SETTINGS * m_Cfg
void addTable(const PCB_TABLE *aTable, CONTAINER_2D_BASE *aContainer, const BOARD_ITEM *aOwner)
BVH_CONTAINER_2D m_viaAnnuli
List of via annular rings.
unsigned int m_copperLayersCount
BVH_CONTAINER_2D m_TH_IDs
List of PTH inner diameters.
BVH_CONTAINER_2D * m_platedPadsFront
void addShape(const PCB_SHAPE *aShape, CONTAINER_2D_BASE *aContainer, const BOARD_ITEM *aOwner, PCB_LAYER_ID aLayer)
SHAPE_POLY_SET m_NPTH_ODPolys
NPTH outer diameters.
SHAPE_POLY_SET * m_backPlatedPadAndGraphicPolys
bool Is3dLayerEnabled(PCB_LAYER_ID aLayer, const std::bitset< LAYER_3D_END > &aVisibilityFlags) const
Check if a layer is enabled.
double m_biuTo3Dunits
Scale factor to convert board internal units to 3D units normalized between -1.0 and 1....
void addText(const EDA_TEXT *aText, CONTAINER_2D_BASE *aDstContainer, const BOARD_ITEM *aOwner)
int m_SolderMaskExpansion
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
const ZONES & Zones() const
const FOOTPRINTS & Footprints() const
const TRACKS & Tracks() const
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
const DRAWINGS & Drawings() const
void Add(OBJECT_2D *aObject)
KICAD_T Type() const
Returns the type of object.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(PCB_LAYER_ID aLayer, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) const
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth=false) const override
Convert the item shape to a closed polygon.
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the track shape to a closed polygon.
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
bool IsTented(PCB_LAYER_ID aLayer) const override
Checks if the given object is tented (its copper shape is covered by solder mask) on a given side of ...
bool FlashLayer(int aLayer) const
Check to see whether the via should have a pad on the specific layer.
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
Handle a list of polygons defining a copper zone.
void TransformRingToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aCentre, int aRadius, int aWidth, int aError, ERROR_LOC aErrorLoc)
Convert arcs to multiple straight segments.
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
#define DELETE_AND_FREE_MAP(map)
void transformFPShapesToPolySet(const FOOTPRINT *aFootprint, PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aBuffer, int aMaxError, ERROR_LOC aErrorLoc)
void buildPadOutlineAsPolygon(const PAD *aPad, PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aBuffer, int aWidth, int aMaxError, ERROR_LOC aErrorLoc)
#define DELETE_AND_FREE(ptr)
static const wxChar * m_logTrace
Trace mask used to enable or disable debug output for this class.
bool IsSolderMaskLayer(int aLayer)
@ LAYER_3D_SOLDERMASK_TOP
@ LAYER_3D_SOLDERMASK_BOTTOM
PCB_LAYER_ID
A quick note on layer IDs:
int64_t GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
bool opengl_copper_thickness
bool clip_silk_on_via_annuli
bool DifferentiatePlatedCopper()
return true if platted copper aeras and non platted copper areas must be drawn using a different colo...
void ConvertPolygonToTriangles(const SHAPE_POLY_SET &aPolyList, CONTAINER_2D_BASE &aDstContainer, float aBiuTo3dUnitsScale, const BOARD_ITEM &aBoardItem)
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension