KiCad PCB EDA Suite
create_layer_items.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-2016 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 
33 #include "cinfo3d_visu.h"
34 #include "../3d_rendering/3d_render_raytracing/shapes2D/cring2d.h"
35 #include "../3d_rendering/3d_render_raytracing/shapes2D/cfilledcircle2d.h"
36 #include "../3d_rendering/3d_render_raytracing/shapes2D/croundsegment2d.h"
37 #include "../3d_rendering/3d_render_raytracing/shapes2D/cpolygon4pts2d.h"
38 #include "../3d_rendering/3d_render_raytracing/shapes2D/cpolygon2d.h"
39 #include "../3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.h"
40 #include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h"
41 #include "../3d_rendering/3d_render_raytracing/shapes3D/ccylinder.h"
42 #include "../3d_rendering/3d_render_raytracing/shapes3D/clayeritem.h"
43 #include <openmp_mutex.h>
44 #include <class_board.h>
45 #include <class_module.h>
46 #include <class_pad.h>
47 #include <class_pcb_text.h>
48 #include <class_edge_mod.h>
49 #include <class_zone.h>
50 #include <class_text_mod.h>
52 #include <trigo.h>
53 #include <drawtxt.h>
54 #include <utility>
55 #include <vector>
56 
57 
58 
59 // These variables are parameters used in addTextSegmToContainer.
60 // But addTextSegmToContainer is a call-back function,
61 // so we cannot send them as arguments.
62 static int s_textWidth;
64 static float s_biuTo3Dunits;
65 static const CBBOX2D *s_boardBBox3DU = NULL;
66 static const BOARD_ITEM *s_boardItem = NULL;
67 
68 // This is a call back function, used by DrawGraphicText to draw the 3D text shape:
69 void addTextSegmToContainer( int x0, int y0, int xf, int yf )
70 {
71  wxASSERT( s_boardBBox3DU != NULL );
72  wxASSERT( s_dstcontainer != NULL );
73 
74  const SFVEC2F start3DU( x0 * s_biuTo3Dunits, -y0 * s_biuTo3Dunits );
75  const SFVEC2F end3DU ( xf * s_biuTo3Dunits, -yf * s_biuTo3Dunits );
76 
77  if( Is_segment_a_circle( start3DU, end3DU ) )
78  s_dstcontainer->Add( new CFILLEDCIRCLE2D( start3DU,
79  s_textWidth * s_biuTo3Dunits,
80  *s_boardItem) );
81  else
82  s_dstcontainer->Add( new CROUNDSEGMENT2D( start3DU,
83  end3DU,
84  s_textWidth * s_biuTo3Dunits,
85  *s_boardItem ) );
86 }
87 
88 
89 // Based on
90 // void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet
91 // board_items_to_polygon_shape_transform.cpp
93  CGENERICCONTAINER2D *aDstContainer,
94  LAYER_ID aLayerId,
95  int aClearanceValue )
96 {
97  wxSize size = aTextPCB->GetTextSize();
98 
99  if( aTextPCB->IsMirrored() )
100  size.x = -size.x;
101 
102  s_boardItem = (const BOARD_ITEM *)&aTextPCB;
103  s_dstcontainer = aDstContainer;
104  s_textWidth = aTextPCB->GetThickness() + ( 2 * aClearanceValue );
106  s_boardBBox3DU = &m_board2dBBox3DU;
107 
108  // not actually used, but needed by DrawGraphicText
109  const COLOR4D dummy_color = COLOR4D::BLACK;
110 
111  if( aTextPCB->IsMultilineAllowed() )
112  {
113  wxArrayString strings_list;
114  wxStringSplit( aTextPCB->GetShownText(), strings_list, '\n' );
115  std::vector<wxPoint> positions;
116  positions.reserve( strings_list.Count() );
117  aTextPCB->GetPositionsOfLinesOfMultilineText( positions,
118  strings_list.Count() );
119 
120  for( unsigned ii = 0; ii < strings_list.Count(); ++ii )
121  {
122  wxString txt = strings_list.Item( ii );
123 
124  DrawGraphicText( NULL, NULL, positions[ii], dummy_color,
125  txt, aTextPCB->GetTextAngle(), size,
126  aTextPCB->GetHorizJustify(), aTextPCB->GetVertJustify(),
127  aTextPCB->GetThickness(), aTextPCB->IsItalic(),
128  true, addTextSegmToContainer );
129  }
130  }
131  else
132  {
133  DrawGraphicText( NULL, NULL, aTextPCB->GetTextPos(), dummy_color,
134  aTextPCB->GetShownText(), aTextPCB->GetTextAngle(), size,
135  aTextPCB->GetHorizJustify(), aTextPCB->GetVertJustify(),
136  aTextPCB->GetThickness(), aTextPCB->IsItalic(),
137  true, addTextSegmToContainer );
138  }
139 }
140 
141 
143  CGENERICCONTAINER2D *aDstContainer,
144  LAYER_ID aLayerId,
145  int aClearanceValue )
146 {
147  AddShapeWithClearanceToContainer(&aDimension->Text(), aDstContainer, aLayerId, aClearanceValue);
148 
149  const int linewidth = aDimension->GetWidth() + (2 * aClearanceValue);
150 
151  std::pair<wxPoint const *, wxPoint const *> segs[] = {
152  {&aDimension->m_crossBarO, &aDimension->m_crossBarF},
153  {&aDimension->m_featureLineGO, &aDimension->m_featureLineGF},
154  {&aDimension->m_featureLineDO, &aDimension->m_featureLineDF},
155  {&aDimension->m_crossBarF, &aDimension->m_arrowD1F},
156  {&aDimension->m_crossBarF, &aDimension->m_arrowD2F},
157  {&aDimension->m_crossBarO, &aDimension->m_arrowG1F},
158  {&aDimension->m_crossBarO, &aDimension->m_arrowG2F}};
159 
160  for( auto const & ii : segs )
161  {
162  const SFVEC2F start3DU( ii.first->x * m_biuTo3Dunits,
163  -ii.first->y * m_biuTo3Dunits );
164 
165  const SFVEC2F end3DU ( ii.second->x * m_biuTo3Dunits,
166  -ii.second->y * m_biuTo3Dunits );
167 
168  aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
169  end3DU,
170  linewidth * m_biuTo3Dunits,
171  *aDimension ) );
172  }
173 }
174 
175 
176 // Based on
177 // void MODULE::TransformGraphicShapesWithClearanceToPolygonSet
178 // board_items_to_polygon_shape_transform.cpp#L204
180  CGENERICCONTAINER2D *aDstContainer,
181  LAYER_ID aLayerId,
182  int aInflateValue )
183 {
184  std::vector<TEXTE_MODULE *> texts; // List of TEXTE_MODULE to convert
185  EDGE_MODULE* outline;
186 
187  for( EDA_ITEM* item = aModule->GraphicalItems();
188  item != NULL;
189  item = item->Next() )
190  {
191  switch( item->Type() )
192  {
193  case PCB_MODULE_TEXT_T:
194  {
195  TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( item );
196 
197  if( text->GetLayer() == aLayerId && text->IsVisible() )
198  texts.push_back( text );
199  }
200  break;
201 
202 
203  case PCB_MODULE_EDGE_T:
204  {
205  outline = (EDGE_MODULE*) item;
206 
207  if( outline->GetLayer() != aLayerId )
208  break;
209 
211  aDstContainer,
212  aLayerId, 0 );
213  }
214  break;
215 
216  default:
217  break;
218  }
219  }
220 
221  // Convert texts sur modules
222  if( aModule->Reference().GetLayer() == aLayerId && aModule->Reference().IsVisible() )
223  texts.push_back( &aModule->Reference() );
224 
225  if( aModule->Value().GetLayer() == aLayerId && aModule->Value().IsVisible() )
226  texts.push_back( &aModule->Value() );
227 
228  s_boardItem = (const BOARD_ITEM *)&aModule->Value();
229  s_dstcontainer = aDstContainer;
231  s_boardBBox3DU = &m_board2dBBox3DU;
232 
233  for( unsigned ii = 0; ii < texts.size(); ++ii )
234  {
235  TEXTE_MODULE *textmod = texts[ii];
236  s_textWidth = textmod->GetThickness() + ( 2 * aInflateValue );
237  wxSize size = textmod->GetTextSize();
238 
239  if( textmod->IsMirrored() )
240  size.x = -size.x;
241 
242  DrawGraphicText( NULL, NULL, textmod->GetTextPos(), BLACK,
243  textmod->GetShownText(), textmod->GetDrawRotation(), size,
244  textmod->GetHorizJustify(), textmod->GetVertJustify(),
245  textmod->GetThickness(), textmod->IsItalic(),
246  true, addTextSegmToContainer );
247  }
248 }
249 
250 
252  int aClearanceValue ) const
253 {
254  SFVEC2F start3DU( aTrack->GetStart().x * m_biuTo3Dunits,
255  -aTrack->GetStart().y * m_biuTo3Dunits ); // y coord is inverted
256 
257  switch( aTrack->Type() )
258  {
259  case PCB_VIA_T:
260  {
261  const float radius = ( ( aTrack->GetWidth() / 2 ) + aClearanceValue ) * m_biuTo3Dunits;
262 
263  return new CFILLEDCIRCLE2D( start3DU, radius, *aTrack );
264  }
265  break;
266 
267  default:
268  {
269  wxASSERT( aTrack->Type() == PCB_TRACE_T );
270 
271  SFVEC2F end3DU ( aTrack->GetEnd().x * m_biuTo3Dunits,
272  -aTrack->GetEnd().y * m_biuTo3Dunits );
273 
274  // Cannot add segments that have the same start and end point
275  if( Is_segment_a_circle( start3DU, end3DU ) )
276  {
277  const float radius = ((aTrack->GetWidth() / 2) + aClearanceValue) * m_biuTo3Dunits;
278 
279  return new CFILLEDCIRCLE2D( start3DU, radius, *aTrack );
280  }
281  else
282  {
283  const float width = (aTrack->GetWidth() + 2 * aClearanceValue ) * m_biuTo3Dunits;
284 
285  return new CROUNDSEGMENT2D( start3DU, end3DU, width, *aTrack );
286  }
287  }
288  break;
289  }
290 
291  return NULL;
292 }
293 
294 
295 // Based on:
296 // void D_PAD:: TransformShapeWithClearanceToPolygon(
297 // board_items_to_polygon_shape_transform.cpp
299  CGENERICCONTAINER2D *aDstContainer,
300  int aClearanceValue ) const
301 {
302  const int dx = (aPad->GetSize().x / 2) + aClearanceValue;
303  const int dy = (aPad->GetSize().y / 2) + aClearanceValue;
304 
305  if( !dx || !dy )
306  {
307  wxLogTrace( m_logTrace,
308  wxT( "CINFO3D_VISU::createNewPadWithClearance - found an invalid pad" ) );
309 
310  return;
311  }
312 
313  wxPoint PadShapePos = aPad->ShapePos(); // Note: for pad having a shape offset,
314  // the pad position is NOT the shape position
315 
316  switch( aPad->GetShape() )
317  {
318  case PAD_SHAPE_CIRCLE:
319  {
320  const float radius = dx * m_biuTo3Dunits;
321 
322  const SFVEC2F center( PadShapePos.x * m_biuTo3Dunits,
323  -PadShapePos.y * m_biuTo3Dunits );
324 
325  aDstContainer->Add( new CFILLEDCIRCLE2D( center, radius, *aPad ) );
326  }
327  break;
328 
329  case PAD_SHAPE_OVAL:
330  {
331  if( abs( dx - dy ) == 0 )
332  {
333  // The segment object cannot store start and end the same position,
334  // so add a circle instead
335  const float radius = dx * m_biuTo3Dunits;
336 
337  const SFVEC2F center( PadShapePos.x * m_biuTo3Dunits,
338  -PadShapePos.y * m_biuTo3Dunits );
339 
340  aDstContainer->Add( new CFILLEDCIRCLE2D( center, radius, *aPad ) );
341  }
342  else
343  {
344  // An oval pad has the same shape as a segment with rounded ends
345 
346  int iwidth;
347  wxPoint shape_offset = wxPoint( 0, 0 );
348 
349  if( dy > dx ) // Oval pad X/Y ratio for choosing translation axis
350  {
351  shape_offset.y = dy - dx;
352  iwidth = dx * 2;
353  }
354  else //if( dy <= dx )
355  {
356  shape_offset.x = dy - dx;
357  iwidth = dy * 2;
358  }
359 
360  RotatePoint( &shape_offset, aPad->GetOrientation() );
361 
362  const wxPoint start = PadShapePos - shape_offset;
363  const wxPoint end = PadShapePos + shape_offset;
364 
365  const SFVEC2F start3DU( start.x * m_biuTo3Dunits, -start.y * m_biuTo3Dunits );
366  const SFVEC2F end3DU ( end.x * m_biuTo3Dunits, -end.y * m_biuTo3Dunits );
367 
368  // Cannot add segments that have the same start and end point
369  if( Is_segment_a_circle( start3DU, end3DU ) )
370  {
371  aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
372  (iwidth / 2) * m_biuTo3Dunits,
373  *aPad ) );
374  }
375  else
376  {
377  aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
378  end3DU,
379  iwidth * m_biuTo3Dunits,
380  *aPad ) );
381  }
382  }
383  }
384  break;
385 
386  case PAD_SHAPE_TRAPEZOID:
387  case PAD_SHAPE_RECT:
388  {
389  // https://github.com/KiCad/kicad-source-mirror/blob/0cab3e47ad8097db7b898b3cef2cf9b235318ca3/pcbnew/board_items_to_polygon_shape_transform.cpp#L613
390 
391  wxPoint corners[4];
392  aPad->BuildPadPolygon( corners, wxSize( 0, 0), aPad->GetOrientation() );
393 
394  SFVEC2F corners3DU[4];
395 
396  // Note: for pad having a shape offset,
397  // the pad position is NOT the shape position
398  for( unsigned int ii = 0; ii < 4; ++ii )
399  {
400  corners[ii] += aPad->ShapePos(); // Shift origin to position
401 
402  corners3DU[ii] = SFVEC2F( corners[ii].x * m_biuTo3Dunits,
403  -corners[ii].y * m_biuTo3Dunits );
404  }
405 
406 
407  // Learn more at:
408  // https://lists.launchpad.net/kicad-developers/msg18729.html
409 
410  // Add the PAD polygon
411  aDstContainer->Add( new CPOLYGON4PTS2D( corners3DU[0],
412  corners3DU[1],
413  corners3DU[2],
414  corners3DU[3],
415  *aPad ) );
416 
417  // Add the PAD contours
418  // !TODO: check the corners because it cannot add
419  // roundsegments that are in the same start and end position
420  aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[0],
421  corners3DU[1],
422  aClearanceValue * 2.0f * m_biuTo3Dunits,
423  *aPad ) );
424 
425  aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[1],
426  corners3DU[2],
427  aClearanceValue * 2.0f * m_biuTo3Dunits,
428  *aPad ) );
429 
430  aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[2],
431  corners3DU[3],
432  aClearanceValue * 2.0f * m_biuTo3Dunits,
433  *aPad ) );
434 
435  aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[3],
436  corners3DU[0],
437  aClearanceValue * 2.0f * m_biuTo3Dunits,
438  *aPad ) );
439  }
440  break;
441 
442  case PAD_SHAPE_ROUNDRECT:
443  {
444  const int pad_radius = aPad->GetRoundRectCornerRadius();
445  const int rounding_radius = pad_radius + aClearanceValue;
446 
447  wxSize shapesize( aPad->GetSize() );
448  shapesize.x += aClearanceValue * 2;
449  shapesize.y += aClearanceValue * 2;
450 
451  wxPoint corners[4];
452 
453  GetRoundRectCornerCenters( corners,
454  rounding_radius,
455  PadShapePos,
456  shapesize,
457  aPad->GetOrientation() );
458 
459  SFVEC2F corners3DU[4];
460 
461  for( unsigned int ii = 0; ii < 4; ++ii )
462  corners3DU[ii] = SFVEC2F( corners[ii].x * m_biuTo3Dunits,
463  -corners[ii].y * m_biuTo3Dunits );
464 
465  // Add the PAD polygon (For some reason the corners need
466  // to be inverted to display with the correctly orientation)
467  aDstContainer->Add( new CPOLYGON4PTS2D( corners3DU[0],
468  corners3DU[3],
469  corners3DU[2],
470  corners3DU[1],
471  *aPad ) );
472 
473  // Add the PAD contours
474  // !TODO: check the corners because it cannot add
475  // roundsegments that are in the same start and end position
476  aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[0],
477  corners3DU[1],
478  rounding_radius * 2.0f * m_biuTo3Dunits,
479  *aPad ) );
480 
481  aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[1],
482  corners3DU[2],
483  rounding_radius * 2.0f * m_biuTo3Dunits,
484  *aPad ) );
485 
486  aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[2],
487  corners3DU[3],
488  rounding_radius * 2.0f * m_biuTo3Dunits,
489  *aPad ) );
490 
491  aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[3],
492  corners3DU[0],
493  rounding_radius * 2.0f * m_biuTo3Dunits,
494  *aPad ) );
495  }
496  break;
497 
498  default:
499  wxFAIL_MSG( "CINFO3D_VISU::createNewPadWithClearance - a pad shape type is not implemented" );
500  break;
501  }
502 }
503 
504 
505 // Based on:
506 // BuildPadDrillShapePolygon
507 // board_items_to_polygon_shape_transform.cpp
508 COBJECT2D *CINFO3D_VISU::createNewPadDrill( const D_PAD* aPad, int aInflateValue )
509 {
510  wxSize drillSize = aPad->GetDrillSize();
511 
512  if( !drillSize.x || !drillSize.y )
513  {
514  wxLogTrace( m_logTrace, wxT( "CINFO3D_VISU::createNewPadDrill - found an invalid pad" ) );
515  return NULL;
516  }
517 
518  if( drillSize.x == drillSize.y ) // usual round hole
519  {
520  const int radius = (drillSize.x / 2) + aInflateValue;
521 
522  const SFVEC2F center( aPad->GetPosition().x * m_biuTo3Dunits,
523  -aPad->GetPosition().y * m_biuTo3Dunits );
524 
525  return new CFILLEDCIRCLE2D( center, radius * m_biuTo3Dunits, *aPad );
526 
527  }
528  else // Oblong hole
529  {
530  wxPoint start, end;
531  int width;
532 
533  aPad->GetOblongDrillGeometry( start, end, width );
534 
535  width += aInflateValue * 2;
536  start += aPad->GetPosition();
537  end += aPad->GetPosition();
538 
539  SFVEC2F start3DU( start.x * m_biuTo3Dunits,
540  -start.y * m_biuTo3Dunits );
541 
542  SFVEC2F end3DU ( end.x * m_biuTo3Dunits,
543  -end.y * m_biuTo3Dunits );
544 
545  if( Is_segment_a_circle( start3DU, end3DU ) )
546  {
547  return new CFILLEDCIRCLE2D( start3DU, (width / 2) * m_biuTo3Dunits, *aPad );
548  }
549  else
550  {
551  return new CROUNDSEGMENT2D( start3DU, end3DU, width * m_biuTo3Dunits, *aPad );
552  }
553  }
554 
555  return NULL;
556 }
557 
558 
559 // This function pretends to be like the
560 // void D_PAD::BuildPadShapePolygon(
561 // board_items_to_polygon_shape_transform.cpp
563  CGENERICCONTAINER2D *aDstContainer,
564  const wxSize &aInflateValue ) const
565 {
566  switch( aPad->GetShape() )
567  {
568  default:
569  wxFAIL_MSG( wxT( "CINFO3D_VISU::createNewPad: found a not implemented pad shape (new shape?)" ) );
570  break;
571 
572  case PAD_SHAPE_CIRCLE:
573  case PAD_SHAPE_OVAL:
574  case PAD_SHAPE_ROUNDRECT:
575  createNewPadWithClearance( aPad, aDstContainer, aInflateValue.x );
576  break;
577 
578  case PAD_SHAPE_TRAPEZOID:
579  case PAD_SHAPE_RECT:
580  wxPoint corners[4];
581  aPad->BuildPadPolygon( corners, aInflateValue, aPad->GetOrientation() );
582 
583  // Note: for pad having a shape offset,
584  // the pad position is NOT the shape position
585  for( unsigned int ii = 0; ii < 4; ++ii )
586  corners[ii] += aPad->ShapePos(); // Shift origin to position
587 
588  aDstContainer->Add( new CPOLYGON4PTS2D(
589  SFVEC2F( corners[0].x * m_biuTo3Dunits,
590  -corners[0].y * m_biuTo3Dunits ),
591  SFVEC2F( corners[1].x * m_biuTo3Dunits,
592  -corners[1].y * m_biuTo3Dunits ),
593  SFVEC2F( corners[2].x * m_biuTo3Dunits,
594  -corners[2].y * m_biuTo3Dunits ),
595  SFVEC2F( corners[3].x * m_biuTo3Dunits,
596  -corners[3].y * m_biuTo3Dunits ),
597  *aPad ) );
598 
599  break;
600  }
601 }
602 
603 
605  CGENERICCONTAINER2D *aDstContainer,
606  LAYER_ID aLayerId,
607  int aInflateValue,
608  bool aSkipNPTHPadsWihNoCopper )
609 {
610  const D_PAD* pad = aModule->Pads();
611 
612  wxSize margin;
613 
614  for( ; pad != NULL; pad = pad->Next() )
615  {
616  if( !pad->IsOnLayer( aLayerId ) )
617  continue;
618 
619  // NPTH pads are not drawn on layers if the
620  // shape size and pos is the same as their hole:
621  if( aSkipNPTHPadsWihNoCopper && (pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED) )
622  {
623  if( (pad->GetDrillSize() == pad->GetSize()) &&
624  (pad->GetOffset() == wxPoint( 0, 0 )) )
625  {
626  switch( pad->GetShape() )
627  {
628  case PAD_SHAPE_CIRCLE:
629  if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
630  continue;
631  break;
632 
633  case PAD_SHAPE_OVAL:
634  if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
635  continue;
636  break;
637 
638  default:
639  break;
640  }
641  }
642  }
643 
644  switch( aLayerId )
645  {
646  case F_Mask:
647  case B_Mask:
648  margin.x = margin.y = pad->GetSolderMaskMargin() + aInflateValue;
649  break;
650 
651  case F_Paste:
652  case B_Paste:
653  margin = pad->GetSolderPasteMargin();
654  margin.x += aInflateValue;
655  margin.y += aInflateValue;
656  break;
657 
658  default:
659  margin.x = margin.y = aInflateValue;
660  break;
661  }
662 
663  createNewPad( pad, aDstContainer, margin );
664  }
665 }
666 
667 // based on TransformArcToPolygon function from
668 // common/convert_basic_shapes_to_polygon.cpp
670  const wxPoint &aStart,
671  double aArcAngle,
672  int aCircleToSegmentsCount,
673  int aWidth,
674  CGENERICCONTAINER2D *aDstContainer,
675  const BOARD_ITEM &aBoardItem )
676 {
677  wxPoint arc_start, arc_end;
678  int delta = 3600 / aCircleToSegmentsCount; // rotate angle in 0.1 degree
679 
680  arc_end = arc_start = aStart;
681 
682  if( aArcAngle != 3600 )
683  {
684  RotatePoint( &arc_end, aCentre, -aArcAngle );
685  }
686 
687  if( aArcAngle < 0 )
688  {
689  std::swap( arc_start, arc_end );
690  aArcAngle = -aArcAngle;
691  }
692 
693  // Compute the ends of segments and creates poly
694  wxPoint curr_end = arc_start;
695  wxPoint curr_start = arc_start;
696 
697  for( int ii = delta; ii < aArcAngle; ii += delta )
698  {
699  curr_end = arc_start;
700  RotatePoint( &curr_end, aCentre, -ii );
701 
702  const SFVEC2F start3DU( curr_start.x * m_biuTo3Dunits, -curr_start.y * m_biuTo3Dunits );
703  const SFVEC2F end3DU ( curr_end.x * m_biuTo3Dunits, -curr_end.y * m_biuTo3Dunits );
704 
705  if( Is_segment_a_circle( start3DU, end3DU ) )
706  {
707  aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
708  ( aWidth / 2 ) * m_biuTo3Dunits,
709  aBoardItem ) );
710  }
711  else
712  {
713  aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
714  end3DU,
715  aWidth * m_biuTo3Dunits,
716  aBoardItem ) );
717  }
718 
719  curr_start = curr_end;
720  }
721 
722  if( curr_end != arc_end )
723  {
724  const SFVEC2F start3DU( curr_end.x * m_biuTo3Dunits, -curr_end.y * m_biuTo3Dunits );
725  const SFVEC2F end3DU ( arc_end.x * m_biuTo3Dunits, -arc_end.y * m_biuTo3Dunits );
726 
727  if( Is_segment_a_circle( start3DU, end3DU ) )
728  {
729  aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
730  ( aWidth / 2 ) * m_biuTo3Dunits,
731  aBoardItem ) );
732  }
733  else
734  {
735  aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
736  end3DU,
737  aWidth * m_biuTo3Dunits,
738  aBoardItem ) );
739  }
740  }
741 }
742 
743 // Based on
744 // TransformShapeWithClearanceToPolygon
745 // board_items_to_polygon_shape_transform.cpp#L431
747  CGENERICCONTAINER2D *aDstContainer,
748  LAYER_ID aLayerId,
749  int aClearanceValue )
750 {
751  // The full width of the lines to create:
752  const int linewidth = aDrawSegment->GetWidth() + (2 * aClearanceValue);
753 
754  switch( aDrawSegment->GetShape() )
755  {
756  case S_CIRCLE:
757  {
758  const SFVEC2F center3DU( aDrawSegment->GetCenter().x * m_biuTo3Dunits,
759  -aDrawSegment->GetCenter().y * m_biuTo3Dunits );
760 
761  const float inner_radius = (aDrawSegment->GetRadius() - linewidth / 2) * m_biuTo3Dunits;
762  const float outter_radius = (aDrawSegment->GetRadius() + linewidth / 2) * m_biuTo3Dunits;
763 
764  aDstContainer->Add( new CRING2D( center3DU,
765  inner_radius,
766  outter_radius,
767  *aDrawSegment ) );
768  }
769  break;
770 
771  case S_ARC:
772  {
773  const unsigned int nr_segments =
774  GetNrSegmentsCircle( aDrawSegment->GetBoundingBox().GetSizeMax() );
775 
776  TransformArcToSegments( aDrawSegment->GetCenter(),
777  aDrawSegment->GetArcStart(),
778  aDrawSegment->GetAngle(),
779  nr_segments,
780  aDrawSegment->GetWidth(),
781  aDstContainer,
782  *aDrawSegment );
783  }
784  break;
785 
786  case S_SEGMENT:
787  {
788  const SFVEC2F start3DU( aDrawSegment->GetStart().x * m_biuTo3Dunits,
789  -aDrawSegment->GetStart().y * m_biuTo3Dunits );
790 
791  const SFVEC2F end3DU ( aDrawSegment->GetEnd().x * m_biuTo3Dunits,
792  -aDrawSegment->GetEnd().y * m_biuTo3Dunits );
793 
794  if( Is_segment_a_circle( start3DU, end3DU ) )
795  {
796  aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
797  ( linewidth / 2 ) * m_biuTo3Dunits,
798  *aDrawSegment ) );
799  }
800  else
801  {
802  aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
803  end3DU,
804  linewidth * m_biuTo3Dunits,
805  *aDrawSegment ) );
806  }
807  }
808  break;
809 
810  case S_POLYGON:
811  {
812  // Check for malformed polygon.
813  if( aDrawSegment->GetPolyPoints().size() > 2 )
814  {
815  // The polygon is expected to be a simple polygon
816  // not self intersecting, no hole.
817  MODULE* module = aDrawSegment->GetParentModule(); // NULL for items not in footprints
818  const double orientation = module ? module->GetOrientation() : 0.0;
819 
820  // Build the polygon with the actual position and orientation:
821  std::vector< wxPoint> poly;
822  poly = aDrawSegment->GetPolyPoints();
823 
824  for( unsigned ii = 0; ii < poly.size(); ++ii )
825  {
826  RotatePoint( &poly[ii], orientation );
827  poly[ii] += aDrawSegment->GetPosition();
828  }
829 
830  // Generate polygons for the outline + clearance
831 
832  if( linewidth ) // Add thick outlines
833  {
834  CPolyPt corner1( poly[poly.size()-1] );
835 
836  for( unsigned ii = 0; ii < poly.size(); ++ii )
837  {
838  CPolyPt corner2( poly[ii] );
839 
840  if( corner2 != corner1 )
841  {
842  const SFVEC2F start3DU( corner1.x * m_biuTo3Dunits,
843  -corner1.y * m_biuTo3Dunits );
844 
845  const SFVEC2F end3DU( corner2.x * m_biuTo3Dunits,
846  -corner2.y * m_biuTo3Dunits );
847 
848  if( Is_segment_a_circle( start3DU, end3DU ) )
849  {
850  aDstContainer->Add(
851  new CFILLEDCIRCLE2D( start3DU,
852  (linewidth / 2) * m_biuTo3Dunits,
853  *aDrawSegment ) );
854  }
855  else
856  {
857  aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
858  end3DU,
859  linewidth * m_biuTo3Dunits,
860  *aDrawSegment ) );
861  }
862  }
863 
864  corner1 = corner2;
865  }
866  }
867 
868  // Polygon for the inside
869  SHAPE_LINE_CHAIN path;
870 
871  for( unsigned ii = 0; ii < poly.size(); ++ii )
872  {
873  wxPoint corner = poly[ii];
874  path.Append( corner.x, corner.y );
875  }
876 
877  path.SetClosed( true );
878 
879  SHAPE_POLY_SET polyList;
880 
881  polyList.AddOutline( path );
882 
883  // This convert the poly in outline and holes
884  polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
886 
887  if( polyList.IsEmpty() ) // Just for caution
888  break;
889 
891  *aDstContainer,
893  *aDrawSegment );
894  }
895  }
896  break;
897 
898  case S_CURVE: // Bezier curve (not yet in use in KiCad)
899  break;
900 
901  default:
902  break;
903  }
904 }
905 
906 
907 // Based on
908 // TransformSolidAreasShapesToPolygonSet
909 // board_items_to_polygon_shape_transform.cpp
911  CGENERICCONTAINER2D *aDstContainer,
912  LAYER_ID aLayerId )
913 {
914  // Copy the polys list because we have to simplify it
915  SHAPE_POLY_SET polyList = SHAPE_POLY_SET(aZoneContainer->GetFilledPolysList());
916 
917  // This convert the poly in outline and holes
918 
919  // Note: This two sequencial calls are need in order to get
920  // the triangulation function to work properly.
921  polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
923 
924  if( polyList.IsEmpty() )
925  return;
926 
928  *aDstContainer,
930  *aZoneContainer );
931 
932 
933  // add filled areas outlines, which are drawn with thick lines segments
934  // /////////////////////////////////////////////////////////////////////////
935  for( int i = 0; i < polyList.OutlineCount(); ++i )
936  {
937  // Add outline
938  const SHAPE_LINE_CHAIN& pathOutline = polyList.COutline( i );
939 
940  for( int j = 0; j < pathOutline.PointCount(); ++j )
941  {
942  const VECTOR2I& a = pathOutline.CPoint( j );
943  const VECTOR2I& b = pathOutline.CPoint( j + 1 );
944 
945  SFVEC2F start3DU( a.x * m_biuTo3Dunits, -a.y * m_biuTo3Dunits );
946  SFVEC2F end3DU ( b.x * m_biuTo3Dunits, -b.y * m_biuTo3Dunits );
947 
948  if( Is_segment_a_circle( start3DU, end3DU ) )
949  {
950  aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
951  (aZoneContainer->GetMinThickness() / 2) *
953  *aZoneContainer ) );
954  }
955  else
956  {
957  aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, end3DU,
958  aZoneContainer->GetMinThickness() *
960  *aZoneContainer ) );
961  }
962  }
963 
964  // Add holes (of the poly, ie: the open parts) for this outline
965  for( int h = 0; h < polyList.HoleCount( i ); ++h )
966  {
967  const SHAPE_LINE_CHAIN& pathHole = polyList.CHole( i, h );
968 
969  for( int j = 0; j < pathHole.PointCount(); j++ )
970  {
971  const VECTOR2I& a = pathHole.CPoint( j );
972  const VECTOR2I& b = pathHole.CPoint( j + 1 );
973 
974  SFVEC2F start3DU( a.x * m_biuTo3Dunits, -a.y * m_biuTo3Dunits );
975  SFVEC2F end3DU ( b.x * m_biuTo3Dunits, -b.y * m_biuTo3Dunits );
976 
977  if( Is_segment_a_circle( start3DU, end3DU ) )
978  {
979  aDstContainer->Add(
980  new CFILLEDCIRCLE2D( start3DU,
981  (aZoneContainer->GetMinThickness() / 2) *
983  *aZoneContainer ) );
984  }
985  else
986  {
987  aDstContainer->Add(
988  new CROUNDSEGMENT2D( start3DU, end3DU,
989  aZoneContainer->GetMinThickness() *
991  *aZoneContainer ) );
992  }
993  }
994  }
995  }
996 }
997 
998 
999 
1001  CGENERICCONTAINER2D *aDstContainer,
1002  int aWidth )
1003 {
1004  if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring
1005  {
1006  const SFVEC2F center3DU( aPad->ShapePos().x * m_biuTo3Dunits,
1007  -aPad->ShapePos().y * m_biuTo3Dunits );
1008 
1009  const int radius = aPad->GetSize().x / 2;
1010  const float inner_radius = (radius - aWidth / 2) * m_biuTo3Dunits;
1011  const float outter_radius = (radius + aWidth / 2) * m_biuTo3Dunits;
1012 
1013  aDstContainer->Add( new CRING2D( center3DU,
1014  inner_radius,
1015  outter_radius,
1016  *aPad ) );
1017 
1018  return;
1019  }
1020 
1021  // For other shapes, draw polygon outlines
1022  SHAPE_POLY_SET corners;
1023 
1024  const int segcountforcircle = GetNrSegmentsCircle( glm::min( aPad->GetSize().x,
1025  aPad->GetSize().y) );
1026 
1027  const double correctionFactor = GetCircleCorrectionFactor( segcountforcircle );
1028 
1029  aPad->BuildPadShapePolygon( corners, wxSize( 0, 0 ),
1030  // This two factors are only expected to be used if render an oval
1031  segcountforcircle, correctionFactor );
1032 
1033 
1034  // Add outlines as thick segments in polygon buffer
1035 
1036  const SHAPE_LINE_CHAIN& path = corners.COutline( 0 );
1037 
1038  for( int j = 0; j < path.PointCount(); j++ )
1039  {
1040  const VECTOR2I& a = path.CPoint( j );
1041  const VECTOR2I& b = path.CPoint( j + 1 );
1042 
1043  SFVEC2F start3DU( a.x * m_biuTo3Dunits, -a.y * m_biuTo3Dunits );
1044  SFVEC2F end3DU ( b.x * m_biuTo3Dunits, -b.y * m_biuTo3Dunits );
1045 
1046  if( Is_segment_a_circle( start3DU, end3DU ) )
1047  {
1048  aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
1049  (aWidth / 2) * m_biuTo3Dunits,
1050  *aPad ) );
1051  }
1052  else
1053  {
1054  aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, end3DU,
1055  aWidth * m_biuTo3Dunits,
1056  *aPad ) );
1057  }
1058  }
1059 }
1060 
1061 
1063 {
1064  if( !m_layers_poly.empty() )
1065  {
1066  for( MAP_POLY::iterator ii = m_layers_poly.begin();
1067  ii != m_layers_poly.end();
1068  ++ii )
1069  {
1070  delete ii->second;
1071  ii->second = NULL;
1072  }
1073 
1074  m_layers_poly.clear();
1075  }
1076 
1077  if( !m_layers_inner_holes_poly.empty() )
1078  {
1079  for( MAP_POLY::iterator ii = m_layers_inner_holes_poly.begin();
1080  ii != m_layers_inner_holes_poly.end();
1081  ++ii )
1082  {
1083  delete ii->second;
1084  ii->second = NULL;
1085  }
1086 
1087  m_layers_inner_holes_poly.clear();
1088  }
1089 
1090  if( !m_layers_outer_holes_poly.empty() )
1091  {
1092  for( MAP_POLY::iterator ii = m_layers_outer_holes_poly.begin();
1093  ii != m_layers_outer_holes_poly.end();
1094  ++ii )
1095  {
1096  delete ii->second;
1097  ii->second = NULL;
1098  }
1099 
1100  m_layers_outer_holes_poly.clear();
1101  }
1102 
1103  if( !m_layers_container2D.empty() )
1104  {
1105  for( MAP_CONTAINER_2D::iterator ii = m_layers_container2D.begin();
1106  ii != m_layers_container2D.end();
1107  ++ii )
1108  {
1109  delete ii->second;
1110  ii->second = NULL;
1111  }
1112 
1113  m_layers_container2D.clear();
1114  }
1115 
1116  if( !m_layers_holes2D.empty() )
1117  {
1118  for( MAP_CONTAINER_2D::iterator ii = m_layers_holes2D.begin();
1119  ii != m_layers_holes2D.end();
1120  ++ii )
1121  {
1122  delete ii->second;
1123  ii->second = NULL;
1124  }
1125 
1126  m_layers_holes2D.clear();
1127  }
1128 
1135  //m_through_inner_holes_poly.RemoveAllContours();
1136 
1139 }
1140 
1141 
1142 void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter )
1143 {
1144  // Number of segments to draw a circle using segments (used on countour zones
1145  // and text copper elements )
1146  const int segcountforcircle = 12;
1147  const double correctionFactor = GetCircleCorrectionFactor( segcountforcircle );
1148 
1149  // segments to draw a circle to build texts. Is is used only to build
1150  // the shape of each segment of the stroke font, therefore no need to have
1151  // many segments per circle.
1152  const int segcountInStrokeFont = 12;
1153  const double correctionFactorStroke = GetCircleCorrectionFactor( segcountInStrokeFont );
1154 
1155  destroyLayers();
1156 
1157  // Build Copper layers
1158  // Based on: https://github.com/KiCad/kicad-source-mirror/blob/master/3d-viewer/3d_draw.cpp#L692
1159  // /////////////////////////////////////////////////////////////////////////
1160 
1161  #ifdef PRINT_STATISTICS_3D_VIEWER
1162  unsigned stats_startCopperLayersTime = GetRunningMicroSecs();
1163 
1164  unsigned start_Time = stats_startCopperLayersTime;
1165 #endif
1166 
1167  LAYER_ID cu_seq[MAX_CU_LAYERS];
1169 
1170  m_stats_nr_tracks = 0;
1172  m_stats_nr_vias = 0;
1174  m_stats_nr_holes = 0;
1176 
1177  // Prepare track list, convert in a vector. Calc statistic for the holes
1178  // /////////////////////////////////////////////////////////////////////////
1179  std::vector< const TRACK *> trackList;
1180  trackList.clear();
1181  trackList.reserve( m_board->m_Track.GetCount() );
1182 
1183  for( const TRACK* track = m_board->m_Track; track; track = track->Next() )
1184  {
1185  if( !Is3DLayerEnabled( track->GetLayer() ) ) // Skip non enabled layers
1186  continue;
1187 
1188  // Note: a TRACK holds normal segment tracks and
1189  // also vias circles (that have also drill values)
1190  trackList.push_back( track );
1191 
1192  if( track->Type() == PCB_VIA_T )
1193  {
1194  const VIA *via = static_cast< const VIA*>( track );
1195  m_stats_nr_vias++;
1197  }
1198  else
1199  {
1201  }
1202 
1203  m_stats_track_med_width += track->GetWidth() * m_biuTo3Dunits;
1204  }
1205 
1206  if( m_stats_nr_tracks )
1208 
1209  if( m_stats_nr_vias )
1211 
1212 #ifdef PRINT_STATISTICS_3D_VIEWER
1213  printf( "T01: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1214  start_Time = GetRunningMicroSecs();
1215 #endif
1216 
1217  // Prepare copper layers index and containers
1218  // /////////////////////////////////////////////////////////////////////////
1219  std::vector< LAYER_ID > layer_id;
1220  layer_id.clear();
1221  layer_id.reserve( m_copperLayersCount );
1222 
1223  for( unsigned i = 0; i < DIM( cu_seq ); ++i )
1224  cu_seq[i] = ToLAYER_ID( B_Cu - i );
1225 
1226  for( LSEQ cu = cu_set.Seq( cu_seq, DIM( cu_seq ) ); cu; ++cu )
1227  {
1228  const LAYER_ID curr_layer_id = *cu;
1229 
1230  if( !Is3DLayerEnabled( curr_layer_id ) ) // Skip non enabled layers
1231  continue;
1232 
1233  layer_id.push_back( curr_layer_id );
1234 
1235  CBVHCONTAINER2D *layerContainer = new CBVHCONTAINER2D;
1236  m_layers_container2D[curr_layer_id] = layerContainer;
1237 
1240  {
1241  SHAPE_POLY_SET *layerPoly = new SHAPE_POLY_SET;
1242  m_layers_poly[curr_layer_id] = layerPoly;
1243  }
1244  }
1245 
1246 #ifdef PRINT_STATISTICS_3D_VIEWER
1247  printf( "T02: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1248  start_Time = GetRunningMicroSecs();
1249 #endif
1250 
1251  if( aStatusTextReporter )
1252  aStatusTextReporter->Report( _( "Create tracks and vias" ) );
1253 
1254  // Create tracks as objects and add it to container
1255  // /////////////////////////////////////////////////////////////////////////
1256  for( unsigned int lIdx = 0; lIdx < layer_id.size(); ++lIdx )
1257  {
1258  const LAYER_ID curr_layer_id = layer_id[lIdx];
1259 
1260  wxASSERT( m_layers_container2D.find( curr_layer_id ) != m_layers_container2D.end() );
1261 
1262  CBVHCONTAINER2D *layerContainer = m_layers_container2D[curr_layer_id];
1263 
1264  // ADD TRACKS
1265  unsigned int nTracks = trackList.size();
1266 
1267  for( unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
1268  {
1269  const TRACK *track = trackList[trackIdx];
1270 
1271  // NOTE: Vias can be on multiple layers
1272  if( !track->IsOnLayer( curr_layer_id ) )
1273  continue;
1274 
1275  // Add object item to layer container
1276  layerContainer->Add( createNewTrack( track, 0.0f ) );
1277  }
1278  }
1279 
1280 #ifdef PRINT_STATISTICS_3D_VIEWER
1281  printf( "T03: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1282  start_Time = GetRunningMicroSecs();
1283 #endif
1284 
1285  // Create VIAS and THTs objects and add it to holes containers
1286  // /////////////////////////////////////////////////////////////////////////
1287  for( unsigned int lIdx = 0; lIdx < layer_id.size(); ++lIdx )
1288  {
1289  const LAYER_ID curr_layer_id = layer_id[lIdx];
1290 
1291  // ADD TRACKS
1292  unsigned int nTracks = trackList.size();
1293 
1294  for( unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
1295  {
1296  const TRACK *track = trackList[trackIdx];
1297 
1298  if( !track->IsOnLayer( curr_layer_id ) )
1299  continue;
1300 
1301  // ADD VIAS and THT
1302  if( track->Type() == PCB_VIA_T )
1303  {
1304  const VIA *via = static_cast< const VIA*>( track );
1305  const VIATYPE_T viatype = via->GetViaType();
1306  const float holediameter = via->GetDrillValue() * BiuTo3Dunits();
1307  const float thickness = GetCopperThickness3DU();
1308  const float hole_inner_radius = ( holediameter / 2.0f );
1309 
1310  const SFVEC2F via_center( via->GetStart().x * m_biuTo3Dunits,
1311  -via->GetStart().y * m_biuTo3Dunits );
1312 
1313  if( viatype != VIA_THROUGH )
1314  {
1315 
1316  // Add hole objects
1317  // /////////////////////////////////////////////////////////
1318 
1319  CBVHCONTAINER2D *layerHoleContainer = NULL;
1320 
1321  // Check if the layer is already created
1322  if( m_layers_holes2D.find( curr_layer_id ) == m_layers_holes2D.end() )
1323  {
1324  // not found, create a new container
1325  layerHoleContainer = new CBVHCONTAINER2D;
1326  m_layers_holes2D[curr_layer_id] = layerHoleContainer;
1327  }
1328  else
1329  {
1330  // found
1331  layerHoleContainer = m_layers_holes2D[curr_layer_id];
1332  }
1333 
1334  // Add a hole for this layer
1335  layerHoleContainer->Add( new CFILLEDCIRCLE2D( via_center,
1336  hole_inner_radius + thickness,
1337  *track ) );
1338  }
1339  else if( lIdx == 0 ) // it only adds once the THT holes
1340  {
1341  // Add through hole object
1342  // /////////////////////////////////////////////////////////
1343  m_through_holes_outer.Add( new CFILLEDCIRCLE2D( via_center,
1344  hole_inner_radius + thickness,
1345  *track ) );
1346 
1348  new CFILLEDCIRCLE2D( via_center,
1349  hole_inner_radius + thickness,
1350  *track ) );
1351 
1352  m_through_holes_inner.Add( new CFILLEDCIRCLE2D( via_center,
1353  hole_inner_radius,
1354  *track ) );
1355 
1356  //m_through_holes_vias_inner.Add( new CFILLEDCIRCLE2D( via_center,
1357  // hole_inner_radius,
1358  // *track ) );
1359  }
1360  }
1361  }
1362  }
1363 
1364 #ifdef PRINT_STATISTICS_3D_VIEWER
1365  printf( "T04: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1366  start_Time = GetRunningMicroSecs();
1367 #endif
1368 
1369  // Create VIAS and THTs objects and add it to holes containers
1370  // /////////////////////////////////////////////////////////////////////////
1371  for( unsigned int lIdx = 0; lIdx < layer_id.size(); ++lIdx )
1372  {
1373  const LAYER_ID curr_layer_id = layer_id[lIdx];
1374 
1375  // ADD TRACKS
1376  const unsigned int nTracks = trackList.size();
1377 
1378  for( unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
1379  {
1380  const TRACK *track = trackList[trackIdx];
1381 
1382  if( !track->IsOnLayer( curr_layer_id ) )
1383  continue;
1384 
1385  // ADD VIAS and THT
1386  if( track->Type() == PCB_VIA_T )
1387  {
1388  const VIA *via = static_cast< const VIA*>( track );
1389  const VIATYPE_T viatype = via->GetViaType();
1390 
1391  if( viatype != VIA_THROUGH )
1392  {
1393 
1394  // Add VIA hole contourns
1395  // /////////////////////////////////////////////////////////
1396 
1397  // Add outter holes of VIAs
1398  SHAPE_POLY_SET *layerOuterHolesPoly = NULL;
1399  SHAPE_POLY_SET *layerInnerHolesPoly = NULL;
1400 
1401  // Check if the layer is already created
1402  if( m_layers_outer_holes_poly.find( curr_layer_id ) ==
1404  {
1405  // not found, create a new container
1406  layerOuterHolesPoly = new SHAPE_POLY_SET;
1407  m_layers_outer_holes_poly[curr_layer_id] = layerOuterHolesPoly;
1408 
1409  wxASSERT( m_layers_inner_holes_poly.find( curr_layer_id ) ==
1410  m_layers_inner_holes_poly.end() );
1411 
1412  layerInnerHolesPoly = new SHAPE_POLY_SET;
1413  m_layers_inner_holes_poly[curr_layer_id] = layerInnerHolesPoly;
1414  }
1415  else
1416  {
1417  // found
1418  layerOuterHolesPoly = m_layers_outer_holes_poly[curr_layer_id];
1419 
1420  wxASSERT( m_layers_inner_holes_poly.find( curr_layer_id ) !=
1421  m_layers_inner_holes_poly.end() );
1422 
1423  layerInnerHolesPoly = m_layers_inner_holes_poly[curr_layer_id];
1424  }
1425 
1426  const int holediameter = via->GetDrillValue();
1427  const int hole_outer_radius = (holediameter / 2) + GetCopperThicknessBIU();
1428 
1429  TransformCircleToPolygon( *layerOuterHolesPoly,
1430  via->GetStart(),
1431  hole_outer_radius,
1432  GetNrSegmentsCircle( hole_outer_radius * 2 ) );
1433 
1434  TransformCircleToPolygon( *layerInnerHolesPoly,
1435  via->GetStart(),
1436  holediameter / 2,
1437  GetNrSegmentsCircle( holediameter ) );
1438  }
1439  else if( lIdx == 0 ) // it only adds once the THT holes
1440  {
1441  const int holediameter = via->GetDrillValue();
1442  const int hole_outer_radius = (holediameter / 2)+ GetCopperThicknessBIU();
1443 
1444  // Add through hole contourns
1445  // /////////////////////////////////////////////////////////
1447  via->GetStart(),
1448  hole_outer_radius,
1449  GetNrSegmentsCircle( hole_outer_radius * 2 ) );
1450 
1452  via->GetStart(),
1453  holediameter / 2,
1454  GetNrSegmentsCircle( holediameter ) );
1455 
1456  // Add samething for vias only
1457 
1459  via->GetStart(),
1460  hole_outer_radius,
1461  GetNrSegmentsCircle( hole_outer_radius * 2 ) );
1462 
1463  //TransformCircleToPolygon( m_through_inner_holes_vias_poly,
1464  // via->GetStart(),
1465  // holediameter / 2,
1466  // GetNrSegmentsCircle( holediameter ) );
1467  }
1468  }
1469  }
1470  }
1471 
1472 #ifdef PRINT_STATISTICS_3D_VIEWER
1473  printf( "T05: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1474  start_Time = GetRunningMicroSecs();
1475 #endif
1476 
1477  // Creates outline contours of the tracks and add it to the poly of the layer
1478  // /////////////////////////////////////////////////////////////////////////
1481  {
1482  for( unsigned int lIdx = 0; lIdx < layer_id.size(); ++lIdx )
1483  {
1484  const LAYER_ID curr_layer_id = layer_id[lIdx];
1485 
1486  wxASSERT( m_layers_poly.find( curr_layer_id ) != m_layers_poly.end() );
1487 
1488  SHAPE_POLY_SET *layerPoly = m_layers_poly[curr_layer_id];
1489 
1490  // ADD TRACKS
1491  unsigned int nTracks = trackList.size();
1492 
1493  for( unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
1494  {
1495  const TRACK *track = trackList[trackIdx];
1496 
1497  if( !track->IsOnLayer( curr_layer_id ) )
1498  continue;
1499 
1500  // Add the track contour
1501  int nrSegments = GetNrSegmentsCircle( track->GetWidth() );
1502 
1504  *layerPoly,
1505  0,
1506  nrSegments,
1507  GetCircleCorrectionFactor( nrSegments ) );
1508  }
1509  }
1510  }
1511 
1512 #ifdef PRINT_STATISTICS_3D_VIEWER
1513  printf( "T06: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1514  start_Time = GetRunningMicroSecs();
1515 #endif
1516 
1517  // Add holes of modules
1518  // /////////////////////////////////////////////////////////////////////////
1519  for( const MODULE* module = m_board->m_Modules; module; module = module->Next() )
1520  {
1521  const D_PAD* pad = module->Pads();
1522 
1523  for( ; pad; pad = pad->Next() )
1524  {
1525  const wxSize padHole = pad->GetDrillSize();
1526 
1527  if( !padHole.x ) // Not drilled pad like SMD pad
1528  continue;
1529 
1530  // The hole in the body is inflated by copper thickness,
1531  // if not plated, no copper
1532  const int inflate = (pad->GetAttribute () != PAD_ATTRIB_HOLE_NOT_PLATED) ?
1533  GetCopperThicknessBIU() : 0;
1534 
1535  m_stats_nr_holes++;
1536  m_stats_hole_med_diameter += ( ( pad->GetDrillSize().x +
1537  pad->GetDrillSize().y ) / 2.0f ) * m_biuTo3Dunits;
1538 
1539  m_through_holes_outer.Add( createNewPadDrill( pad, inflate ) );
1541  }
1542  }
1543  if( m_stats_nr_holes )
1545 
1546 #ifdef PRINT_STATISTICS_3D_VIEWER
1547  printf( "T07: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1548  start_Time = GetRunningMicroSecs();
1549 #endif
1550 
1551  // Add contours of the pad holes (pads can be Circle or Segment holes)
1552  // /////////////////////////////////////////////////////////////////////////
1553  for( const MODULE* module = m_board->m_Modules; module; module = module->Next() )
1554  {
1555  const D_PAD* pad = module->Pads();
1556 
1557  for( ; pad; pad = pad->Next() )
1558  {
1559  const wxSize padHole = pad->GetDrillSize();
1560 
1561  if( !padHole.x ) // Not drilled pad like SMD pad
1562  continue;
1563 
1564  // The hole in the body is inflated by copper thickness.
1565  const int inflate = GetCopperThicknessBIU();
1566 
1567  // we use the hole diameter to calculate the seg count.
1568  // for round holes, padHole.x == padHole.y
1569  // for oblong holes, the diameter is the smaller of (padHole.x, padHole.y)
1570  const int diam = std::min( padHole.x, padHole.y );
1571 
1572 
1573  if( pad->GetAttribute () != PAD_ATTRIB_HOLE_NOT_PLATED )
1574  {
1576  inflate,
1577  GetNrSegmentsCircle( diam ) );
1578 
1580  0,
1581  GetNrSegmentsCircle( diam ) );
1582  }
1583  else
1584  {
1585  // If not plated, no copper.
1587  inflate,
1588  GetNrSegmentsCircle( diam ) );
1589  }
1590  }
1591  }
1592 
1593 #ifdef PRINT_STATISTICS_3D_VIEWER
1594  printf( "T08: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1595  start_Time = GetRunningMicroSecs();
1596 #endif
1597 
1598  // Add modules PADs objects to containers
1599  // /////////////////////////////////////////////////////////////////////////
1600  for( unsigned int lIdx = 0; lIdx < layer_id.size(); ++lIdx )
1601  {
1602  const LAYER_ID curr_layer_id = layer_id[lIdx];
1603 
1604  wxASSERT( m_layers_container2D.find( curr_layer_id ) != m_layers_container2D.end() );
1605 
1606  CBVHCONTAINER2D *layerContainer = m_layers_container2D[curr_layer_id];
1607 
1608  // ADD PADS
1609  for( const MODULE* module = m_board->m_Modules; module; module = module->Next() )
1610  {
1611  // Note: NPTH pads are not drawn on copper layers when the pad
1612  // has same shape as its hole
1614  layerContainer,
1615  curr_layer_id,
1616  0,
1617  true );
1618 
1619  // Micro-wave modules may have items on copper layers
1621  layerContainer,
1622  curr_layer_id,
1623  0 );
1624  }
1625  }
1626 
1627 #ifdef PRINT_STATISTICS_3D_VIEWER
1628  printf( "T09: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1629  start_Time = GetRunningMicroSecs();
1630 #endif
1631 
1632  // Add modules PADs poly contourns
1633  // /////////////////////////////////////////////////////////////////////////
1636  {
1637  for( unsigned int lIdx = 0; lIdx < layer_id.size(); ++lIdx )
1638  {
1639  const LAYER_ID curr_layer_id = layer_id[lIdx];
1640 
1641  wxASSERT( m_layers_poly.find( curr_layer_id ) != m_layers_poly.end() );
1642 
1643  SHAPE_POLY_SET *layerPoly = m_layers_poly[curr_layer_id];
1644 
1645  // ADD PADS
1646  for( const MODULE* module = m_board->m_Modules;
1647  module;
1648  module = module->Next() )
1649  {
1650  // Construct polys
1651  // /////////////////////////////////////////////////////////////
1652 
1653  // Note: NPTH pads are not drawn on copper layers when the pad
1654  // has same shape as its hole
1656  curr_layer_id,
1657  *layerPoly,
1658  0,
1659  true );
1660 
1661  // Micro-wave modules may have items on copper layers
1662  module->TransformGraphicTextWithClearanceToPolygonSet( curr_layer_id,
1663  *layerPoly,
1664  0,
1665  segcountforcircle,
1666  correctionFactor );
1667 
1668  transformGraphicModuleEdgeToPolygonSet( module, curr_layer_id, *layerPoly );
1669  }
1670  }
1671  }
1672 
1673 #ifdef PRINT_STATISTICS_3D_VIEWER
1674  printf( "T10: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1675  start_Time = GetRunningMicroSecs();
1676 #endif
1677 
1678  // Add graphic item on copper layers to object containers
1679  // /////////////////////////////////////////////////////////////////////////
1680  for( unsigned int lIdx = 0; lIdx < layer_id.size(); ++lIdx )
1681  {
1682  const LAYER_ID curr_layer_id = layer_id[lIdx];
1683 
1684  wxASSERT( m_layers_container2D.find( curr_layer_id ) != m_layers_container2D.end() );
1685 
1686  CBVHCONTAINER2D *layerContainer = m_layers_container2D[curr_layer_id];
1687 
1688  // ADD GRAPHIC ITEMS ON COPPER LAYERS (texts)
1689  for( const BOARD_ITEM* item = m_board->m_Drawings;
1690  item;
1691  item = item->Next() )
1692  {
1693  if( !item->IsOnLayer( curr_layer_id ) )
1694  continue;
1695 
1696  switch( item->Type() )
1697  {
1698  case PCB_LINE_T: // should not exist on copper layers
1699  {
1701  layerContainer,
1702  curr_layer_id,
1703  0 );
1704  }
1705  break;
1706 
1707  case PCB_TEXT_T:
1709  layerContainer,
1710  curr_layer_id,
1711  0 );
1712  break;
1713 
1714  case PCB_DIMENSION_T:
1716  layerContainer,
1717  curr_layer_id,
1718  0 );
1719  break;
1720 
1721  default:
1722  wxLogTrace( m_logTrace,
1723  wxT( "createLayers: item type: %d not implemented" ),
1724  item->Type() );
1725  break;
1726  }
1727  }
1728  }
1729 
1730 #ifdef PRINT_STATISTICS_3D_VIEWER
1731  printf( "T11: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1732  start_Time = GetRunningMicroSecs();
1733 #endif
1734 
1735  // Add graphic item on copper layers to poly contourns
1736  // /////////////////////////////////////////////////////////////////////////
1739  {
1740  for( unsigned int lIdx = 0; lIdx < layer_id.size(); ++lIdx )
1741  {
1742  const LAYER_ID curr_layer_id = layer_id[lIdx];
1743 
1744  wxASSERT( m_layers_poly.find( curr_layer_id ) != m_layers_poly.end() );
1745 
1746  SHAPE_POLY_SET *layerPoly = m_layers_poly[curr_layer_id];
1747 
1748  // ADD GRAPHIC ITEMS ON COPPER LAYERS (texts)
1749  for( const BOARD_ITEM* item = m_board->m_Drawings;
1750  item;
1751  item = item->Next() )
1752  {
1753  if( !item->IsOnLayer( curr_layer_id ) )
1754  continue;
1755 
1756  switch( item->Type() )
1757  {
1758  case PCB_LINE_T: // should not exist on copper layers
1759  {
1760  const int nrSegments =
1761  GetNrSegmentsCircle( item->GetBoundingBox().GetSizeMax() );
1762 
1763  ( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon(
1764  *layerPoly,
1765  0,
1766  nrSegments,
1767  GetCircleCorrectionFactor( nrSegments ) );
1768  }
1769  break;
1770 
1771  case PCB_TEXT_T:
1772  ( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet(
1773  *layerPoly,
1774  0,
1775  segcountforcircle,
1776  correctionFactor );
1777  break;
1778 
1779  default:
1780  wxLogTrace( m_logTrace,
1781  wxT( "createLayers: item type: %d not implemented" ),
1782  item->Type() );
1783  break;
1784  }
1785  }
1786  }
1787  }
1788 
1789 #ifdef PRINT_STATISTICS_3D_VIEWER
1790  printf( "T12: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1791  start_Time = GetRunningMicroSecs();
1792 #endif
1793 
1794  if( GetFlag( FL_ZONE ) )
1795  {
1796  if( aStatusTextReporter )
1797  aStatusTextReporter->Report( _( "Create zones" ) );
1798 
1799  // Add zones objects
1800  // /////////////////////////////////////////////////////////////////////
1801  for( unsigned int lIdx = 0; lIdx < layer_id.size(); ++lIdx )
1802  {
1803  const LAYER_ID curr_layer_id = layer_id[lIdx];
1804 
1805  if( aStatusTextReporter )
1806  aStatusTextReporter->Report( wxString::Format( _( "Create zones of layer %s" ),
1807  LSET::Name( curr_layer_id ) ) );
1808 
1809  wxASSERT( m_layers_container2D.find( curr_layer_id ) != m_layers_container2D.end() );
1810 
1811  CBVHCONTAINER2D *layerContainer = m_layers_container2D[curr_layer_id];
1812 
1813  // ADD COPPER ZONES
1814  for( int ii = 0; ii < m_board->GetAreaCount(); ++ii )
1815  {
1816  const ZONE_CONTAINER* zone = m_board->GetArea( ii );
1817  const LAYER_ID zonelayer = zone->GetLayer();
1818 
1819  if( zonelayer == curr_layer_id )
1820  {
1822  layerContainer,
1823  curr_layer_id );
1824  }
1825  }
1826  }
1827  }
1828 
1829 #ifdef PRINT_STATISTICS_3D_VIEWER
1830  printf( "T13: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1831  start_Time = GetRunningMicroSecs();
1832 #endif
1833 
1834  if( GetFlag( FL_ZONE ) &&
1837  {
1838  // Add zones poly contourns
1839  // /////////////////////////////////////////////////////////////////////
1840  for( unsigned int lIdx = 0; lIdx < layer_id.size(); ++lIdx )
1841  {
1842  const LAYER_ID curr_layer_id = layer_id[lIdx];
1843 
1844  wxASSERT( m_layers_poly.find( curr_layer_id ) != m_layers_poly.end() );
1845 
1846  SHAPE_POLY_SET *layerPoly = m_layers_poly[curr_layer_id];
1847 
1848  // ADD COPPER ZONES
1849  for( int ii = 0; ii < m_board->GetAreaCount(); ++ii )
1850  {
1851  const ZONE_CONTAINER* zone = m_board->GetArea( ii );
1852  const LAYER_NUM zonelayer = zone->GetLayer();
1853 
1854  if( zonelayer == curr_layer_id )
1855  {
1856  zone->TransformSolidAreasShapesToPolygonSet( *layerPoly,
1857  segcountforcircle,
1858  correctionFactor );
1859  }
1860  }
1861  }
1862  }
1863 
1864 #ifdef PRINT_STATISTICS_3D_VIEWER
1865  printf( "T14: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1866  start_Time = GetRunningMicroSecs();
1867 #endif
1868 
1869  // Simplify layer polygons
1870  // /////////////////////////////////////////////////////////////////////////
1871 
1872  if( aStatusTextReporter )
1873  aStatusTextReporter->Report( _( "Simplifying polygons" ) );
1874 
1877  {
1878  const int nLayers = layer_id.size();
1879 
1880  #pragma omp parallel for
1881  for( signed int lIdx = 0; lIdx < nLayers; ++lIdx )
1882  {
1883  const LAYER_ID curr_layer_id = layer_id[lIdx];
1884 
1885  wxASSERT( m_layers_poly.find( curr_layer_id ) != m_layers_poly.end() );
1886 
1887  SHAPE_POLY_SET *layerPoly = m_layers_poly[curr_layer_id];
1888 
1889  wxASSERT( layerPoly != NULL );
1890 
1891  // This will make a union of all added contourns
1892  layerPoly->Simplify( SHAPE_POLY_SET::PM_FAST );
1893  }
1894  }
1895 
1896 #ifdef PRINT_STATISTICS_3D_VIEWER
1897  printf( "T15: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1898  start_Time = GetRunningMicroSecs();
1899 #endif
1900 
1901  // Simplify holes polygon contours
1902  // /////////////////////////////////////////////////////////////////////////
1903  if( aStatusTextReporter )
1904  aStatusTextReporter->Report( _( "Simplify holes contours" ) );
1905 
1906  for( unsigned int lIdx = 0; lIdx < layer_id.size(); ++lIdx )
1907  {
1908  const LAYER_ID curr_layer_id = layer_id[lIdx];
1909 
1910  if( m_layers_outer_holes_poly.find( curr_layer_id ) !=
1912  {
1913  // found
1914  SHAPE_POLY_SET *polyLayer = m_layers_outer_holes_poly[curr_layer_id];
1915  polyLayer->Simplify( SHAPE_POLY_SET::PM_FAST );
1916 
1917  wxASSERT( m_layers_inner_holes_poly.find( curr_layer_id ) !=
1918  m_layers_inner_holes_poly.end() );
1919 
1920  polyLayer = m_layers_inner_holes_poly[curr_layer_id];
1921  polyLayer->Simplify( SHAPE_POLY_SET::PM_FAST );
1922  }
1923  }
1924 
1925 #ifdef PRINT_STATISTICS_3D_VIEWER
1926  printf( "T16: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
1927 #endif
1928  // End Build Copper layers
1929 
1930 
1931  // This will make a union of all added contourns
1936  //m_through_inner_holes_vias_poly.Simplify( SHAPE_POLY_SET::PM_FAST ); // Not in use
1937 
1938 #ifdef PRINT_STATISTICS_3D_VIEWER
1939  unsigned stats_endCopperLayersTime = GetRunningMicroSecs();
1940 #endif
1941 
1942 
1943  // Build Tech layers
1944  // Based on: https://github.com/KiCad/kicad-source-mirror/blob/master/3d-viewer/3d_draw.cpp#L1059
1945  // /////////////////////////////////////////////////////////////////////////
1946 #ifdef PRINT_STATISTICS_3D_VIEWER
1947  unsigned stats_startTechLayersTime = GetRunningMicroSecs();
1948 #endif
1949 
1950  if( aStatusTextReporter )
1951  aStatusTextReporter->Report( _( "Build Tech layers" ) );
1952 
1953  // draw graphic items, on technical layers
1954  static const LAYER_ID teckLayerList[] = {
1955  B_Adhes,
1956  F_Adhes,
1957  B_Paste,
1958  F_Paste,
1959  B_SilkS,
1960  F_SilkS,
1961  B_Mask,
1962  F_Mask,
1963 
1964  // Aux Layers
1965  Dwgs_User,
1966  Cmts_User,
1967  Eco1_User,
1968  Eco2_User,
1969  Edge_Cuts,
1970  Margin
1971  };
1972 
1973  // User layers are not drawn here, only technical layers
1974  for( LSEQ seq = LSET::AllNonCuMask().Seq( teckLayerList, DIM( teckLayerList ) );
1975  seq;
1976  ++seq )
1977  {
1978  const LAYER_ID curr_layer_id = *seq;
1979 
1980  if( !Is3DLayerEnabled( curr_layer_id ) )
1981  continue;
1982 
1983  CBVHCONTAINER2D *layerContainer = new CBVHCONTAINER2D;
1984  m_layers_container2D[curr_layer_id] = layerContainer;
1985 
1986  SHAPE_POLY_SET *layerPoly = new SHAPE_POLY_SET;
1987  m_layers_poly[curr_layer_id] = layerPoly;
1988 
1989  // Add drawing objects
1990  // /////////////////////////////////////////////////////////////////////
1991  for( BOARD_ITEM* item = m_board->m_Drawings; item; item = item->Next() )
1992  {
1993  if( !item->IsOnLayer( curr_layer_id ) )
1994  continue;
1995 
1996  switch( item->Type() )
1997  {
1998  case PCB_LINE_T:
2000  layerContainer,
2001  curr_layer_id,
2002  0 );
2003  break;
2004 
2005  case PCB_TEXT_T:
2007  layerContainer,
2008  curr_layer_id,
2009  0 );
2010  break;
2011 
2012  case PCB_DIMENSION_T:
2014  layerContainer,
2015  curr_layer_id,
2016  0 );
2017  break;
2018 
2019  default:
2020  break;
2021  }
2022  }
2023 
2024 
2025  // Add drawing contours
2026  // /////////////////////////////////////////////////////////////////////
2027  for( BOARD_ITEM* item = m_board->m_Drawings; item; item = item->Next() )
2028  {
2029  if( !item->IsOnLayer( curr_layer_id ) )
2030  continue;
2031 
2032  switch( item->Type() )
2033  {
2034  case PCB_LINE_T:
2035  {
2036  const unsigned int nr_segments =
2037  GetNrSegmentsCircle( item->GetBoundingBox().GetSizeMax() );
2038 
2039  ((DRAWSEGMENT*) item)->TransformShapeWithClearanceToPolygon( *layerPoly,
2040  0,
2041  nr_segments,
2042  0.0 );
2043  }
2044  break;
2045 
2046  case PCB_TEXT_T:
2047  ((TEXTE_PCB*) item)->TransformShapeWithClearanceToPolygonSet( *layerPoly,
2048  0,
2049  segcountInStrokeFont,
2050  1.0 );
2051  break;
2052 
2053  default:
2054  break;
2055  }
2056  }
2057 
2058 
2059  // Add modules tech layers - objects
2060  // /////////////////////////////////////////////////////////////////////
2061  for( MODULE* module = m_board->m_Modules; module; module = module->Next() )
2062  {
2063  if( (curr_layer_id == F_SilkS) || (curr_layer_id == B_SilkS) )
2064  {
2065  D_PAD* pad = module->Pads();
2066  int linewidth = g_DrawDefaultLineThickness;
2067 
2068  for( ; pad; pad = pad->Next() )
2069  {
2070  if( !pad->IsOnLayer( curr_layer_id ) )
2071  continue;
2072 
2074  layerContainer,
2075  linewidth );
2076  }
2077  }
2078  else
2079  {
2081  layerContainer,
2082  curr_layer_id,
2083  0,
2084  false );
2085  }
2086 
2088  layerContainer,
2089  curr_layer_id,
2090  0 );
2091  }
2092 
2093 
2094  // Add modules tech layers - contours
2095  // /////////////////////////////////////////////////////////////////////
2096  for( MODULE* module = m_board->m_Modules; module; module = module->Next() )
2097  {
2098  if( (curr_layer_id == F_SilkS) || (curr_layer_id == B_SilkS) )
2099  {
2100  D_PAD* pad = module->Pads();
2101  const int linewidth = g_DrawDefaultLineThickness;
2102 
2103  for( ; pad; pad = pad->Next() )
2104  {
2105  if( !pad->IsOnLayer( curr_layer_id ) )
2106  continue;
2107 
2108  buildPadShapeThickOutlineAsPolygon( pad, *layerPoly, linewidth );
2109  }
2110  }
2111  else
2112  {
2114  curr_layer_id,
2115  *layerPoly,
2116  0,
2117  false );
2118  }
2119 
2120  // On tech layers, use a poor circle approximation, only for texts (stroke font)
2121  module->TransformGraphicTextWithClearanceToPolygonSet( curr_layer_id,
2122  *layerPoly,
2123  0,
2124  segcountInStrokeFont,
2125  correctionFactorStroke,
2126  segcountInStrokeFont );
2127 
2128  // Add the remaining things with dynamic seg count for circles
2129  transformGraphicModuleEdgeToPolygonSet( module, curr_layer_id, *layerPoly );
2130  }
2131 
2132 
2133  // Draw non copper zones
2134  // /////////////////////////////////////////////////////////////////////
2135  if( GetFlag( FL_ZONE ) )
2136  {
2137  for( int ii = 0; ii < m_board->GetAreaCount(); ++ii )
2138  {
2139  ZONE_CONTAINER* zone = m_board->GetArea( ii );
2140 
2141  if( !zone->IsOnLayer( curr_layer_id ) )
2142  continue;
2143 
2145  layerContainer,
2146  curr_layer_id );
2147  }
2148 
2149  for( int ii = 0; ii < m_board->GetAreaCount(); ++ii )
2150  {
2151  ZONE_CONTAINER* zone = m_board->GetArea( ii );
2152 
2153  if( !zone->IsOnLayer( curr_layer_id ) )
2154  continue;
2155 
2156  zone->TransformSolidAreasShapesToPolygonSet( *layerPoly,
2157  // Use the same segcount as stroke font
2158  segcountInStrokeFont,
2159  correctionFactorStroke );
2160  }
2161  }
2162 
2163  // This will make a union of all added contourns
2164  layerPoly->Simplify( SHAPE_POLY_SET::PM_FAST );
2165  }
2166  // End Build Tech layers
2167 
2168 #ifdef PRINT_STATISTICS_3D_VIEWER
2169  unsigned stats_endTechLayersTime = GetRunningMicroSecs();
2170 #endif
2171 
2172 
2173  // Build BVH for holes and vias
2174  // /////////////////////////////////////////////////////////////////////////
2175 
2176 #ifdef PRINT_STATISTICS_3D_VIEWER
2177  unsigned stats_startHolesBVHTime = GetRunningMicroSecs();
2178 #endif
2179 
2182 
2183  if( !m_layers_holes2D.empty() )
2184  {
2185  for( MAP_CONTAINER_2D::iterator ii = m_layers_holes2D.begin();
2186  ii != m_layers_holes2D.end();
2187  ++ii )
2188  {
2189  ((CBVHCONTAINER2D *)(ii->second))->BuildBVH();
2190  }
2191  }
2192 
2193  // We only need the Solder mask to initialize the BVH
2194  // because..?
2196  ((CBVHCONTAINER2D *)m_layers_container2D[B_Mask])->BuildBVH();
2197 
2199  ((CBVHCONTAINER2D *)m_layers_container2D[F_Mask])->BuildBVH();
2200 
2201 #ifdef PRINT_STATISTICS_3D_VIEWER
2202  unsigned stats_endHolesBVHTime = GetRunningMicroSecs();
2203 
2204  printf( "CINFO3D_VISU::createLayers times\n" );
2205  printf( " Copper Layers: %.3f ms\n",
2206  (float)( stats_endCopperLayersTime - stats_startCopperLayersTime ) / 1e3 );
2207  printf( " Holes BVH creation: %.3f ms\n",
2208  (float)( stats_endHolesBVHTime - stats_startHolesBVHTime ) / 1e3 );
2209  printf( " Tech Layers: %.3f ms\n",
2210  (float)( stats_endTechLayersTime - stats_startTechLayersTime ) / 1e3 );
2211  printf( "Statistics:\n" );
2212  printf( " m_stats_nr_tracks %u\n", m_stats_nr_tracks );
2213  printf( " m_stats_nr_vias %u\n", m_stats_nr_vias );
2214  printf( " m_stats_nr_holes %u\n", m_stats_nr_holes );
2215  printf( " m_stats_via_med_hole_diameter (3DU) %f\n", m_stats_via_med_hole_diameter );
2216  printf( " m_stats_hole_med_diameter (3DU) %f\n", m_stats_hole_med_diameter );
2217  printf( " m_calc_seg_min_factor3DU (3DU) %f\n", m_calc_seg_min_factor3DU );
2218  printf( " m_calc_seg_max_factor3DU (3DU) %f\n", m_calc_seg_max_factor3DU );
2219 #endif
2220 }
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Function wxStringSplit splits aString to a string list separated at aSplitter.
Definition: common.cpp:137
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu LAYER_IDs.
Definition: lset.cpp:638
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
#define DIM(x)
of elements in an array
Definition: macros.h:98
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
COBJECT2D * createNewTrack(const TRACK *aTrack, int aClearanceValue) const
void DrawGraphicText(EDA_RECT *aClipBox, wxDC *aDC, const wxPoint &aPos, COLOR4D aColor, const wxString &aText, double aOrient, const wxSize &aSize, enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, bool aBold, void(*aCallback)(int x0, int y0, int xf, int yf), PLOTTER *aPlotter)
Function DrawGraphicText Draw a graphic text (like module texts)
Definition: drawtxt.cpp:122
static const CBBOX2D * s_boardBBox3DU
TEXTE_MODULE & Reference()
Definition: class_module.h:455
void AddSolidAreasShapesToContainer(const ZONE_CONTAINER *aZoneContainer, CGENERICCONTAINER2D *aDstContainer, LAYER_ID aLayerId)
bool IsMultilineAllowed() const
Definition: eda_text.h:188
double GetDrawRotation() const
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:238
TEXTE_PCB class definition.
const wxPoint & GetTextPos() const
Definition: eda_text.h:224
float GetCopperThickness3DU() const
GetCopperThickness3DU - Get the current copper layer thickness.
Definition: cinfo3d_visu.h:165
bool IsItalic() const
Definition: eda_text.h:170
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:63
CBVHCONTAINER2D m_through_holes_vias_outer
It contains the list of throughHoles vias of the board, the radius of the hole is inflated with the c...
Definition: cinfo3d_visu.h:602
int GetMinThickness() const
Definition: class_zone.h:209
wxPoint m_crossBarF
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
void AddPadsShapesWithClearanceToContainer(const MODULE *aModule, CGENERICCONTAINER2D *aDstContainer, LAYER_ID aLayerId, int aInflateValue, bool aSkipNPTHPadsWihNoCopper)
const wxPoint GetCenter() const override
Function GetCenter()
wxPoint m_arrowD1F
CBBOX2D m_board2dBBox3DU
2d bouding box of the pcb board in 3d units
Definition: cinfo3d_visu.h:554
void BuildPadPolygon(wxPoint aCoord[4], wxSize aInflateValue, double aRotation) const
Function BuildPadPolygon Has meaning only for polygonal pads (trapezoid and rectangular) Build the Co...
void TransformCircleToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aCenter, int aRadius, int aCircleToSegmentsCount)
Function TransformCircleToPolygon convert a circle to a polygon, using multiple straight lines...
int PointCount() const
Function PointCount()
int GetWidth() const
Class BOARD to handle a board.
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:351
void transformGraphicModuleEdgeToPolygonSet(const MODULE *aModule, LAYER_ID aLayer, SHAPE_POLY_SET &aCornerBuffer) const
polygon (not yet used for tracks, but could be in microwave apps)
Class CBBOX manages a bounding box defined by two SFVEC2F min max points.
Definition: cbbox2d.h:40
float m_calc_seg_min_factor3DU
min factor used for cicle segment approximation calculation
Definition: cinfo3d_visu.h:641
LSEQ Seq(const LAYER_ID *aWishListSequence, unsigned aCount) const
Function Seq returns an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:336
static const wxChar * Name(LAYER_ID aLayerId)
Function Name returns the fixed name association with aLayerId.
Definition: lset.cpp:73
SHAPE_POLY_SET m_through_inner_holes_poly
It contains polygon contours for through holes (inner cylinder)
Definition: cinfo3d_visu.h:572
static LSET AllNonCuMask()
Function AllNonCuMask returns a mask holding all layer minus CU layers.
Definition: lset.cpp:661
MODULE * Next() const
Definition: class_module.h:99
MAP_POLY m_layers_inner_holes_poly
It contains polygon contours for holes of each layer (inner holes)
Definition: cinfo3d_visu.h:563
int HoleCount(int aOutline) const
Returns the number of holes in a given outline
Handles data related with the board to be visualized.
void TransformArcToSegments(const wxPoint &aCentre, const wxPoint &aStart, double aArcAngle, int aCircleToSegmentsCount, int aWidth, CGENERICCONTAINER2D *aDstContainer, const BOARD_ITEM &aBoardItem)
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:104
float m_calc_seg_max_factor3DU
max factor used for cicle segment approximation calculation
Definition: cinfo3d_visu.h:644
Classes to handle copper zones.
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:221
int GetCopperThicknessBIU() const
GetCopperThicknessBIU - Get the current copper layer thickness.
usual segment : line with rounded ends
const std::vector< wxPoint > & GetPolyPoints() const
BOARD * m_board
Current board.
Definition: cinfo3d_visu.h:515
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
wxPoint m_featureLineDF
unsigned int m_stats_nr_holes
number of holes in the board
Definition: cinfo3d_visu.h:662
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
int OutlineCount() const
Returns the number of outlines in the set
const wxSize & GetDrillSize() const
Definition: class_pad.h:188
Class REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:61
virtual wxString GetShownText() const override
Returns the string actually shown after processing of the base text.
VIATYPE_T
Definition: class_track.h:48
CBVHCONTAINER2D m_through_holes_inner
It contains the list of throughHoles of the board, the radius is the inner hole.
Definition: cinfo3d_visu.h:598
float m_stats_via_med_hole_diameter
Computed medium diameter of the via holes in 3D units.
Definition: cinfo3d_visu.h:659
LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
#define cu(a)
Definition: auxiliary.h:88
static const BOARD_ITEM * s_boardItem
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:166
#define abs(a)
Definition: auxiliary.h:84
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:190
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:106
DLIST< BOARD_ITEM > & GraphicalItems()
Definition: class_module.h:136
static const int delta[8][2]
Definition: solve.cpp:112
const wxPoint & GetEnd() const
Definition: class_track.h:117
MAP_CONTAINER_2D m_layers_container2D
It contains the 2d elements of each layer.
Definition: cinfo3d_visu.h:587
double GetTextAngle() const
Definition: eda_text.h:164
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:107
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
int GetThickness() const
Function GetThickness returns pen width.
Definition: eda_text.h:154
float m_stats_hole_med_diameter
Computed medium diameter of the holes in 3D units.
Definition: cinfo3d_visu.h:665
bool IsOnLayer(LAYER_ID aLayer) const override
Function IsOnLayer tests to see if this object is on the given layer.
Definition: class_pad.h:479
void TransformSolidAreasShapesToPolygonSet(SHAPE_POLY_SET &aCornerBuffer, int aCircleToSegmentsCount, double aCorrectionFactor) const
Function TransformSolidAreasShapesToPolygonSet Convert solid areas full shapes to polygon set (the fu...
void addTextSegmToContainer(int x0, int y0, int xf, int yf)
const wxPoint & GetArcStart() const
wxPoint m_featureLineGO
virtual wxString GetShownText() const
Returns the string actually shown after processing of the base text.
Definition: eda_text.h:135
virtual bool IsOnLayer(LAYER_ID aLayer) const
Function IsOnLayer tests to see if this object is on the given layer.
BOARD_ITEM * Next() const
void SetClosed(bool aClosed)
Function SetClosed()
a mutex for openmp got from the website: http://bisqwit.iki.fi/story/howto/openmp/ by Joel Yliluoma b...
STROKE_T GetShape() const
MAP_POLY m_layers_poly
It contains polygon contours for each layer.
Definition: cinfo3d_visu.h:557
bool Is_segment_a_circle(const SFVEC2F &aStart, const SFVEC2F &aEnd)
Segment_is_a_circle - check if segment start and end is very close to each other should used to check...
Class LSET is a set of LAYER_IDs.
static float s_biuTo3Dunits
Footprint text class description.
SHAPE_POLY_SET m_through_inner_holes_vias_poly
It contains polygon contours for through holes vias (inner cylinder)
Definition: cinfo3d_visu.h:578
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
glm::vec2 SFVEC2F
Definition: xv3d_types.h:45
VIATYPE_T GetViaType() const
Definition: class_track.h:442
unsigned int m_stats_nr_vias
Nr of vias.
Definition: cinfo3d_visu.h:656
double GetOrientation() const
Definition: class_module.h:147
Class SHAPE_POLY_SET.
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:454
void AddShapeWithClearanceToContainer(const TEXTE_PCB *aTextPCB, CGENERICCONTAINER2D *aDstContainer, LAYER_ID aLayerId, int aClearanceValue)
int GetSolderMaskMargin() const
Function GetSolderMaskMargin.
Definition: class_pad.cpp:486
const wxPoint & GetStart() const
Definition: class_track.h:120
const wxPoint & GetPosition() const override
Definition: class_pad.h:170
Arcs (with rounded ends)
int GetSizeMax() const
GetSizeMax.
void createLayers(REPORTER *aStatusTextReporter)
wxPoint m_arrowG1F
void Convert_shape_line_polygon_to_triangles(const SHAPE_POLY_SET &aPolyList, CGENERICCONTAINER2D &aDstContainer, float aBiuTo3DunitsScale, const BOARD_ITEM &aBoardItem)
wxPoint m_arrowD2F
wxPoint m_arrowG2F
double m_biuTo3Dunits
Normalization scale to convert board internal units to 3D units to normalize 3D units between -1...
Definition: cinfo3d_visu.h:616
D_PAD * Next() const
Definition: class_pad.h:106
const wxSize & GetSize() const
Definition: class_pad.h:182
DLIST< BOARD_ITEM > m_Drawings
Definition: class_board.h:242
SHAPE_POLY_SET m_through_outer_holes_poly_NPTH
It contains polygon contours for (just) non plated through holes (outer cylinder) ...
Definition: cinfo3d_visu.h:566
void GetPositionsOfLinesOfMultilineText(std::vector< wxPoint > &aPositions, int aLineCount) const
Function GetPositionsOfLinesOfMultilineText Populates aPositions with the position of each line of a ...
Definition: eda_text.cpp:327
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
MAP_POLY m_layers_outer_holes_poly
It contains polygon contours for holes of each layer (outer holes)
Definition: cinfo3d_visu.h:560
void Simplify(POLYGON_MODE aFastMode)
Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFast...
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1051
int g_DrawDefaultLineThickness
Default line thickness in internal units used to draw or plot items using a default thickness line va...
Bezier Curve.
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this class.
Definition: cinfo3d_visu.h:673
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:112
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aClearanceValue, int aCircleToSegmentsCount, double aCorrectionFactor) const
Function TransformShapeWithClearanceToPolygon Convert the track shape to a closed polygon Used in fil...
const SHAPE_POLY_SET & GetFilledPolysList() const
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: class_zone.h:587
void AddGraphicsShapesWithClearanceToContainer(const MODULE *aModule, CGENERICCONTAINER2D *aDstContainer, LAYER_ID aLayerId, int aInflateValue)
Class LSEQ is a sequence (and therefore also a set) of LAYER_IDs.
Pad object description.
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
unsigned int GetNrSegmentsCircle(float aDiameter3DU) const
GetNrSegmentsCircle.
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:105
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index
void Add(COBJECT2D *aObject)
Definition: ccontainer2d.h:51
EDA_TEXT_VJUSTIFY_T GetVertJustify() const
Definition: eda_text.h:191
bool GetFlag(DISPLAY3D_FLG aFlag) const
GetFlag - get a configuration status of a flag.
void transformPadsShapesWithClearanceToPolygon(const DLIST< D_PAD > &aPads, LAYER_ID aLayer, SHAPE_POLY_SET &aCornerBuffer, int aInflateValue, bool aSkipNPTHPadsWihNoCopper) const
This handles simple polygons with 4 points.
SHAPE_POLY_SET m_through_outer_holes_poly
It contains polygon contours for through holes (outer cylinder)
Definition: cinfo3d_visu.h:569
TRACK * Next() const
Definition: class_track.h:97
double GetAngle() const
double GetCircleCorrectionFactor(int aNrSides) const
GetCircleCorrectionFactor - computes a angle correction factor used when creating circles...
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:1022
LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:766
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
void GetOblongDrillGeometry(wxPoint &aStartPoint, wxPoint &aEndPoint, int &aWidth) const
Function GetOblongDrillGeometry calculates the start point, end point and width of an equivalent segm...
Definition: class_pad.cpp:667
LAYER_ID
Enum LAYER_ID is the set of PCB layers.
bool IsMirrored() const
Definition: eda_text.h:179
DLIST< MODULE > m_Modules
Definition: class_board.h:243
unsigned GetRunningMicroSecs()
Function GetRunningMicroSecs An alternate way to calculate an elapset time (in microsecondes) to clas...
Class SHAPE_LINE_CHAIN.
bool IsVisible() const
Definition: eda_text.h:176
int GetWidth() const
Definition: class_track.h:114
TEXTE_PCB & Text()
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees, but soon degrees.
Definition: class_pad.h:214
float m_stats_track_med_width
Track average width.
Definition: cinfo3d_visu.h:653
unsigned int m_copperLayersCount
Number of copper layers actually used by the board.
Definition: cinfo3d_visu.h:612
MAP_CONTAINER_2D m_layers_holes2D
It contains the holes per each layer.
Definition: cinfo3d_visu.h:590
wxSize GetSolderPasteMargin() const
Function GetSolderPasteMargin.
Definition: class_pad.cpp:519
RENDER_ENGINE m_render_engine
render engine currently on use
Definition: cinfo3d_visu.h:530
void GetRoundRectCornerCenters(wxPoint aCenters[4], int aRadius, const wxPoint &aPosition, const wxSize &aSize, double aRotation)
Helper function GetRoundRectCornerCenters Has meaning only for rounded rect Returns the centers of th...
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
static int s_textWidth
int GetWidth() const
void BuildPadShapePolygon(SHAPE_POLY_SET &aCornerBuffer, wxSize aInflateValue, int aSegmentsPerCircle, double aCorrectionFactor) const
Function BuildPadShapePolygon Build the Corner list of the polygonal shape, depending on shape...
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
wxPoint ShapePos() const
Definition: class_pad.cpp:367
CBVHCONTAINER2D m_through_holes_vias_inner
It contains the list of throughHoles vias of the board, the radius of the hole.
Definition: cinfo3d_visu.h:606
MODULE * GetParentModule() const
Function GetParentModule returns a pointer to the parent module, or NULL if DRAWSEGMENT does not belo...
This file is part of the common libary.
unsigned GetCount() const
Function GetCount returns the number of elements in the list.
Definition: dlist.h:126
wxPoint m_crossBarO
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:108
DLIST< D_PAD > & Pads()
Definition: class_module.h:133
SHAPE_POLY_SET m_through_outer_holes_vias_poly
It contains polygon contours for through holes vias (outer cylinder)
Definition: cinfo3d_visu.h:575
DLIST< TRACK > m_Track
Definition: class_board.h:244
Module description (excepted pads)
void createNewPadWithClearance(const D_PAD *aPad, CGENERICCONTAINER2D *aDstContainer, int aClearanceValue) const
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
Definition: colors.h:45
const wxSize & GetTextSize() const
Definition: eda_text.h:215
void createNewPad(const D_PAD *aPad, CGENERICCONTAINER2D *aDstContainer, const wxSize &aInflateValue) const
CBVHCONTAINER2D m_through_holes_outer
It contains the list of throughHoles of the board, the radius of the hole is inflated with the copper...
Definition: cinfo3d_visu.h:594
EDGE_MODULE class definition.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:103
void buildPadShapeThickOutlineAsSegments(const D_PAD *aPad, CGENERICCONTAINER2D *aDstContainer, int aWidth)
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
bool Is3DLayerEnabled(LAYER_ID aLayer) const
Is3DLayerEnabled - Check if a layer is enabled.
int GetRadius() const
Function GetRadius returns the radius of this item Has meaning only for arc and circle.
COBJECT2D * createNewPadDrill(const D_PAD *aPad, int aInflateValue)
bool BuildPadDrillShapePolygon(SHAPE_POLY_SET &aCornerBuffer, int aInflateValue, int aSegmentsPerCircle) const
Function BuildPadDrillShapePolygon Build the Corner list of the polygonal drill shape, depending on shape pad hole and orientation.
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
wxPoint m_featureLineDO
static CGENERICCONTAINER2D * s_dstcontainer
Class DIMENSION.
const wxPoint & GetOffset() const
Definition: class_pad.h:191
unsigned int m_stats_nr_tracks
Number of tracks in the board.
Definition: cinfo3d_visu.h:650
void buildPadShapeThickOutlineAsPolygon(const D_PAD *aPad, SHAPE_POLY_SET &aCornerBuffer, int aWidth) const
double BiuTo3Dunits() const
BiuTo3Dunits - Board integer units To 3D units.
Definition: cinfo3d_visu.h:141
const wxPoint & GetPosition() const override
#define min(a, b)
Definition: auxiliary.h:85
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
virtual const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
wxPoint m_featureLineGF