KiCad PCB EDA Suite
board_adapter.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
5  * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
30 #include "../3d_rendering/ccamera.h"
31 #include "board_adapter.h"
33 #include <class_board.h>
34 #include <3d_math.h>
35 #include "3d_fastmath.h"
37 #include <math/util.h> // for KiROUND
38 #include <pgm_base.h>
40 
47 const wxChar *BOARD_ADAPTER::m_logTrace = wxT( "KI_TRACE_EDA_CINFO3D_VISU" );
48 
49 
51  m_board( nullptr ),
52  m_3d_model_manager( nullptr ),
53  m_colors( nullptr ),
54  m_layerZcoordTop(),
55  m_layerZcoordBottom()
56 {
57  wxLogTrace( m_logTrace, wxT( "BOARD_ADAPTER::BOARD_ADAPTER" ) );
58 
61  m_drawFlags.resize( FL_LAST, false );
62 
63  if( PgmOrNull() )
64  m_colors = Pgm().GetSettingsManager().GetColorSettings();
65 
68 
69  m_boardPos = wxPoint();
70  m_boardSize = wxSize();
71  m_boardCenter = SFVEC3F( 0.0f );
72 
74 
77 
79  m_epoxyThickness3DU = 0.0f;
80  m_copperThickness3DU = 0.0f;
82  m_biuTo3Dunits = 1.0;
83 
85  m_stats_nr_vias = 0;
87  m_stats_nr_holes = 0;
90 
93 
96  SetFlag( FL_SHOW_BOARD_BODY, true );
100  SetFlag( FL_ZONE, true );
101  SetFlag( FL_SILKSCREEN, true );
102  SetFlag( FL_SOLDERMASK, true );
104 
110 
111  m_BgColorBot = SFVEC3D( 0.4, 0.4, 0.5 );
112  m_BgColorTop = SFVEC3D( 0.8, 0.8, 0.9 );
113  m_BoardBodyColor = SFVEC3D( 0.4, 0.4, 0.5 );
114  m_SolderMaskColorTop = SFVEC3D( 0.1, 0.2, 0.1 );
115  m_SolderMaskColorBot = SFVEC3D( 0.1, 0.2, 0.1 );
116  m_SolderPasteColor = SFVEC3D( 0.4, 0.4, 0.4 );
117  m_SilkScreenColorTop = SFVEC3D( 0.9, 0.9, 0.9 );
118  m_SilkScreenColorBot = SFVEC3D( 0.9, 0.9, 0.9 );
119  m_CopperColor = SFVEC3D( 0.75, 0.61, 0.23 );
120 }
121 
122 
124 {
125  destroyLayers();
126 }
127 
128 
130 {
131  wxASSERT( aLayer < PCB_LAYER_ID_COUNT );
132 
133  DISPLAY3D_FLG flg;
134 
135  // see if layer needs to be shown
136  // check the flags
137  switch( aLayer )
138  {
139  case B_Adhes:
140  case F_Adhes:
141  flg = FL_ADHESIVE;
142  break;
143 
144  case B_Paste:
145  case F_Paste:
146  flg = FL_SOLDERPASTE;
147  break;
148 
149  case B_SilkS:
150  case F_SilkS:
151  flg = FL_SILKSCREEN;
152  break;
153 
154  case B_Mask:
155  case F_Mask:
156  flg = FL_SOLDERMASK;
157  break;
158 
159  case Dwgs_User:
160  case Cmts_User:
162  return false;
163 
164  flg = FL_COMMENTS;
165  break;
166 
167  case Eco1_User:
168  case Eco2_User:
170  return false;
171 
172  flg = FL_ECO;
173  break;
174 
175  case Edge_Cuts:
177  return false;
178 
179  return true;
180  break;
181 
182  case Margin:
184  return false;
185 
186  return true;
187  break;
188 
189  case B_Cu:
190  case F_Cu:
191  return m_board->IsLayerVisible( aLayer ) || GetFlag( FL_USE_REALISTIC_MODE );
192  break;
193 
194  default:
195  // the layer is an internal copper layer, used the visibility
197  {
198  // Do not render internal layers if it is overlap with the board
199  // (on OpenGL render)
200  return false;
201  }
202 
203  return m_board->IsLayerVisible( aLayer );
204  }
205 
206  // The layer has a flag, return the flag
207  return GetFlag( flg );
208 }
209 
210 
212 {
213  wxASSERT( aFlag < FL_LAST );
214 
215  return m_drawFlags[aFlag];
216 }
217 
218 
219 void BOARD_ADAPTER::SetFlag( DISPLAY3D_FLG aFlag, bool aState )
220 {
221  wxASSERT( aFlag < FL_LAST );
222 
223  m_drawFlags[aFlag] = aState;
224 }
225 
227 {
228  if( ( ( aModuleAttributs == MOD_DEFAULT ) &&
230  ( ( ( aModuleAttributs & MOD_CMS) == MOD_CMS ) &&
232  ( ( ( aModuleAttributs & MOD_VIRTUAL) == MOD_VIRTUAL ) &&
234  {
235  return true;
236  }
237 
238  return false;
239 }
240 
241 
242 // !TODO: define the actual copper thickness by user
243 #define COPPER_THICKNESS KiROUND( 0.035 * IU_PER_MM ) // for 35 um
244 #define TECH_LAYER_THICKNESS KiROUND( 0.04 * IU_PER_MM )
245 
247 {
248  return COPPER_THICKNESS;
249 }
250 
251 unsigned int BOARD_ADAPTER::GetNrSegmentsCircle( float aDiameter3DU ) const
252 {
253  wxASSERT( aDiameter3DU > 0.0f );
254 
255  return GetNrSegmentsCircle( (int)( aDiameter3DU / m_biuTo3Dunits ) );
256 }
257 
258 
259 unsigned int BOARD_ADAPTER::GetNrSegmentsCircle( int aDiameterBIU ) const
260 {
261  wxASSERT( aDiameterBIU > 0 );
262 
263  // Require at least 3 segments for a circle
264  return std::max( GetArcToSegmentCount( aDiameterBIU / 2, ARC_HIGH_DEF, 360.0 ), 3 );
265 }
266 
267 
268 double BOARD_ADAPTER::GetCircleCorrectionFactor( int aNrSides ) const
269 {
270  wxASSERT( aNrSides >= 3 );
271 
272  return GetCircletoPolyCorrectionFactor( aNrSides );
273 }
274 
275 
276 void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningReporter )
277 {
278  wxLogTrace( m_logTrace, wxT( "BOARD_ADAPTER::InitSettings" ) );
279 
280  // Calculates the board bounding box (board outlines + items)
281  // to ensure any item, even outside the board outlines can be seen
282  EDA_RECT bbbox = m_board->ComputeBoundingBox( false );
283 
284  // Gives a non null size to avoid issues in zoom / scale calculations
285  if( ( bbbox.GetWidth() == 0 ) && ( bbbox.GetHeight() == 0 ) )
286  bbbox.Inflate( Millimeter2iu( 10 ) );
287 
288  m_boardSize = bbbox.GetSize();
289  m_boardPos = bbbox.Centre();
290 
291  wxASSERT( (m_boardSize.x > 0) && (m_boardSize.y > 0) );
292 
293  m_boardPos.y = -m_boardPos.y; // The y coord is inverted in 3D viewer
294 
296 
297  // Ensure the board has 2 sides for 3D views, because it is hard to find
298  // a *really* single side board in the true life...
299  if( m_copperLayersCount < 2 )
301 
302  // Calculate the convertion to apply to all positions.
304 
306 
307  // !TODO: use value defined by user (currently use default values by ctor
310 
311  // Init Z position of each layer
312  // calculate z position for each copper layer
313  // Zstart = -m_epoxyThickness / 2.0 is the z position of the back (bottom layer) (layer id = 31)
314  // Zstart = +m_epoxyThickness / 2.0 is the z position of the front (top layer) (layer id = 0)
315  // all unused copper layer z position are set to 0
316 
317  // ____==__________==________==______ <- Bottom = +m_epoxyThickness / 2.0,
318  // | | Top = Bottom + m_copperThickness
319  // |__________________________________|
320  // == == == == <- Bottom = -m_epoxyThickness / 2.0,
321  // Top = Bottom - m_copperThickness
322 
323  unsigned int layer;
324 
325  for( layer = 0; layer < m_copperLayersCount; ++layer )
326  {
327  m_layerZcoordBottom[layer] = m_epoxyThickness3DU / 2.0f -
328  (m_epoxyThickness3DU * layer / (m_copperLayersCount - 1) );
329 
330  if( layer < (m_copperLayersCount / 2) )
332  else
334  }
335 
336  #define layerThicknessMargin 1.1
337  const float zpos_offset = m_nonCopperLayerThickness3DU * layerThicknessMargin;
338 
339  // Fill remaining unused copper layers and back layer zpos
340  // with -m_epoxyThickness / 2.0
341  for( ; layer < MAX_CU_LAYERS; layer++ )
342  {
343  m_layerZcoordBottom[layer] = -(m_epoxyThickness3DU / 2.0f);
345  }
346 
347  // This is the top of the copper layer thickness.
348  const float zpos_copperTop_back = m_layerZcoordTop[B_Cu];
349  const float zpos_copperTop_front = m_layerZcoordTop[F_Cu];
350 
351  // calculate z position for each non copper layer
352  // Solder mask and Solder paste have the same Z position
353  for( int layer_id = MAX_CU_LAYERS; layer_id < PCB_LAYER_ID_COUNT; ++layer_id )
354  {
355  float zposTop;
356  float zposBottom;
357 
358  switch( layer_id )
359  {
360  case B_Adhes:
361  zposBottom = zpos_copperTop_back - 2.0f * zpos_offset;
362  zposTop = zposBottom - m_nonCopperLayerThickness3DU;
363  break;
364 
365  case F_Adhes:
366  zposBottom = zpos_copperTop_front + 2.0f * zpos_offset;
367  zposTop = zposBottom + m_nonCopperLayerThickness3DU;
368  break;
369 
370  case B_Mask:
371  case B_Paste:
372  zposBottom = zpos_copperTop_back;
373  zposTop = zpos_copperTop_back - m_nonCopperLayerThickness3DU;
374  break;
375 
376  case F_Mask:
377  case F_Paste:
378  zposTop = zpos_copperTop_front + m_nonCopperLayerThickness3DU;
379  zposBottom = zpos_copperTop_front;
380  break;
381 
382  case B_SilkS:
383  zposBottom = zpos_copperTop_back - 1.0f * zpos_offset;
384  zposTop = zposBottom - m_nonCopperLayerThickness3DU;
385  break;
386 
387  case F_SilkS:
388  zposBottom = zpos_copperTop_front + 1.0f * zpos_offset;
389  zposTop = zposBottom + m_nonCopperLayerThickness3DU;
390  break;
391 
392  // !TODO: review
393  default:
394  zposTop = zpos_copperTop_front + (layer_id - MAX_CU_LAYERS + 3.0f) * zpos_offset;
395  zposBottom = zposTop - m_nonCopperLayerThickness3DU;
396  break;
397  }
398 
399  m_layerZcoordTop[layer_id] = zposTop;
400  m_layerZcoordBottom[layer_id] = zposBottom;
401  }
402 
405  0.0f );
406 
407  SFVEC3F boardSize = SFVEC3F( m_boardSize.x * m_biuTo3Dunits,
409  0.0f );
410  boardSize /= 2.0f;
411 
412  SFVEC3F boardMin = (m_boardCenter - boardSize);
413  SFVEC3F boardMax = (m_boardCenter + boardSize);
414 
415  boardMin.z = m_layerZcoordTop[B_Adhes];
416  boardMax.z = m_layerZcoordTop[F_Adhes];
417 
418  m_boardBoundingBox = CBBOX( boardMin, boardMax );
419 
420 #ifdef PRINT_STATISTICS_3D_VIEWER
421  unsigned stats_startCreateBoardPolyTime = GetRunningMicroSecs();
422 #endif
423 
424  if( aStatusReporter )
425  aStatusReporter->Report( _( "Build board body" ) );
426 
427  if( !createBoardPolygon() )
428  aWarningReporter->Report( _( "Board outline is not closed" ), RPT_SEVERITY_WARNING );
429  else
430  aWarningReporter->Report( wxEmptyString );
431 
432 #ifdef PRINT_STATISTICS_3D_VIEWER
433  unsigned stats_stopCreateBoardPolyTime = GetRunningMicroSecs();
434  unsigned stats_startCreateLayersTime = stats_stopCreateBoardPolyTime;
435 #endif
436 
437  if( aStatusReporter )
438  aStatusReporter->Report( _( "Create layers" ) );
439 
440  createLayers( aStatusReporter );
441 
442 #ifdef PRINT_STATISTICS_3D_VIEWER
443  unsigned stats_stopCreateLayersTime = GetRunningMicroSecs();
444 
445  printf( "BOARD_ADAPTER::InitSettings times\n" );
446  printf( " CreateBoardPoly: %.3f ms\n",
447  (float)( stats_stopCreateBoardPolyTime - stats_startCreateBoardPolyTime ) / 1e3 );
448  printf( " CreateLayers and holes: %.3f ms\n",
449  (float)( stats_stopCreateLayersTime - stats_startCreateLayersTime ) / 1e3 );
450  printf( "\n" );
451 #endif
452 }
453 
454 
456 {
458 
459  wxString errmsg;
460 
461  return m_board->GetBoardPolygonOutlines( m_board_poly, &errmsg );
462 }
463 
464 
465 float BOARD_ADAPTER::GetModulesZcoord3DIU( bool aIsFlipped ) const
466 {
467  if( aIsFlipped )
468  {
469  if( GetFlag( FL_SOLDERPASTE ) )
471  else
473  }
474  else
475  {
476  if( GetFlag( FL_SOLDERPASTE ) )
477  return m_layerZcoordTop[F_SilkS];
478  else
479  return m_layerZcoordTop[F_Paste];
480  }
481 }
482 
483 
485 {
486  wxASSERT( aLayerId < PCB_LAYER_ID_COUNT );
487 
488  const COLOR4D color = m_colors->GetColor( aLayerId );
489 
490  return SFVEC3F( color.r, color.g, color.b );
491 }
492 
493 
495 {
496  return GetColor( m_colors->GetColor( aItemId ) );
497 }
498 
499 
501 {
502  return SFVEC3F( aColor.r, aColor.g, aColor.b );
503 }
GRID3D_TYPE m_3D_grid_type
bool GetFlag(DISPLAY3D_FLG aFlag) const
GetFlag - get a configuration status of a flag.
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:104
Defines math related functions.
#define TECH_LAYER_THICKNESS
float m_nonCopperLayerThickness3DU
Non copper layers thickness.
SFVEC3D m_SolderPasteColor
in realistic mode: solder paste color
bool createBoardPolygon()
Create the board outline polygon.
SFVEC3D m_SolderMaskColorBot
in realistic mode: solder mask color ( bot )
void SetFlag(DISPLAY3D_FLG aFlag, bool aState)
SetFlag - set the status of a flag.
COLOR_SETTINGS * m_colors
int color
Definition: DXF_plotter.cpp:61
CBVHCONTAINER2D m_through_holes_inner
It contains the list of throughHoles of the board, the radius is the inner hole.
int GetWidth() const
Definition: eda_rect.h:119
Set for modules listed in the automatic insertion list (usually SMD footprints)
Definition: class_module.h:68
void InitSettings(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
InitSettings - Function to be called by the render when it need to reload the settings for the board.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:551
double g
Green component.
Definition: color4d.h:367
unsigned int m_stats_nr_holes
number of holes in the board
#define layerThicknessMargin
wxPoint m_boardPos
center board actual position in board units
REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
SFVEC3D m_SilkScreenColorBot
in realistic mode: SilkScreen color ( bot )
std::array< float, PCB_LAYER_ID_COUNT > m_layerZcoordBottom
Bottom (Start) Z position of each layer (normalized)
float m_epoxyThickness3DU
Epoxy thickness (normalized)
unsigned int m_stats_nr_vias
Nr of vias.
float m_copperThickness3DU
Copper thickness (normalized)
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
double GetCircleCorrectionFactor(int aNrSides) const
GetCircleCorrectionFactor - computes a angle correction factor used when creating circles.
double b
Blue component.
Definition: color4d.h:368
SFVEC3D m_BgColorTop
background top color
RENDER_ENGINE m_render_engine
PCB_LAYER_ID
A quick note on layer IDs:
unsigned int GetNrSegmentsCircle(float aDiameter3DU) const
GetNrSegmentsCircle.
std::vector< bool > m_drawFlags
std::array< float, PCB_LAYER_ID_COUNT > m_layerZcoordTop
Top (End) Z position of each layer (normalized)
CBBOX m_boardBoundingBox
3d bounding box of the pcb board in 3d units
SHAPE_POLY_SET m_board_poly
PCB board outline polygon.
double GetCircletoPolyCorrectionFactor(int aSegCountforCircle)
int GetCopperThicknessBIU() const noexcept
GetCopperThicknessBIU - Get the current copper layer thickness.
Use all material properties from model file.
float m_stats_track_med_width
Track average width.
glm::dvec3 SFVEC3D
Definition: xv3d_types.h:48
float m_calc_seg_max_factor3DU
max factor used for cicle segment approximation calculation
double m_biuTo3Dunits
Normalization scale to convert board internal units to 3D units to normalize 3D units between -1....
bool Is3DLayerEnabled(PCB_LAYER_ID aLayer) const
Is3DLayerEnabled - Check if a layer is enabled.
a few functions useful in geometry calculations.
MODULE_ATTR_T
Enum MODULE_ATTR_T is the set of attributes allowed within a MODULE, using MODULE::SetAttributes() an...
Definition: class_module.h:65
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, wxString *aErrorText=nullptr, wxPoint *aErrorLocation=nullptr)
Function GetBoardPolygonOutlines Extracts the board outlines and build a closed polygon from lines,...
SFVEC3F GetLayerColor(PCB_LAYER_ID aLayerId) const
GetLayerColor - get the technical color of a layer.
void createLayers(REPORTER *aStatusReporter)
int GetHeight() const
Definition: eda_rect.h:120
SFVEC3D m_BgColorBot
background bottom color
default
Definition: class_module.h:67
DISPLAY3D_FLG
Flags used in rendering options.
Definition: 3d_enums.h:34
CBVHCONTAINER2D m_through_holes_outer
It contains the list of throughHoles of the board, the radius of the hole is inflated with the copper...
SFVEC3D m_SolderMaskColorTop
in realistic mode: solder mask color ( top )
COLOR4D GetColor(int aLayer) const
wxSize m_boardSize
board actual size in board units
bool IsLayerVisible(PCB_LAYER_ID aLayer) const
Function IsLayerVisible is a proxy function that calls the correspondent function in m_BoardSettings ...
SFVEC3D m_SilkScreenColorTop
in realistic mode: SilkScreen color ( top )
see class PGM_BASE
bool ShouldModuleBeDisplayed(MODULE_ATTR_T aModuleAttributs) const
ShouldModuleBeDisplayed - Test if module should be displayed in relation to attributs and the flags.
#define _(s)
Definition: 3d_actions.cpp:33
unsigned GetRunningMicroSecs()
Function GetRunningMicroSecs An alternate way to calculate an elapset time (in microsecondes) to clas...
glm::vec3 SFVEC3F
Definition: xv3d_types.h:47
Virtual component: when created by copper shapes on board (Like edge card connectors,...
Definition: class_module.h:70
unsigned int m_copperLayersCount
Number of copper layers actually used by the board.
SFVEC3D m_BoardBodyColor
in realistic mode: FR4 board color
SFVEC3F GetItemColor(int aItemId) const
GetItemColor - get the technical color of a layer.
int GetCopperLayerCount() const
Function GetCopperLayerCount.
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
SFVEC3D m_CopperColor
in realistic mode: copper color
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
float GetModulesZcoord3DIU(bool aIsFlipped) const
GetModulesZcoord3DIU - Get the position of the module in 3d integer units considering if it is flippe...
wxPoint Centre() const
Definition: eda_rect.h:62
float m_stats_via_med_hole_diameter
Computed medium diameter of the via holes in 3D units.
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Function ComputeBoundingBox calculates the bounding box containing all board items (or board edge seg...
Defines math related functions.
float m_stats_hole_med_diameter
Computed medium diameter of the holes in 3D units.
SFVEC3F m_boardCenter
3d center position of the pcb board in 3d units
#define COPPER_THICKNESS
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this class.
double r
Red component.
Definition: color4d.h:366
MATERIAL_MODE m_material_mode
SFVEC3F GetColor(COLOR4D aColor) const
GetColor.
PGM_BASE * PgmOrNull()
similat to PGM_BASE& Pgm(), but return a reference that can be nullptr when running a shared lib from...
ANTIALIASING_MODE m_antialiasing_mode
float m_calc_seg_min_factor3DU
min factor used for cicle segment approximation calculation
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
Definition: board_adapter.h:61
CBBOX manages a bounding box defined by two SFVEC3F min max points.
Definition: cbbox.h:40
void Reset()
Function Reset reset the bounding box to zero and de-initialized it.
Definition: cbbox.cpp:98
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
unsigned int m_stats_nr_tracks
Number of tracks in the board.
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
const wxSize GetSize() const
Definition: eda_rect.h:103
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:99