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 <[email protected]>
5  * Copyright (C) 1992-2021 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 
25 #include "../3d_rendering/camera.h"
26 #include "board_adapter.h"
27 #include <board_design_settings.h>
31 #include <board.h>
33 #include <3d_math.h>
34 #include "3d_fastmath.h"
36 #include <convert_to_biu.h>
37 #include <pgm_base.h>
39 #include <wx/log.h>
40 
41 
47 
55 
56 static bool g_ColorsLoaded = false;
57 
66 const wxChar *BOARD_ADAPTER::m_logTrace = wxT( "KI_TRACE_EDA_CINFO3D_VISU" );
67 
68 
70  m_board( nullptr ),
71  m_3dModelManager( nullptr ),
72  m_colors( nullptr ),
73  m_layerZcoordTop(),
74  m_layerZcoordBottom()
75 {
76  wxLogTrace( m_logTrace, wxT( "BOARD_ADAPTER::BOARD_ADAPTER" ) );
77 
80  m_drawFlags.resize( FL_LAST, false );
81 
82  if( PgmOrNull() )
83  m_colors = Pgm().GetSettingsManager().GetColorSettings();
84 
87 
88  m_boardPos = wxPoint();
89  m_boardSize = wxSize();
90  m_boardCenter = SFVEC3F( 0.0f );
91 
93 
97 
99  m_epoxyThickness3DU = 0.0f;
100  m_copperThickness3DU = 0.0f;
103  m_biuTo3Dunits = 1.0;
104 
105  m_trackCount = 0;
106  m_viaCount = 0;
108  m_holeCount = 0;
109  m_averageHoleDiameter = 0.0f;
110  m_averageTrackWidth = 0.0f;
111 
114  SetFlag( FL_SHOW_BOARD_BODY, true );
119  SetFlag( FL_ZONE, true );
120  SetFlag( FL_SILKSCREEN, true );
121  SetFlag( FL_SOLDERMASK, true );
123 
129 
130  SetFlag( FL_USE_SELECTION, true );
132 
133  m_BgColorBot = SFVEC4F( 0.4, 0.4, 0.5, 1.0 );
134  m_BgColorTop = SFVEC4F( 0.8, 0.8, 0.9, 1.0 );
135  m_BoardBodyColor = SFVEC4F( 0.4, 0.4, 0.5, 0.9 );
136  m_SolderMaskColorTop = SFVEC4F( 0.1, 0.2, 0.1, 0.83 );
137  m_SolderMaskColorBot = SFVEC4F( 0.1, 0.2, 0.1, 0.83 );
138  m_SolderPasteColor = SFVEC4F( 0.4, 0.4, 0.4, 1.0 );
139  m_SilkScreenColorTop = SFVEC4F( 0.9, 0.9, 0.9, 1.0 );
140  m_SilkScreenColorBot = SFVEC4F( 0.9, 0.9, 0.9, 1.0 );
141  m_CopperColor = SFVEC4F( 0.75, 0.61, 0.23, 1.0 );
142 
143  m_platedPadsFront = nullptr;
144  m_platedPadsBack = nullptr;
145 
146  m_frontPlatedPadPolys = nullptr;
147  m_backPlatedPadPolys = nullptr;
148 
149  // Avoid raytracing options not initialized:
153 
154  m_RtSpreadShadows = 0.0;
155  m_RtSpreadReflections = 0.0;
156  m_RtSpreadRefractions = 0.0;
157 
160 
161  if( !g_ColorsLoaded )
162  {
163 #define ADD_COLOR( list, r, g, b, a, name ) \
164  list.push_back( CUSTOM_COLOR_ITEM( r/255.0, g/255.0, b/255.0, a, name ) )
165 
166  ADD_COLOR( g_SilkscreenColors, 245, 245, 245, 1.0, NotSpecifiedPrm() ); // White
167  ADD_COLOR( g_SilkscreenColors, 20, 51, 36, 1.0, wxT( "Green" ) );
168  ADD_COLOR( g_SilkscreenColors, 181, 19, 21, 1.0, wxT( "Red" ) );
169  ADD_COLOR( g_SilkscreenColors, 2, 59, 162, 1.0, wxT( "Blue" ) );
170  ADD_COLOR( g_SilkscreenColors, 11, 11, 11, 1.0, wxT( "Black" ) );
171  ADD_COLOR( g_SilkscreenColors, 245, 245, 245, 1.0, wxT( "White" ) );
172  ADD_COLOR( g_SilkscreenColors, 32, 2, 53, 1.0, wxT( "Purple" ) );
173  ADD_COLOR( g_SilkscreenColors, 194, 195, 0, 1.0, wxT( "Yellow" ) );
174 
175  ADD_COLOR( g_MaskColors, 20, 51, 36, 0.83, NotSpecifiedPrm() ); // Green
176  ADD_COLOR( g_MaskColors, 20, 51, 36, 0.83, wxT( "Green" ) );
177  ADD_COLOR( g_MaskColors, 91, 168, 12, 0.83, wxT( "Light Green" ) );
178  ADD_COLOR( g_MaskColors, 13, 104, 11, 0.83, wxT( "Saturated Green" ) );
179  ADD_COLOR( g_MaskColors, 181, 19, 21, 0.83, wxT( "Red" ) );
180  ADD_COLOR( g_MaskColors, 210, 40, 14, 0.83, wxT( "Light Red" ) );
181  ADD_COLOR( g_MaskColors, 239, 53, 41, 0.83, wxT( "Red/Orange" ) );
182  ADD_COLOR( g_MaskColors, 2, 59, 162, 0.83, wxT( "Blue" ) );
183  ADD_COLOR( g_MaskColors, 54, 79, 116, 0.83, wxT( "Light Blue 1" ) );
184  ADD_COLOR( g_MaskColors, 61, 85, 130, 0.83, wxT( "Light Blue 2" ) );
185  ADD_COLOR( g_MaskColors, 21, 70, 80, 0.83, wxT( "Green/Blue" ) );
186  ADD_COLOR( g_MaskColors, 11, 11, 11, 0.83, wxT( "Black" ) );
187  ADD_COLOR( g_MaskColors, 245, 245, 245, 0.83, wxT( "White" ) );
188  ADD_COLOR( g_MaskColors, 32, 2, 53, 0.83, wxT( "Purple" ) );
189  ADD_COLOR( g_MaskColors, 119, 31, 91, 0.83, wxT( "Light Purple" ) );
190  ADD_COLOR( g_MaskColors, 194, 195, 0, 0.83, wxT( "Yellow" ) );
191 
192  ADD_COLOR( g_PasteColors, 128, 128, 128, 1.0, wxT( "Grey" ) );
193  ADD_COLOR( g_PasteColors, 90, 90, 90, 1.0, wxT( "Dark Grey" ) );
194  ADD_COLOR( g_PasteColors, 213, 213, 213, 1.0, wxT( "Silver" ) );
195 
196  ADD_COLOR( g_FinishColors, 184, 115, 50, 1.0, wxT( "Copper" ) );
197  ADD_COLOR( g_FinishColors, 178, 156, 0, 1.0, wxT( "Gold" ) );
198  ADD_COLOR( g_FinishColors, 213, 213, 213, 1.0, wxT( "Silver" ) );
199  ADD_COLOR( g_FinishColors, 160, 160, 160, 1.0, wxT( "Tin" ) );
200 
201  ADD_COLOR( g_BoardColors, 51, 43, 22, 0.83, wxT( "FR4 natural, dark" ) );
202  ADD_COLOR( g_BoardColors, 109, 116, 75, 0.83, wxT( "FR4 natural" ) );
203  ADD_COLOR( g_BoardColors, 252, 252, 250, 0.90, wxT( "PTFE natural" ) );
204  ADD_COLOR( g_BoardColors, 205, 130, 0, 0.68, wxT( "Polyimide" ) );
205  ADD_COLOR( g_BoardColors, 92, 17, 6, 0.90, wxT( "Phenolic natural" ) );
206  ADD_COLOR( g_BoardColors, 146, 99, 47, 0.83, wxT( "Brown 1" ) );
207  ADD_COLOR( g_BoardColors, 160, 123, 54, 0.83, wxT( "Brown 2" ) );
208  ADD_COLOR( g_BoardColors, 146, 99, 47, 0.83, wxT( "Brown 3" ) );
209  ADD_COLOR( g_BoardColors, 213, 213, 213, 1.0, wxT( "Aluminum" ) );
210 
211  g_DefaultBackgroundTop = COLOR4D( 0.80, 0.80, 0.90, 1.0 );
212  g_DefaultBackgroundBot = COLOR4D( 0.40, 0.40, 0.50, 1.0 );
213 
214  g_DefaultSilkscreen = COLOR4D( 0.94, 0.94, 0.94, 1.0 );
215  g_DefaultSolderMask = COLOR4D( 0.08, 0.20, 0.14, 0.83 );
216  g_DefaultSolderPaste = COLOR4D( 0.50, 0.50, 0.50, 1.0 );
217  g_DefaultSurfaceFinish = COLOR4D( 0.75, 0.61, 0.23, 1.0 );
218  g_DefaultBoardBody = COLOR4D( 0.43, 0.45, 0.30, 0.90 );
219 
220  g_ColorsLoaded = true;
221  }
222 #undef ADD_COLOR
223 }
224 
225 
227 {
228  destroyLayers();
229 }
230 
231 
233 {
234  wxASSERT( aLayer < PCB_LAYER_ID_COUNT );
235 
236  if( m_board && !m_board->IsLayerEnabled( aLayer ) )
237  return false;
238 
239  // see if layer needs to be shown
240  // check the flags
241  switch( aLayer )
242  {
243  case B_Adhes:
244  case F_Adhes:
245  return GetFlag( FL_ADHESIVE );
246 
247  case B_Paste:
248  case F_Paste:
249  return GetFlag( FL_SOLDERPASTE );
250 
251  case B_SilkS:
252  case F_SilkS:
253  return GetFlag( FL_SILKSCREEN );
254 
255  case B_Mask:
256  case F_Mask:
257  return GetFlag( FL_SOLDERMASK );
258 
259  case Dwgs_User:
260  case Cmts_User:
262  return false;
263 
264  return GetFlag( FL_COMMENTS );
265 
266  case Eco1_User:
267  case Eco2_User:
269  return false;
270 
271  return GetFlag( FL_ECO );
272 
273  case Edge_Cuts:
275  return false;
276 
277  return true;
278 
279  case Margin:
281  return false;
282 
283  return true;
284 
285  case B_Cu:
286  case F_Cu:
288  : true;
289 
290  default:
291  // the layer is an internal copper layer, used the visibility
292  return m_board && m_board->IsLayerVisible( aLayer );
293  }
294 }
295 
296 
298 {
299  wxASSERT( aFlag < FL_LAST );
300 
301  return m_drawFlags[aFlag];
302 }
303 
304 
305 void BOARD_ADAPTER::SetFlag( DISPLAY3D_FLG aFlag, bool aState )
306 {
307  wxASSERT( aFlag < FL_LAST );
308 
309  m_drawFlags[aFlag] = aState;
310 }
311 
312 
314 {
315  if( aFPAttributes & FP_SMD )
317  else if( aFPAttributes & FP_THROUGH_HOLE )
319  else
321 }
322 
323 
324 // !TODO: define the actual copper thickness by user from board stackup
325 #define COPPER_THICKNESS Millimeter2iu( 0.035 ) // for 35 um
326 // The solder mask layer (and silkscreen) thickness
327 #define TECH_LAYER_THICKNESS Millimeter2iu( 0.025 )
328 // The solder paste thickness is chosen bigger than the solder mask layer
329 // to be sure is covers the mask when overlapping.
330 #define SOLDERPASTE_LAYER_THICKNESS Millimeter2iu( 0.04 )
331 
333 {
335  : 0.035 * PCB_IU_PER_MM;
336 }
337 
338 
339 unsigned int BOARD_ADAPTER::GetCircleSegmentCount( float aDiameter3DU ) const
340 {
341  wxASSERT( aDiameter3DU > 0.0f );
342 
343  return GetCircleSegmentCount( (int)( aDiameter3DU / m_biuTo3Dunits ) );
344 }
345 
346 
347 unsigned int BOARD_ADAPTER::GetCircleSegmentCount( int aDiameterBIU ) const
348 {
349  wxASSERT( aDiameterBIU > 0 );
350 
351  return GetArcToSegmentCount( aDiameterBIU / 2, ARC_HIGH_DEF, 360.0 );
352 }
353 
354 
355 void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningReporter )
356 {
357  wxLogTrace( m_logTrace, wxT( "BOARD_ADAPTER::InitSettings" ) );
358 
359  if( aStatusReporter )
360  aStatusReporter->Report( _( "Build board outline" ) );
361 
362  wxString msg;
363 
364  const bool succeedToGetBoardPolygon = createBoardPolygon( &msg );
365 
366  if( aWarningReporter )
367  {
368  if( !succeedToGetBoardPolygon )
369  aWarningReporter->Report( msg, RPT_SEVERITY_WARNING );
370  else
371  aWarningReporter->Report( wxEmptyString );
372  }
373 
374  // Calculates the board bounding box (board outlines + items)
375  // to ensure any item, even outside the board outlines can be seen
376  bool boardEdgesOnly = true;
377 
379  || !succeedToGetBoardPolygon )
380  {
381  boardEdgesOnly = false;
382  }
383 
384  EDA_RECT bbbox;
385 
386  if( m_board )
387  bbbox = m_board->ComputeBoundingBox( boardEdgesOnly );
388 
389  // Gives a non null size to avoid issues in zoom / scale calculations
390  if( ( bbbox.GetWidth() == 0 ) && ( bbbox.GetHeight() == 0 ) )
391  bbbox.Inflate( Millimeter2iu( 10 ) );
392 
393  m_boardSize = bbbox.GetSize();
394  m_boardPos = bbbox.Centre();
395 
396  wxASSERT( (m_boardSize.x > 0) && (m_boardSize.y > 0) );
397 
398  m_boardPos.y = -m_boardPos.y; // The y coord is inverted in 3D viewer
399 
401 
402  // Ensure the board has 2 sides for 3D views, because it is hard to find
403  // a *really* single side board in the true life...
404  if( m_copperLayersCount < 2 )
406 
407  // Calculate the conversion to apply to all positions.
409 
412  : 1.6 * PCB_IU_PER_MM * m_biuTo3Dunits;
413 
414  // !TODO: use value defined by user (currently use default values by ctor
418 
419  // Init Z position of each layer
420  // calculate z position for each copper layer
421  // Zstart = -m_epoxyThickness / 2.0 is the z position of the back (bottom layer) (layer id = 31)
422  // Zstart = +m_epoxyThickness / 2.0 is the z position of the front (top layer) (layer id = 0)
423  // all unused copper layer z position are set to 0
424 
425  // ____==__________==________==______ <- Bottom = +m_epoxyThickness / 2.0,
426  // | | Top = Bottom + m_copperThickness
427  // |__________________________________|
428  // == == == == <- Bottom = -m_epoxyThickness / 2.0,
429  // Top = Bottom - m_copperThickness
430 
431  unsigned int layer;
432 
433  for( layer = 0; layer < m_copperLayersCount; ++layer )
434  {
435  m_layerZcoordBottom[layer] = m_epoxyThickness3DU / 2.0f -
436  (m_epoxyThickness3DU * layer / (m_copperLayersCount - 1) );
437 
438  if( layer < (m_copperLayersCount / 2) )
440  else
442  }
443 
444  #define layerThicknessMargin 1.1
445  const float zpos_offset = m_nonCopperLayerThickness3DU * layerThicknessMargin;
446 
447  // Fill remaining unused copper layers and back layer zpos
448  // with -m_epoxyThickness / 2.0
449  for( ; layer < MAX_CU_LAYERS; layer++ )
450  {
451  m_layerZcoordBottom[layer] = -(m_epoxyThickness3DU / 2.0f);
453  }
454 
455  // This is the top of the copper layer thickness.
456  const float zpos_copperTop_back = m_layerZcoordTop[B_Cu];
457  const float zpos_copperTop_front = m_layerZcoordTop[F_Cu];
458 
459  // calculate z position for each non copper layer
460  // Solder mask and Solder paste have the same Z position
461  for( int layer_id = MAX_CU_LAYERS; layer_id < PCB_LAYER_ID_COUNT; ++layer_id )
462  {
463  float zposTop;
464  float zposBottom;
465 
466  switch( layer_id )
467  {
468  case B_Adhes:
469  zposBottom = zpos_copperTop_back - 2.0f * zpos_offset;
470  zposTop = zposBottom - m_nonCopperLayerThickness3DU;
471  break;
472 
473  case F_Adhes:
474  zposBottom = zpos_copperTop_front + 2.0f * zpos_offset;
475  zposTop = zposBottom + m_nonCopperLayerThickness3DU;
476  break;
477 
478  case B_Mask:
479  zposBottom = zpos_copperTop_back;
480  zposTop = zpos_copperTop_back - m_nonCopperLayerThickness3DU;
481  break;
482 
483  case B_Paste:
484  zposBottom = zpos_copperTop_back;
485  zposTop = zpos_copperTop_back - m_solderPasteLayerThickness3DU;
486  break;
487 
488  case F_Mask:
489  zposBottom = zpos_copperTop_front;
490  zposTop = zpos_copperTop_front + m_nonCopperLayerThickness3DU;
491  break;
492 
493  case F_Paste:
494  zposBottom = zpos_copperTop_front;
495  zposTop = zpos_copperTop_front + m_solderPasteLayerThickness3DU;
496  break;
497 
498  case B_SilkS:
499  zposBottom = zpos_copperTop_back - 1.0f * zpos_offset;
500  zposTop = zposBottom - m_nonCopperLayerThickness3DU;
501  break;
502 
503  case F_SilkS:
504  zposBottom = zpos_copperTop_front + 1.0f * zpos_offset;
505  zposTop = zposBottom + m_nonCopperLayerThickness3DU;
506  break;
507 
508  // !TODO: review
509  default:
510  zposTop = zpos_copperTop_front + (layer_id - MAX_CU_LAYERS + 3.0f) * zpos_offset;
511  zposBottom = zposTop - m_nonCopperLayerThickness3DU;
512  break;
513  }
514 
515  m_layerZcoordTop[layer_id] = zposTop;
516  m_layerZcoordBottom[layer_id] = zposBottom;
517  }
518 
520 
522  0.0f );
523  boardSize /= 2.0f;
524 
525  SFVEC3F boardMin = ( m_boardCenter - boardSize );
526  SFVEC3F boardMax = ( m_boardCenter + boardSize );
527 
528  boardMin.z = m_layerZcoordTop[B_Adhes];
529  boardMax.z = m_layerZcoordTop[F_Adhes];
530 
531  m_boardBoundingBox = BBOX_3D( boardMin, boardMax );
532 
533 #ifdef PRINT_STATISTICS_3D_VIEWER
534  unsigned stats_startCreateBoardPolyTime = GetRunningMicroSecs();
535 #endif
536 
537  if( aStatusReporter )
538  aStatusReporter->Report( _( "Create layers" ) );
539 
540  createLayers( aStatusReporter );
541 
542  COLOR_SETTINGS* colors = Pgm().GetSettingsManager().GetColorSettings();
543 
544  auto to_SFVEC4F =
545  []( const COLOR4D& src )
546  {
547  return SFVEC4F( src.r, src.g, src.b, src.a );
548  };
549 
550  m_BgColorTop = to_SFVEC4F( colors->GetColor( LAYER_3D_BACKGROUND_TOP ) );
551  m_BgColorBot = to_SFVEC4F( colors->GetColor( LAYER_3D_BACKGROUND_BOTTOM ) );
552 
553  m_SolderPasteColor = to_SFVEC4F( colors->GetColor( LAYER_3D_SOLDERPASTE ) );
554 
555  if( m_board && colors->GetUseBoardStackupColors() )
556  {
558 
559  auto findColor =
560  []( const wxString& aColorName, const CUSTOM_COLORS_LIST& aColorSet )
561  {
562  if( aColorName.StartsWith( wxT( "#" ) ) )
563  {
564  return KIGFX::COLOR4D( aColorName );
565  }
566  else
567  {
568  for( const CUSTOM_COLOR_ITEM& color : aColorSet )
569  {
570  if( color.m_ColorName == aColorName )
571  return color.m_Color;
572  }
573  }
574 
575  return KIGFX::COLOR4D();
576  };
577 
582 
583  KIGFX::COLOR4D bodyColor( 0, 0, 0, 0 );
584 
585  for( const BOARD_STACKUP_ITEM* stackupItem : stackup.GetList() )
586  {
587  wxString colorName = stackupItem->GetColor();
588 
589  switch( stackupItem->GetType() )
590  {
592  if( stackupItem->GetBrdLayerId() == F_SilkS )
593  m_SilkScreenColorTop = to_SFVEC4F( findColor( colorName, g_SilkscreenColors ) );
594  else
595  m_SilkScreenColorBot = to_SFVEC4F( findColor( colorName, g_SilkscreenColors ) );
596  break;
597 
599  if( stackupItem->GetBrdLayerId() == F_Mask )
600  m_SolderMaskColorTop = to_SFVEC4F( findColor( colorName, g_MaskColors ) );
601  else
602  m_SolderMaskColorBot = to_SFVEC4F( findColor( colorName, g_MaskColors ) );
603 
604  break;
605 
607  {
608  KIGFX::COLOR4D layerColor = COLOR4D::UNSPECIFIED;
609  const wxString& materialName = stackupItem->GetMaterial();
610 
611  if( materialName.StartsWith( wxT( "FR4" ) ) )
612  {
613  layerColor = findColor( wxT( "FR4 natural" ), g_BoardColors );
614  }
615  else if( materialName.IsSameAs( wxT( "PTFE" ) )
616  || materialName.IsSameAs( wxT( "Teflon" ) ) )
617  {
618  layerColor = findColor( wxT( "PTFE natural" ), g_BoardColors );
619  }
620  else if( materialName.IsSameAs( wxT( "Polyimide" ) )
621  || materialName.IsSameAs( wxT( "Kapton" ) ) )
622  {
623  layerColor = findColor( wxT( "Polyimide" ), g_BoardColors );
624  }
625  else if( materialName.IsSameAs( wxT( "Al" ) ) )
626  {
627  layerColor = findColor( wxT( "Aluminum" ), g_BoardColors );
628  }
629  else // A default color value for unknown dielectric material
630  // (i.e. an exotic name entered by hand)
631  {
632  layerColor = findColor( wxT( "FR4 natural" ), g_BoardColors );
633  }
634 
635  if( bodyColor == COLOR4D( 0, 0, 0, 0 ) )
636  bodyColor = layerColor;
637  else
638  bodyColor = bodyColor.Mix( layerColor, 1.0 - layerColor.a );
639 
640  bodyColor.a += ( 1.0 - bodyColor.a ) * layerColor.a / 2;
641  break;
642  }
643 
644  default:
645  break;
646  }
647  }
648 
649  if( bodyColor != COLOR4D( 0, 0, 0, 0 ) )
650  m_BoardBodyColor = to_SFVEC4F( bodyColor );
651  else
652  m_BoardBodyColor = to_SFVEC4F( g_DefaultBoardBody );
653 
654  const wxString& finishName = stackup.m_FinishType;
655 
656  if( finishName.EndsWith( wxT( "OSP" ) ) )
657  {
658  m_CopperColor = to_SFVEC4F( findColor( wxT( "Copper" ), g_FinishColors ) );
659  }
660  else if( finishName.EndsWith( wxT( "IG" ) )
661  || finishName.EndsWith( wxT( "gold" ) ) )
662  {
663  m_CopperColor = to_SFVEC4F( findColor( wxT( "Gold" ), g_FinishColors ) );
664  }
665  else if( finishName.StartsWith( wxT( "HAL" ) )
666  || finishName.StartsWith( wxT( "HASL" ) )
667  || finishName.EndsWith( wxT( "tin" ) )
668  || finishName.EndsWith( wxT( "nickel" ) ) )
669  {
670  m_CopperColor = to_SFVEC4F( findColor( wxT( "Tin" ), g_FinishColors ) );
671  }
672  else if( finishName.EndsWith( wxT( "silver" ) ) )
673  {
674  m_CopperColor = to_SFVEC4F( findColor( wxT( "Silver" ), g_FinishColors ) );
675  }
676  else
677  {
678  m_CopperColor = to_SFVEC4F( g_DefaultSurfaceFinish );
679  }
680  }
681  else
682  {
683  m_SilkScreenColorBot = to_SFVEC4F( colors->GetColor( LAYER_3D_SILKSCREEN_BOTTOM ) );
684  m_SilkScreenColorTop = to_SFVEC4F( colors->GetColor( LAYER_3D_SILKSCREEN_TOP ) );
685  m_SolderMaskColorBot = to_SFVEC4F( colors->GetColor( LAYER_3D_SOLDERMASK_BOTTOM ) );
686  m_SolderMaskColorTop = to_SFVEC4F( colors->GetColor( LAYER_3D_SOLDERMASK_TOP ) );
687  m_CopperColor = to_SFVEC4F( colors->GetColor( LAYER_3D_COPPER ) );
688  m_BoardBodyColor = to_SFVEC4F( colors->GetColor( LAYER_3D_BOARD ) );
689  }
690 }
691 
692 
693 extern bool BuildFootprintPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
694  int aErrorMax, int aChainingEpsilon,
695  OUTLINE_ERROR_HANDLER* aErrorHandler = nullptr );
696 
697 
698 bool BOARD_ADAPTER::createBoardPolygon( wxString* aErrorMsg )
699 {
701 
702  if( !m_board )
703  return false;
704 
705  bool success;
706 
707  if( m_board->IsFootprintHolder() )
708  {
709  if( !m_board->GetFirstFootprint() )
710  {
711  if( aErrorMsg )
712  *aErrorMsg = _( "No footprint loaded." );
713 
714  return false;
715  }
716 
717  int chainingEpsilon = Millimeter2iu( 0.02 ); // max dist from one endPt to next startPt
718 
721  chainingEpsilon );
722 
723  // Make polygon strictly simple to avoid issues (especially in 3D viewer)
725 
726  if( !success && aErrorMsg )
727  {
728  *aErrorMsg = _( "Footprint outline is missing or malformed. Run Footprint Checker for "
729  "a full analysis." );
730  }
731  }
732  else
733  {
735 
736  if( !success && aErrorMsg )
737  *aErrorMsg = _( "Board outline is missing or malformed. Run DRC for a full analysis." );
738  }
739 
740  return success;
741 }
742 
743 
744 float BOARD_ADAPTER::GetFootprintZPos( bool aIsFlipped ) const
745 {
746  if( aIsFlipped )
747  {
748  if( GetFlag( FL_SOLDERPASTE ) )
750  else
752  }
753  else
754  {
755  if( GetFlag( FL_SOLDERPASTE ) )
756  return m_layerZcoordTop[F_SilkS];
757  else
758  return m_layerZcoordTop[F_Paste];
759  }
760 }
761 
762 
764 {
765  wxASSERT( aLayerId < PCB_LAYER_ID_COUNT );
766 
767  const COLOR4D color = m_colors->GetColor( aLayerId );
768 
769  return SFVEC4F( color.r, color.g, color.b, color.a );
770 }
771 
772 
774 {
775  return GetColor( m_colors->GetColor( aItemId ) );
776 }
777 
778 
780 {
781  return SFVEC4F( aColor.r, aColor.g, aColor.b, aColor.a );
782 }
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
BVH_CONTAINER_2D * m_platedPadsFront
static bool g_ColorsLoaded
int m_RtShadowSampleCount
Defines math related functions.
#define TECH_LAYER_THICKNESS
SFVEC4F m_SilkScreenColorBot
in realistic mode: SilkScreen color ( bot )
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:1835
bool GetUseBoardStackupColors() const
bool BuildFootprintPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, int aErrorMax, int aChainingEpsilon, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
This function is used to extract a board outline for a footprint view.
SHAPE_POLY_SET * m_backPlatedPadPolys
Polygon contours for hole outer diameters for each layer.
float m_solderPasteLayerThickness3DU
Number of tracks in the board.
BVH_CONTAINER_2D m_throughHoleIds
List of through hole vias with the radius of the hole inflated with the copper thickness.
Manage layers needed to make a physical board.
bool IsFootprintShown(FOOTPRINT_ATTR_T aFPAttributes) const
Test if footprint should be displayed in relation to attributes and the flags.
float m_nonCopperLayerThickness3DU
solder paste layers thickness in 3D units.
SHAPE_POLY_SET * m_frontPlatedPadPolys
wxString m_FinishType
The name of external copper finish.
Manage a bounding box defined by two SFVEC3F min max points.
Definition: bbox_3d.h:41
SFVEC4F GetColor(const COLOR4D &aColor) const
float m_averageHoleDiameter
glm::vec4 SFVEC4F
Definition: xv3d_types.h:46
int GetHolePlatingThickness() const
Pad & via drills are finish size.
static KIGFX::COLOR4D g_DefaultSilkscreen
void SetFlag(DISPLAY3D_FLG aFlag, bool aState)
Set the status of a flag.
COLOR_SETTINGS * m_colors
SFVEC4F m_SolderMaskColorTop
in realistic mode: solder mask color ( top )
int color
Definition: DXF_plotter.cpp:57
int GetWidth() const
Definition: eda_rect.h:118
static KIGFX::COLOR4D g_DefaultSurfaceFinish
BVH_CONTAINER_2D m_throughHoleOds
List of plated through hole annular rings.
void InitSettings(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
Function to be called by the render when it need to reload the settings for the board.
SFVEC4F m_BoardBodyColor
in realistic mode: FR4 board color
SFVEC4F m_SolderPasteColor
in realistic mode: solder paste color
double g
Green component.
Definition: color4d.h:385
#define layerThicknessMargin
float m_averageTrackWidth
Number of through hole vias in the board.
A class to handle a custom color (predefined color) for the color picker dialog.
SFVEC4F m_SolderMaskColorBot
in realistic mode: solder mask color ( bot )
wxPoint m_boardPos
Board center position in board internal units.
bool IsFootprintHolder() const
Find out if the board is being used to hold a single footprint for editing/viewing.
Definition: board.h:222
std::vector< CUSTOM_COLOR_ITEM > CUSTOM_COLORS_LIST
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:70
std::array< float, PCB_LAYER_ID_COUNT > m_layerZcoordBottom
Copper thickness in 3D units.
bool IsLayerEnabled(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
Definition: board.cpp:493
float m_epoxyThickness3DU
Non copper layers thickness in 3D units.
static CUSTOM_COLORS_LIST g_BoardColors
float m_copperThickness3DU
Epoxy thickness in 3D units.
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
static KIGFX::COLOR4D g_DefaultBackgroundBot
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
float m_RtSpreadRefractions
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
FOOTPRINT_ATTR_T
The set of attributes allowed within a FOOTPRINT, using FOOTPRINT::SetAttributes() and FOOTPRINT::Get...
Definition: footprint.h:66
double b
Blue component.
Definition: color4d.h:386
static CUSTOM_COLORS_LIST g_FinishColors
static CUSTOM_COLORS_LIST g_PasteColors
bool Is3dLayerEnabled(PCB_LAYER_ID aLayer) const
Check if a layer is enabled.
static KIGFX::COLOR4D g_DefaultSolderMask
BOARD_STACKUP & GetStackupDescriptor()
double a
Alpha component.
Definition: color4d.h:387
static KIGFX::COLOR4D g_DefaultBoardBody
int m_RtRecursiveReflectionCount
float m_RtSpreadReflections
SFVEC4F m_BgColorTop
background top color
unsigned int m_trackCount
Track average width.
std::vector< bool > m_drawFlags
std::array< float, PCB_LAYER_ID_COUNT > m_layerZcoordTop
Bottom (Start) Z position of each layer in 3D units.
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:318
#define ADD_COLOR(list, r, g, b, a, name)
#define MAX_CU_LAYERS
Definition: layer_ids.h:147
GRID3D_TYPE m_gridType
SHAPE_POLY_SET m_board_poly
Board outline polygon.
PGM_BASE * PgmOrNull()
similar to PGM_BASE& Pgm(), but return a reference that can be nullptr when running a shared lib from...
Definition: cvpcb.cpp:125
BVH_CONTAINER_2D * m_platedPadsBack
The holes per each layer.
BBOX_3D m_boardBoundingBox
3D bounding box of the board in 3D units.
wxString NotSpecifiedPrm()
Represent a set of closed polygons.
constexpr double PCB_IU_PER_MM
Use all material properties from model file.
static KIGFX::COLOR4D g_DefaultBackgroundTop
double m_biuTo3Dunits
Top (End) Z position of each layer in 3D units.
#define _(s)
SFVEC4F m_BgColorBot
background bottom color
a few functions useful in geometry calculations.
void Simplify(POLYGON_MODE aFastMode)
BVH_CONTAINER_2D m_throughHoleAnnularRings
List of through hole inner diameters.
unsigned int m_viaCount
Computed average diameter of the via holes in 3D units.
int m_RtRecursiveRefractionCount
Manage one layer needed to make a physical board.
Definition: board_stackup.h:89
int m_RtRefractionSampleCount
SFVEC4F GetItemColor(int aItemId) const
Get the technical color of a layer.
void createLayers(REPORTER *aStatusReporter)
int GetHeight() const
Definition: eda_rect.h:119
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
#define SOLDERPASTE_LAYER_THICKNESS
float GetFootprintZPos(bool aIsFlipped) const
Get the position of the footprint in 3d integer units considering if it is flipped or not.
DISPLAY3D_FLG
Flags used in rendering options.
Definition: 3d_enums.h:34
RENDER_ENGINE m_renderEngine
COLOR4D GetColor(int aLayer) const
wxSize m_boardSize
Board size in board internal units.
bool IsLayerVisible(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
Definition: board.cpp:473
SFVEC4F GetLayerColor(PCB_LAYER_ID aLayerId) const
Get the technical color of a layer.
see class PGM_BASE
MATERIAL_MODE m_materialMode
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this class.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:191
unsigned GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
static KIGFX::COLOR4D g_DefaultSolderPaste
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
unsigned int m_copperLayersCount
Scale factor to convert board internal units to 3D units normalized between -1.0 and 1....
bool createBoardPolygon(wxString *aErrorMsg)
Create the board outline polygon.
SFVEC4F m_CopperColor
in realistic mode: copper color
Definition: layer_ids.h:71
int GetCopperLayerCount() const
Definition: board.cpp:455
Handle the component boundary box.
Definition: eda_rect.h:42
wxPoint Centre() const
Definition: eda_rect.h:64
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1085
Defines math related functions.
Color settings are a bit different than most of the settings objects in that there can be more than o...
const std::function< void(const wxString &msg, BOARD_ITEM *itemA, BOARD_ITEM *itemB, const wxPoint &pt)> OUTLINE_ERROR_HANDLER
SFVEC4F m_SilkScreenColorTop
in realistic mode: SilkScreen color ( top )
static CUSTOM_COLORS_LIST g_MaskColors
ANTIALIASING_MODE m_antiAliasingMode
static CUSTOM_COLORS_LIST g_SilkscreenColors
SFVEC3F m_boardCenter
3D center position of the board in 3D units.
#define COPPER_THICKNESS
double r
Red component.
Definition: color4d.h:384
float m_averageViaHoleDiameter
Number of holes in the board.
COLOR4D Mix(const COLOR4D &aColor, double aFactor) const
Return a color that is mixed with the input by a factor.
Definition: color4d.h:305
float m_RtSpreadShadows
static constexpr int Millimeter2iu(double mm)
void Clear() override
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
Definition: board_adapter.h:62
void Reset()
Reset the bounding box to zero and de-initialize it.
Definition: bbox_3d.cpp:95
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
unsigned int GetCircleSegmentCount(float aDiameter3DU) const
int m_RtReflectionSampleCount
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Inflate the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:364
unsigned int m_holeCount
Computed average diameter of the holes in 3D units.
const wxSize GetSize() const
Definition: eda_rect.h:100
int GetHolePlatingThickness() const noexcept
Get the current copper layer thickness.
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103