KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 <[email protected]>
5 * Copyright (C) 2023 CERN
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include "board_adapter.h"
30#include <board.h>
31#include <layer_range.h>
32#include <lset.h>
34#include <trigo.h>
35#include <vector>
36#include <thread>
37#include <algorithm>
38#include <atomic>
39#include <wx/log.h>
40
41#ifdef PRINT_STATISTICS_3D_VIEWER
42#include <core/profile.h>
43#endif
44
45/*
46 * This is used to draw pad outlines on silk layers.
47 */
48void buildPadOutlineAsPolygon( const PAD* aPad, PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aBuffer,
49 int aWidth, int aMaxError, ERROR_LOC aErrorLoc )
50{
51 if( aPad->GetShape( aLayer ) == PAD_SHAPE::CIRCLE ) // Draw a ring
52 {
53 TransformRingToPolygon( aBuffer, aPad->ShapePos( aLayer ), aPad->GetSize( aLayer ).x / 2,
54 aWidth, aMaxError, aErrorLoc );
55 }
56 else
57 {
58 // For other shapes, add outlines as thick segments in polygon buffer
59 const SHAPE_LINE_CHAIN& path = aPad->GetEffectivePolygon( aLayer, ERROR_INSIDE )->COutline( 0 );
60
61 for( int ii = 0; ii < path.PointCount(); ++ii )
62 {
63 const VECTOR2I& a = path.CPoint( ii );
64 const VECTOR2I& b = path.CPoint( ii + 1 );
65
66 TransformOvalToPolygon( aBuffer, a, b, aWidth, aMaxError, aErrorLoc );
67 }
68 }
69}
70
71
72void transformFPShapesToPolySet( const FOOTPRINT* aFootprint, PCB_LAYER_ID aLayer,
73 SHAPE_POLY_SET& aBuffer, int aMaxError, ERROR_LOC aErrorLoc )
74{
75 for( BOARD_ITEM* item : aFootprint->GraphicalItems() )
76 {
77 if( item->Type() == PCB_SHAPE_T || BaseType( item->Type() ) == PCB_DIMENSION_T )
78 {
79 if( item->GetLayer() == aLayer )
80 item->TransformShapeToPolySet( aBuffer, aLayer, 0, aMaxError, aErrorLoc );
81 }
82 }
83}
84
85
86void transformFPTextToPolySet( const FOOTPRINT* aFootprint, PCB_LAYER_ID aLayer,
87 const std::bitset<LAYER_3D_END>& aFlags, SHAPE_POLY_SET& aBuffer,
88 int aMaxError, ERROR_LOC aErrorLoc )
89{
90 for( BOARD_ITEM* item : aFootprint->GraphicalItems() )
91 {
92 if( item->GetLayer() != aLayer )
93 continue;
94
95 if( item->Type() == PCB_TEXT_T )
96 {
97 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
98
99 if( !aFlags.test( LAYER_FP_TEXT ) )
100 continue;
101
102 if( text->GetText() == wxT( "${REFERENCE}" ) && !aFlags.test( LAYER_FP_REFERENCES ) )
103 continue;
104
105 if( text->GetText() == wxT( "${VALUE}" ) && !aFlags.test( LAYER_FP_VALUES ) )
106 continue;
107
108 if( aLayer != UNDEFINED_LAYER && text->GetLayer() == aLayer )
109 text->TransformTextToPolySet( aBuffer, 0, aMaxError, aErrorLoc );
110 }
111
112 if( item->Type() == PCB_TEXTBOX_T )
113 {
114 PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
115
116 if( aLayer != UNDEFINED_LAYER && textbox->GetLayer() == aLayer )
117 {
118 // border
119 if( textbox->IsBorderEnabled() )
120 textbox->PCB_SHAPE::TransformShapeToPolygon( aBuffer, aLayer, 0, aMaxError, aErrorLoc );
121
122 // text
123 textbox->TransformTextToPolySet( aBuffer, 0, aMaxError, aErrorLoc );
124 }
125 }
126 }
127
128 for( const PCB_FIELD* field : aFootprint->GetFields() )
129 {
130 if( !aFlags.test( LAYER_FP_TEXT ) )
131 continue;
132
133 if( field->IsReference() && !aFlags.test( LAYER_FP_REFERENCES ) )
134 continue;
135
136 if( field->IsValue() && !aFlags.test( LAYER_FP_VALUES ) )
137 continue;
138
139 if( field->GetLayer() == aLayer && field->IsVisible() )
140 field->TransformTextToPolySet( aBuffer, 0, aMaxError, aErrorLoc );
141 }
142}
143
144
146{
147#define DELETE_AND_FREE( ptr ) \
148 { \
149 delete ptr; \
150 ptr = nullptr; \
151 } \
152
153#define DELETE_AND_FREE_MAP( map ) \
154 { \
155 for( auto& [ layer, poly ] : map ) \
156 delete poly; \
157 \
158 map.clear(); \
159 }
160
162
165
168
169 m_NPTH_ODPolys.RemoveAllContours();
170 m_TH_ODPolys.RemoveAllContours();
171 m_viaTH_ODPolys.RemoveAllContours();
172 m_viaAnnuliPolys.RemoveAllContours();
173
176
181
182 m_TH_ODs.Clear();
183 m_TH_IDs.Clear();
184 m_viaAnnuli.Clear();
185 m_viaTH_ODs.Clear();
186}
187
188
189void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
190{
192
193 // Build Copper layers
194 // Based on:
195 // https://github.com/KiCad/kicad-source-mirror/blob/master/3d-viewer/3d_draw.cpp#L692
196
197#ifdef PRINT_STATISTICS_3D_VIEWER
198 int64_t stats_startCopperLayersTime = GetRunningMicroSecs();
199
200 int64_t start_Time = stats_startCopperLayersTime;
201#endif
202
204
205 std::bitset<LAYER_3D_END> visibilityFlags = GetVisibleLayers();
206
207 m_trackCount = 0;
209 m_viaCount = 0;
211 m_holeCount = 0;
213
214 if( !m_board )
215 return;
216
217 // Prepare track list, convert in a vector. Calc statistic for the holes
218 std::vector<const PCB_TRACK*> trackList;
219 trackList.clear();
220 trackList.reserve( m_board->Tracks().size() );
221
222 for( PCB_TRACK* track : m_board->Tracks() )
223 {
224 // Skip tracks (not vias theyt are on more than one layer ) on disabled layers
225 if( track->Type() != PCB_VIA_T && !Is3dLayerEnabled( track->GetLayer(), visibilityFlags ) )
226 {
227 continue;
228 }
229
230 // Note: a PCB_TRACK holds normal segment tracks and also vias circles (that have also
231 // drill values)
232 trackList.push_back( track );
233
234 if( track->Type() == PCB_VIA_T )
235 {
236 const PCB_VIA *via = static_cast< const PCB_VIA*>( track );
237 m_viaCount++;
238 m_averageViaHoleDiameter += static_cast<float>( via->GetDrillValue() * m_biuTo3Dunits );
239 }
240 else
241 {
242 m_trackCount++;
243 m_averageTrackWidth += static_cast<float>( track->GetWidth() * m_biuTo3Dunits );
244 }
245 }
246
247 if( m_trackCount )
249
250 if( m_viaCount )
252
253 // Prepare copper layers index and containers
254 std::vector<PCB_LAYER_ID> layer_ids;
255 layer_ids.clear();
256 layer_ids.reserve( m_copperLayersCount );
257
259 {
260 if( !Is3dLayerEnabled( layer, visibilityFlags ) ) // Skip non enabled layers
261 continue;
262
263 layer_ids.push_back( layer );
264
265 BVH_CONTAINER_2D *layerContainer = new BVH_CONTAINER_2D;
266 m_layerMap[layer] = layerContainer;
267
269 {
270 SHAPE_POLY_SET* layerPoly = new SHAPE_POLY_SET;
271 m_layers_poly[layer] = layerPoly;
272 }
273 }
274
275 if( cfg.DifferentiatePlatedCopper() )
276 {
279
282 }
283
284 if( cfg.show_off_board_silk )
285 {
288 }
289
290 if( aStatusReporter )
291 aStatusReporter->Report( _( "Create tracks and vias" ) );
292
293 // Create tracks as objects and add it to container
294 for( PCB_LAYER_ID layer : layer_ids )
295 {
296 wxASSERT( m_layerMap.contains( layer ) );
297
298 BVH_CONTAINER_2D *layerContainer = m_layerMap[layer];
299
300 for( const PCB_TRACK* track : trackList )
301 {
302 // NOTE: Vias can be on multiple layers
303 if( !track->IsOnLayer( layer ) )
304 continue;
305
306 // Skip vias annulus when not flashed on this layer
307 if( track->Type() == PCB_VIA_T && !static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
308 continue;
309
310 // Add object item to layer container
311 createTrackWithMargin( track, layerContainer, layer );
312 }
313 }
314
315 // Create VIAS and THTs objects and add it to holes containers
316 for( PCB_LAYER_ID layer : layer_ids )
317 {
318 // ADD TRACKS
319 unsigned int nTracks = trackList.size();
320
321 for( unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
322 {
323 const PCB_TRACK *track = trackList[trackIdx];
324
325 if( !track->IsOnLayer( layer ) )
326 continue;
327
328 // ADD VIAS and THT
329 if( track->Type() == PCB_VIA_T )
330 {
331 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
332 const VIATYPE viatype = via->GetViaType();
333 const double holediameter = via->GetDrillValue() * BiuTo3dUnits();
334 const double viasize = via->GetWidth( layer ) * BiuTo3dUnits();
335 const double plating = GetHolePlatingThickness() * BiuTo3dUnits();
336
337 // holes and layer copper extend half info cylinder wall to hide transition
338 const float thickness = static_cast<float>( plating / 2.0f );
339 const float hole_inner_radius = static_cast<float>( holediameter / 2.0f );
340 const float ring_radius = static_cast<float>( viasize / 2.0f );
341
342 const SFVEC2F via_center( via->GetStart().x * m_biuTo3Dunits,
343 -via->GetStart().y * m_biuTo3Dunits );
344
345 if( viatype != VIATYPE::THROUGH )
346 {
347 // Add hole objects
348 BVH_CONTAINER_2D *layerHoleContainer = nullptr;
349
350 // Check if the layer is already created
351 if( !m_layerHoleMap.contains( layer ) )
352 {
353 // not found, create a new container
354 layerHoleContainer = new BVH_CONTAINER_2D;
355 m_layerHoleMap[layer] = layerHoleContainer;
356 }
357 else
358 {
359 // found
360 layerHoleContainer = m_layerHoleMap[layer];
361 }
362
363 // Add a hole for this layer
364 layerHoleContainer->Add( new FILLED_CIRCLE_2D( via_center, hole_inner_radius + thickness,
365 *track ) );
366 }
367 else if( layer == layer_ids[0] ) // it only adds once the THT holes
368 {
369 // Add through hole object
370 m_TH_ODs.Add( new FILLED_CIRCLE_2D( via_center, hole_inner_radius + thickness, *track ) );
371 m_viaTH_ODs.Add( new FILLED_CIRCLE_2D( via_center, hole_inner_radius + thickness, *track ) );
372
373 if( cfg.clip_silk_on_via_annuli && ring_radius > 0.0 )
374 m_viaAnnuli.Add( new FILLED_CIRCLE_2D( via_center, ring_radius, *track ) );
375
376 if( hole_inner_radius > 0.0 )
377 m_TH_IDs.Add( new FILLED_CIRCLE_2D( via_center, hole_inner_radius, *track ) );
378 }
379 }
380
381 if( cfg.DifferentiatePlatedCopper() && layer == F_Cu )
382 {
384 ERROR_INSIDE );
385 }
386 else if( cfg.DifferentiatePlatedCopper() && layer == B_Cu )
387 {
389 ERROR_INSIDE );
390 }
391 }
392 }
393
394 // Create VIAS and THTs objects and add it to holes containers
395 for( PCB_LAYER_ID layer : layer_ids )
396 {
397 // ADD TRACKS
398 const unsigned int nTracks = trackList.size();
399
400 for( unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
401 {
402 const PCB_TRACK *track = trackList[trackIdx];
403
404 if( !track->IsOnLayer( layer ) )
405 continue;
406
407 // ADD VIAS and THT
408 if( track->Type() == PCB_VIA_T )
409 {
410 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
411 const VIATYPE viatype = via->GetViaType();
412
413 if( viatype != VIATYPE::THROUGH )
414 {
415 // Add PCB_VIA hole contours
416
417 // Add outer holes of VIAs
418 SHAPE_POLY_SET *layerOuterHolesPoly = nullptr;
419 SHAPE_POLY_SET *layerInnerHolesPoly = nullptr;
420
421 // Check if the layer is already created
422 if( !m_layerHoleOdPolys.contains( layer ) )
423 {
424 // not found, create a new container
425 layerOuterHolesPoly = new SHAPE_POLY_SET;
426 m_layerHoleOdPolys[layer] = layerOuterHolesPoly;
427
428 wxASSERT( !m_layerHoleIdPolys.contains( layer ) );
429
430 layerInnerHolesPoly = new SHAPE_POLY_SET;
431 m_layerHoleIdPolys[layer] = layerInnerHolesPoly;
432 }
433 else
434 {
435 // found
436 layerOuterHolesPoly = m_layerHoleOdPolys[layer];
437
438 wxASSERT( m_layerHoleIdPolys.contains( layer ) );
439
440 layerInnerHolesPoly = m_layerHoleIdPolys[layer];
441 }
442
443 const int holediameter = via->GetDrillValue();
444 const int hole_outer_radius = (holediameter / 2) + GetHolePlatingThickness();
445
446 TransformCircleToPolygon( *layerOuterHolesPoly, via->GetStart(), hole_outer_radius,
447 via->GetMaxError(), ERROR_INSIDE );
448
449 TransformCircleToPolygon( *layerInnerHolesPoly, via->GetStart(), holediameter / 2,
450 via->GetMaxError(), ERROR_INSIDE );
451 }
452 else if( layer == layer_ids[0] ) // it only adds once the THT holes
453 {
454 const int holediameter = via->GetDrillValue();
455 const int hole_outer_radius = (holediameter / 2) + GetHolePlatingThickness();
456 const int hole_outer_ring_radius = KiROUND( via->GetWidth( layer ) / 2.0 );
457
458 // Add through hole contours
459 TransformCircleToPolygon( m_TH_ODPolys, via->GetStart(), hole_outer_radius,
460 via->GetMaxError(), ERROR_INSIDE );
461
462 // Add same thing for vias only
463 TransformCircleToPolygon( m_viaTH_ODPolys, via->GetStart(), hole_outer_radius,
464 via->GetMaxError(), ERROR_INSIDE );
465
467 {
468 TransformCircleToPolygon( m_viaAnnuliPolys, via->GetStart(), hole_outer_ring_radius,
469 via->GetMaxError(), ERROR_INSIDE );
470 }
471 }
472 }
473 }
474 }
475
476 // Creates vertical outline contours of the tracks and add it to the poly of the layer
478 {
479 for( PCB_LAYER_ID layer : layer_ids )
480 {
481 wxASSERT( m_layers_poly.contains( layer ) );
482
483 SHAPE_POLY_SET *layerPoly = m_layers_poly[layer];
484
485 // ADD TRACKS
486 unsigned int nTracks = trackList.size();
487
488 for( unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
489 {
490 const PCB_TRACK *track = trackList[trackIdx];
491
492 if( !track->IsOnLayer( layer ) )
493 continue;
494
495 // Skip vias annulus when not flashed on this layer
496 if( track->Type() == PCB_VIA_T && !static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
497 continue;
498
499 // Add the track/via contour
500 track->TransformShapeToPolygon( *layerPoly, layer, 0, track->GetMaxError(), ERROR_INSIDE );
501 }
502 }
503 }
504
505 // Add holes of footprints
506 for( FOOTPRINT* footprint : m_board->Footprints() )
507 {
508 for( PAD* pad : footprint->Pads() )
509 {
510 // Note: holes of NPTH are already built by GetBoardPolygonOutlines
511 if( !pad->HasHole() )
512 continue;
513
514 m_holeCount++;
515 double holeDiameter = ( pad->GetDrillSize().x + pad->GetDrillSize().y ) / 2.0;
516 m_averageHoleDiameter += static_cast<float>( holeDiameter * m_biuTo3Dunits );
517
518 if( pad->GetAttribute() == PAD_ATTRIB::NPTH )
519 {
520 // Ensure the silk drawings are clipped to the NPTH hole, like other pad/via holes
521 // even if the clip to board body is not activated (remember NPTH holes are part of
522 // the board body)
524 continue;
525 }
526
527 // The hole in the body is inflated by copper thickness
528 int inflate = KiROUND( GetHolePlatingThickness() / 2.0 );
529
530 createPadHoleShape( pad, &m_TH_ODs, inflate );
531
533 createPadHoleShape( pad, &m_viaAnnuli, inflate );
534
536 }
537 }
538
539 if( m_holeCount )
541
542 // Add contours of the pad holes (pads can be Circle or Segment holes)
543 for( FOOTPRINT* footprint : m_board->Footprints() )
544 {
545 for( PAD* pad : footprint->Pads() )
546 {
547 if( !pad->HasHole() )
548 continue;
549
550 // The hole in the body is inflated by copper thickness.
551 const int inflate = GetHolePlatingThickness();
552
553 if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
554 {
556 pad->TransformHoleToPolygon( m_viaAnnuliPolys, inflate, pad->GetMaxError(), ERROR_INSIDE );
557
558 pad->TransformHoleToPolygon( m_TH_ODPolys, inflate, pad->GetMaxError(), ERROR_INSIDE );
559 }
560 else
561 {
562 // If not plated, no copper.
564 pad->TransformHoleToPolygon( m_viaAnnuliPolys, 0, pad->GetMaxError(), ERROR_INSIDE );
565
566 pad->TransformHoleToPolygon( m_NPTH_ODPolys, 0, pad->GetMaxError(), ERROR_INSIDE );
567 }
568 }
569 }
570
571 // Add footprints copper items (pads, shapes and text) to containers
572 for( PCB_LAYER_ID layer : layer_ids )
573 {
574 wxASSERT( m_layerMap.contains( layer ) );
575
576 BVH_CONTAINER_2D *layerContainer = m_layerMap[layer];
577
578 for( FOOTPRINT* fp : m_board->Footprints() )
579 {
580 addPads( fp, layerContainer, layer );
581 addFootprintShapes( fp, layerContainer, layer, visibilityFlags );
582
583 // Add copper item to the plated copper polygon list if required
585 {
587
588 fp->TransformPadsToPolySet( *layerPoly, layer, 0, fp->GetMaxError(), ERROR_INSIDE );
589 transformFPTextToPolySet( fp, layer, visibilityFlags, *layerPoly, fp->GetMaxError(), ERROR_INSIDE );
590 transformFPShapesToPolySet( fp, layer, *layerPoly, fp->GetMaxError(), ERROR_INSIDE );
591 }
592
593 // Add copper item to poly contours (vertical outlines) if required
595 {
596 wxASSERT( m_layers_poly.contains( layer ) );
597
598 SHAPE_POLY_SET* layerPoly = m_layers_poly[layer];
599
600 fp->TransformPadsToPolySet( *layerPoly, layer, 0, fp->GetMaxError(), ERROR_INSIDE );
601 transformFPTextToPolySet( fp, layer, visibilityFlags, *layerPoly, fp->GetMaxError(), ERROR_INSIDE );
602 transformFPShapesToPolySet( fp, layer, *layerPoly, fp->GetMaxError(), ERROR_INSIDE );
603 }
604 }
605 }
606
607 // Add graphic item on copper layers to object containers
608 for( PCB_LAYER_ID layer : layer_ids )
609 {
610 wxASSERT( m_layerMap.contains( layer ) );
611
612 BVH_CONTAINER_2D *layerContainer = m_layerMap[layer];
613
614 // Add graphic items on copper layers (texts and other graphics)
615 for( BOARD_ITEM* item : m_board->Drawings() )
616 {
617 if( !item->IsOnLayer( layer ) )
618 continue;
619
620 switch( item->Type() )
621 {
622 case PCB_SHAPE_T:
623 addShape( static_cast<PCB_SHAPE*>( item ), layerContainer, item, layer );
624 break;
625
626 case PCB_TEXT_T:
627 addText( static_cast<PCB_TEXT*>( item ), layerContainer, item );
628 break;
629
630 case PCB_TEXTBOX_T:
631 addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
632 break;
633
634 case PCB_TABLE_T:
635 addTable( static_cast<PCB_TABLE*>( item ), layerContainer, item );
636 break;
637
639 case PCB_DIM_CENTER_T:
640 case PCB_DIM_RADIAL_T:
642 case PCB_DIM_LEADER_T:
643 addShape( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer, item );
644 break;
645
646 case PCB_REFERENCE_IMAGE_T: // ignore
647 break;
648
649 default:
650 wxLogTrace( m_logTrace, wxT( "createLayers: item type: %d not implemented" ), item->Type() );
651 break;
652 }
653
654 // Add copper item to the plated copper polygon list if required
656 {
658
659 // Note: for TEXT and TEXTBOX, TransformShapeToPolygon returns the bounding
660 // box shape, not the exact text shape. So it is not used for these items
661 if( item->Type() == PCB_TEXTBOX_T )
662 {
663 PCB_TEXTBOX* text_box = static_cast<PCB_TEXTBOX*>( item );
664 text_box->TransformTextToPolySet( *copperPolys, 0, text_box->GetMaxError(), ERROR_INSIDE );
665
666 // Add box outlines
667 text_box->PCB_SHAPE::TransformShapeToPolygon( *copperPolys, layer, 0, text_box->GetMaxError(),
668 ERROR_INSIDE );
669 }
670 else if( item->Type() == PCB_TEXT_T )
671 {
672 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
673 text->TransformTextToPolySet( *copperPolys, 0, text->GetMaxError(), ERROR_INSIDE );
674 }
675 else if( item->Type() != PCB_REFERENCE_IMAGE_T )
676 {
677 item->TransformShapeToPolySet( *copperPolys, layer, 0, item->GetMaxError(), ERROR_INSIDE );
678 }
679 }
680
681 // Add copper item to poly contours (vertical outlines) if required
683 {
684 wxASSERT( m_layers_poly.contains( layer ) );
685
686 SHAPE_POLY_SET *layerPoly = m_layers_poly[layer];
687
688 switch( item->Type() )
689 {
690 case PCB_SHAPE_T:
691 item->TransformShapeToPolySet( *layerPoly, layer, 0, item->GetMaxError(), ERROR_INSIDE );
692 break;
693
694 case PCB_TEXT_T:
695 {
696 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
697
698 text->TransformTextToPolySet( *layerPoly, 0, text->GetMaxError(), ERROR_INSIDE );
699 break;
700 }
701
702 case PCB_TEXTBOX_T:
703 {
704 PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
705
706 if( textbox->IsBorderEnabled() )
707 {
708 textbox->PCB_SHAPE::TransformShapeToPolygon( *layerPoly, layer, 0, textbox->GetMaxError(),
709 ERROR_INSIDE );
710 }
711
712 textbox->TransformTextToPolySet( *layerPoly, 0, textbox->GetMaxError(), ERROR_INSIDE );
713 break;
714 }
715
716 case PCB_TABLE_T:
717 {
718 PCB_TABLE* table = static_cast<PCB_TABLE*>( item );
719
720 for( PCB_TABLECELL* cell : table->GetCells() )
721 cell->TransformTextToPolySet( *layerPoly, 0, cell->GetMaxError(), ERROR_INSIDE );
722
723 table->DrawBorders(
724 [&]( const VECTOR2I& ptA, const VECTOR2I& ptB,
725 const STROKE_PARAMS& stroke )
726 {
727 SHAPE_SEGMENT seg( ptA, ptB, stroke.GetWidth() );
728 seg.TransformToPolygon( *layerPoly, table->GetMaxError(), ERROR_INSIDE );
729 } );
730 break;
731 }
732
734 case PCB_DIM_CENTER_T:
735 case PCB_DIM_RADIAL_T:
737 case PCB_DIM_LEADER_T:
738 {
739 PCB_DIMENSION_BASE* dimension = static_cast<PCB_DIMENSION_BASE*>( item );
740
741 dimension->TransformTextToPolySet( *layerPoly, 0, dimension->GetMaxError(), ERROR_INSIDE );
742
743 for( const std::shared_ptr<SHAPE>& shape : dimension->GetShapes() )
744 shape->TransformToPolygon( *layerPoly, dimension->GetMaxError(), ERROR_INSIDE );
745
746 break;
747 }
748
749 case PCB_REFERENCE_IMAGE_T: // ignore
750 break;
751
752 default:
753 wxLogTrace( m_logTrace, wxT( "createLayers: item type: %d not implemented" ), item->Type() );
754 break;
755 }
756 }
757 }
758 }
759
760 if( cfg.show_zones )
761 {
762 if( aStatusReporter )
763 aStatusReporter->Report( _( "Create zones" ) );
764
765 std::vector<std::pair<ZONE*, PCB_LAYER_ID>> zones;
766 std::unordered_map<PCB_LAYER_ID, std::unique_ptr<std::mutex>> layer_lock;
767
768 for( ZONE* zone : m_board->Zones() )
769 {
770 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
771 {
772 zones.emplace_back( std::make_pair( zone, layer ) );
773 layer_lock.emplace( layer, std::make_unique<std::mutex>() );
774
776 {
778
779 zone->TransformShapeToPolygon( *copperPolys, layer, 0, zone->GetMaxError(), ERROR_INSIDE );
780 }
781 }
782 }
783
784 // Add zones objects
785 std::atomic<size_t> nextZone( 0 );
786 std::atomic<size_t> threadsFinished( 0 );
787
788 size_t parallelThreadCount = std::min<size_t>( zones.size(),
789 std::max<size_t>( std::thread::hardware_concurrency(), 2 ) );
790
791 for( size_t ii = 0; ii < parallelThreadCount; ++ii )
792 {
793 std::thread t = std::thread( [&]()
794 {
795 for( size_t areaId = nextZone.fetch_add( 1 );
796 areaId < zones.size();
797 areaId = nextZone.fetch_add( 1 ) )
798 {
799 ZONE* zone = zones[areaId].first;
800
801 if( zone == nullptr )
802 break;
803
804 PCB_LAYER_ID layer = zones[areaId].second;
805
806 if( m_layerMap.contains( layer ) )
807 addSolidAreasShapes( zone, m_layerMap[layer], layer );
808
810 && m_layers_poly.contains( layer ) )
811 {
812 auto mut_it = layer_lock.find( layer );
813
814 if( mut_it != layer_lock.end() )
815 {
816 std::lock_guard< std::mutex > lock( *( mut_it->second ) );
818 }
819 }
820 }
821
822 threadsFinished++;
823 } );
824
825 t.detach();
826 }
827
828 while( threadsFinished < parallelThreadCount )
829 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
830 }
831 // End Build Copper layers
832
833 // This will make a union of all added contours
834 m_TH_ODPolys.Simplify();
835 m_NPTH_ODPolys.Simplify();
836 m_viaTH_ODPolys.Simplify();
837 m_viaAnnuliPolys.Simplify();
838
839 // Build Tech layers
840 // Based on:
841 // https://github.com/KiCad/kicad-source-mirror/blob/master/3d-viewer/3d_draw.cpp#L1059
842 if( aStatusReporter )
843 aStatusReporter->Report( _( "Build Tech layers" ) );
844
845 // draw graphic items, on technical layers
846
847 LSEQ techLayerList = LSET::AllNonCuMask().Seq( {
848 B_Adhes,
849 F_Adhes,
850 B_Paste,
851 F_Paste,
852 B_SilkS,
853 F_SilkS,
854 B_Mask,
855 F_Mask,
856
857 // Aux Layers
858 Dwgs_User,
859 Cmts_User,
860 Eco1_User,
861 Eco2_User,
862 User_1,
863 User_2,
864 User_3,
865 User_4,
866 User_5,
867 User_6,
868 User_7,
869 User_8,
870 User_9,
871 User_10,
872 User_11,
873 User_12,
874 User_13,
875 User_14,
876 User_15,
877 User_16,
878 User_17,
879 User_18,
880 User_19,
881 User_20,
882 User_21,
883 User_22,
884 User_23,
885 User_24,
886 User_25,
887 User_26,
888 User_27,
889 User_28,
890 User_29,
891 User_30,
892 User_31,
893 User_32,
894 User_33,
895 User_34,
896 User_35,
897 User_36,
898 User_37,
899 User_38,
900 User_39,
901 User_40,
902 User_41,
903 User_42,
904 User_43,
905 User_44,
906 User_45,
907 } );
908
909 std::bitset<LAYER_3D_END> enabledFlags = visibilityFlags;
910
912 {
913 enabledFlags.set( LAYER_3D_SOLDERMASK_TOP );
914 enabledFlags.set( LAYER_3D_SOLDERMASK_BOTTOM );
915 }
916
917 for( PCB_LAYER_ID layer : techLayerList )
918 {
919 if( aStatusReporter )
920 aStatusReporter->Report( wxString::Format( _( "Build Tech layer %d" ), (int) layer ) );
921
922 if( !Is3dLayerEnabled( layer, enabledFlags ) )
923 continue;
924
925 BVH_CONTAINER_2D *layerContainer = new BVH_CONTAINER_2D;
926 m_layerMap[layer] = layerContainer;
927
928 SHAPE_POLY_SET *layerPoly = new SHAPE_POLY_SET;
929 m_layers_poly[layer] = layerPoly;
930
931 if( Is3dLayerEnabled( layer, visibilityFlags ) )
932 {
933 // Add drawing objects
934 for( BOARD_ITEM* item : m_board->Drawings() )
935 {
936 if( !item->IsOnLayer( layer ) )
937 continue;
938
939 switch( item->Type() )
940 {
941 case PCB_SHAPE_T:
942 addShape( static_cast<PCB_SHAPE*>( item ), layerContainer, item, layer );
943 break;
944
945 case PCB_TEXT_T:
946 addText( static_cast<PCB_TEXT*>( item ), layerContainer, item );
947 break;
948
949 case PCB_TEXTBOX_T:
950 addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
951 break;
952
953 case PCB_TABLE_T:
954 addTable( static_cast<PCB_TABLE*>( item ), layerContainer, item );
955 break;
956
958 case PCB_DIM_CENTER_T:
959 case PCB_DIM_RADIAL_T:
961 case PCB_DIM_LEADER_T:
962 addShape( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer, item );
963 break;
964
965 default:
966 break;
967 }
968 }
969
970 // Add track, via and arc tech layers
971 if( IsSolderMaskLayer( layer ) )
972 {
973 for( PCB_TRACK* track : m_board->Tracks() )
974 {
975 if( !track->IsOnLayer( layer ) )
976 continue;
977
978 // Only vias on a external copper layer can have a solder mask
979 PCB_LAYER_ID copper_layer = ( layer == F_Mask ) ? F_Cu : B_Cu;
980
981 if( track->Type() == PCB_VIA_T )
982 {
983 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
984
985 if( !via->FlashLayer( copper_layer ) )
986 continue;
987 }
988
989 int maskExpansion = track->GetSolderMaskExpansion();
990 createTrackWithMargin( track, layerContainer, layer, maskExpansion );
991 }
992 }
993
994 // Add footprints tech layers - objects
995 for( FOOTPRINT* footprint : m_board->Footprints() )
996 {
997 if( layer == F_SilkS || layer == B_SilkS )
998 {
999 int linewidth = m_board->GetDesignSettings().m_LineThickness[ LAYER_CLASS_SILK ];
1000
1001 for( PAD* pad : footprint->Pads() )
1002 {
1003 if( !pad->IsOnLayer( layer ) )
1004 continue;
1005
1006 buildPadOutlineAsSegments( pad, layer, layerContainer, linewidth );
1007 }
1008 }
1009 else
1010 {
1011 addPads( footprint, layerContainer, layer );
1012 }
1013
1014 addFootprintShapes( footprint, layerContainer, layer, visibilityFlags );
1015 }
1016
1017 // Draw non copper zones
1018 if( cfg.show_zones )
1019 {
1020 for( ZONE* zone : m_board->Zones() )
1021 {
1022 if( zone->IsOnLayer( layer ) )
1023 addSolidAreasShapes( zone, layerContainer, layer );
1024 }
1025 }
1026 }
1027
1028 // Add item contours. We need these if we're building vertical walls or if this is a
1029 // mask layer and we're differentiating copper from plated copper.
1031 || ( cfg.DifferentiatePlatedCopper() && ( layer == F_Mask || layer == B_Mask ) ) )
1032 {
1033 // DRAWINGS
1034 for( BOARD_ITEM* item : m_board->Drawings() )
1035 {
1036 if( !item->IsOnLayer( layer ) )
1037 continue;
1038
1039 switch( item->Type() )
1040 {
1041 case PCB_SHAPE_T:
1042 item->TransformShapeToPolySet( *layerPoly, layer, 0, item->GetMaxError(), ERROR_INSIDE );
1043 break;
1044
1045 case PCB_TEXT_T:
1046 {
1047 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
1048
1049 text->TransformTextToPolySet( *layerPoly, 0, text->GetMaxError(), ERROR_INSIDE );
1050 break;
1051 }
1052
1053 case PCB_TEXTBOX_T:
1054 {
1055 PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
1056
1057 if( textbox->IsBorderEnabled() )
1058 {
1059 textbox->PCB_SHAPE::TransformShapeToPolygon( *layerPoly, layer, 0, textbox->GetMaxError(),
1060 ERROR_INSIDE );
1061 }
1062
1063 textbox->TransformTextToPolySet( *layerPoly, 0, textbox->GetMaxError(), ERROR_INSIDE );
1064 break;
1065 }
1066
1067 case PCB_TABLE_T:
1068 {
1069 PCB_TABLE* table = static_cast<PCB_TABLE*>( item );
1070
1071 for( PCB_TABLECELL* cell : table->GetCells() )
1072 cell->TransformTextToPolySet( *layerPoly, 0, cell->GetMaxError(), ERROR_INSIDE );
1073
1074 table->DrawBorders(
1075 [&]( const VECTOR2I& ptA, const VECTOR2I& ptB,
1076 const STROKE_PARAMS& stroke )
1077 {
1078 SHAPE_SEGMENT seg( ptA, ptB, stroke.GetWidth() );
1079 seg.TransformToPolygon( *layerPoly, table->GetMaxError(), ERROR_INSIDE );
1080 } );
1081
1082 break;
1083 }
1084
1085 default:
1086 break;
1087 }
1088 }
1089
1090 // NON-TENTED VIAS
1091 if( ( layer == F_Mask || layer == B_Mask ) )
1092 {
1093 int maskExpansion = GetBoard()->GetDesignSettings().m_SolderMaskExpansion;
1094
1095 for( PCB_TRACK* track : m_board->Tracks() )
1096 {
1097 if( track->Type() == PCB_VIA_T )
1098 {
1099 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
1100
1101 if( via->FlashLayer( layer ) && !via->IsTented( layer ) )
1102 {
1103 track->TransformShapeToPolygon( *layerPoly, layer, maskExpansion, track->GetMaxError(),
1104 ERROR_INSIDE );
1105 }
1106 }
1107 else
1108 {
1109 if( track->HasSolderMask() )
1110 {
1111 track->TransformShapeToPolySet( *layerPoly, layer, maskExpansion, track->GetMaxError(),
1112 ERROR_INSIDE );
1113 }
1114 }
1115 }
1116 }
1117
1118 // FOOTPRINT CHILDREN
1119 for( FOOTPRINT* footprint : m_board->Footprints() )
1120 {
1121 if( layer == F_SilkS || layer == B_SilkS )
1122 {
1123 int linewidth = m_board->GetDesignSettings().m_LineThickness[ LAYER_CLASS_SILK ];
1124
1125 for( PAD* pad : footprint->Pads() )
1126 {
1127 if( pad->IsOnLayer( layer ) )
1128 {
1129 buildPadOutlineAsPolygon( pad, layer, *layerPoly, linewidth, pad->GetMaxError(),
1130 ERROR_INSIDE );
1131 }
1132 }
1133 }
1134 else
1135 {
1136 footprint->TransformPadsToPolySet( *layerPoly, layer, 0, footprint->GetMaxError(), ERROR_INSIDE );
1137 }
1138
1139 transformFPTextToPolySet( footprint, layer, visibilityFlags, *layerPoly, footprint->GetMaxError(),
1140 ERROR_INSIDE );
1141 transformFPShapesToPolySet( footprint, layer, *layerPoly, footprint->GetMaxError(), ERROR_INSIDE );
1142 }
1143
1144 if( cfg.show_zones || layer == F_Mask || layer == B_Mask )
1145 {
1146 for( ZONE* zone : m_board->Zones() )
1147 {
1148 if( zone->IsOnLayer( layer ) )
1149 zone->TransformSolidAreasShapesToPolygon( layer, *layerPoly );
1150 }
1151 }
1152
1153 // This will make a union of all added contours
1154 layerPoly->Simplify();
1155 }
1156 }
1157 // End Build Tech layers
1158
1159 // If we're rendering off-board silk, also render pads of footprints which are entirely
1160 // outside the board outline. This makes off-board footprints more visually recognizable.
1161 if( cfg.show_off_board_silk )
1162 {
1163 BOX2I boardBBox = m_board_poly.BBox();
1164
1165 for( FOOTPRINT* footprint : m_board->Footprints() )
1166 {
1167 if( !footprint->GetBoundingBox().Intersects( boardBBox ) )
1168 {
1169 if( footprint->IsFlipped() )
1170 addPads( footprint, m_offboardPadsBack, B_Cu );
1171 else
1172 addPads( footprint, m_offboardPadsFront, F_Cu );
1173 }
1174 }
1175
1176 m_offboardPadsFront->BuildBVH();
1177 m_offboardPadsBack->BuildBVH();
1178 }
1179
1180 // Simplify layer polygons
1181
1182 if( aStatusReporter )
1183 aStatusReporter->Report( _( "Simplifying copper layer polygons" ) );
1184
1185 if( cfg.DifferentiatePlatedCopper() )
1186 {
1187 if( aStatusReporter )
1188 aStatusReporter->Report( _( "Calculating plated copper" ) );
1189
1190 // TRIM PLATED COPPER TO SOLDERMASK
1191 if( m_layers_poly.contains( F_Mask ) )
1192 m_frontPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( F_Mask ) );
1193
1194 if( m_layers_poly.contains( B_Mask ))
1195 m_backPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( B_Mask ) );
1196
1197 // Subtract plated copper from unplated copper
1198 if( m_layers_poly.contains( F_Cu ) )
1199 m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedCopperPolys );
1200
1201 if( m_layers_poly.contains( B_Cu ) )
1202 m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedCopperPolys );
1203
1204 // ADD PLATED COPPER
1207
1210
1211 m_platedPadsFront->BuildBVH();
1212 m_platedPadsBack->BuildBVH();
1213 }
1214
1216 {
1217 std::vector<PCB_LAYER_ID> &selected_layer_id = layer_ids;
1218 std::vector<PCB_LAYER_ID> layer_id_without_F_and_B;
1219
1220 if( cfg.DifferentiatePlatedCopper() )
1221 {
1222 layer_id_without_F_and_B.clear();
1223 layer_id_without_F_and_B.reserve( layer_ids.size() );
1224
1225 for( PCB_LAYER_ID layer: layer_ids )
1226 {
1227 if( layer != F_Cu && layer != B_Cu )
1228 layer_id_without_F_and_B.push_back( layer );
1229 }
1230
1231 selected_layer_id = layer_id_without_F_and_B;
1232 }
1233
1234 if( selected_layer_id.size() > 0 )
1235 {
1236 if( aStatusReporter )
1237 {
1238 aStatusReporter->Report( wxString::Format( _( "Simplifying %d copper layers" ),
1239 (int) selected_layer_id.size() ) );
1240 }
1241
1242 std::atomic<size_t> nextItem( 0 );
1243 std::atomic<size_t> threadsFinished( 0 );
1244
1245 size_t parallelThreadCount = std::min<size_t>(
1246 std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
1247 selected_layer_id.size() );
1248
1249 for( size_t ii = 0; ii < parallelThreadCount; ++ii )
1250 {
1251 std::thread t = std::thread(
1252 [&nextItem, &threadsFinished, &selected_layer_id, this]()
1253 {
1254 for( size_t i = nextItem.fetch_add( 1 );
1255 i < selected_layer_id.size();
1256 i = nextItem.fetch_add( 1 ) )
1257 {
1258 if( m_layers_poly.contains( selected_layer_id[i] ) )
1259 {
1260 // This will make a union of all added contours
1261 m_layers_poly[ selected_layer_id[i] ]->ClearArcs();
1262 m_layers_poly[ selected_layer_id[i] ]->Simplify();
1263 }
1264 }
1265
1266 threadsFinished++;
1267 } );
1268
1269 t.detach();
1270 }
1271
1272 while( threadsFinished < parallelThreadCount )
1273 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1274 }
1275 }
1276
1277 // Simplify holes polygon contours
1278 if( aStatusReporter )
1279 aStatusReporter->Report( _( "Simplify holes contours" ) );
1280
1281 for( PCB_LAYER_ID layer : layer_ids )
1282 {
1283 if( m_layerHoleOdPolys.contains( layer ) )
1284 {
1285 // found
1286 SHAPE_POLY_SET *polyLayer = m_layerHoleOdPolys[layer];
1287 polyLayer->Simplify();
1288
1289 wxASSERT( m_layerHoleIdPolys.contains( layer ) );
1290
1291 polyLayer = m_layerHoleIdPolys[layer];
1292 polyLayer->Simplify();
1293 }
1294 }
1295
1296 // Build BVH (Bounding volume hierarchy) for holes and vias
1297
1298 if( aStatusReporter )
1299 aStatusReporter->Report( _( "Build BVH for holes and vias" ) );
1300
1301 m_TH_IDs.BuildBVH();
1302 m_TH_ODs.BuildBVH();
1303 m_viaAnnuli.BuildBVH();
1304
1305 if( !m_layerHoleMap.empty() )
1306 {
1307 for( std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& hole : m_layerHoleMap )
1308 hole.second->BuildBVH();
1309 }
1310
1311 // We only need the Solder mask to initialize the BVH
1312 // because..?
1313 if( m_layerMap[B_Mask] )
1314 m_layerMap[B_Mask]->BuildBVH();
1315
1316 if( m_layerMap[F_Mask] )
1317 m_layerMap[F_Mask]->BuildBVH();
1318}
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ ERROR_INSIDE
@ LAYER_CLASS_SILK
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
MAP_CONTAINER_2D_BASE m_layerHoleMap
Holes for each layer.
double BiuTo3dUnits() const noexcept
Board integer units To 3D units.
BVH_CONTAINER_2D * m_offboardPadsBack
void createLayers(REPORTER *aStatusReporter)
SHAPE_POLY_SET m_TH_ODPolys
PTH outer diameters.
void addPads(const FOOTPRINT *aFootprint, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayerId)
unsigned int m_viaCount
void createTrackWithMargin(const PCB_TRACK *aTrack, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayer, int aMargin=0)
MAP_POLY m_layerHoleOdPolys
Hole outer diameters (per layer)
void addSolidAreasShapes(const ZONE *aZone, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayerId)
SHAPE_POLY_SET * m_frontPlatedCopperPolys
MAP_CONTAINER_2D_BASE m_layerMap
2D elements for each layer.
BVH_CONTAINER_2D m_TH_ODs
List of PTH outer diameters.
unsigned int m_trackCount
float m_averageTrackWidth
SHAPE_POLY_SET m_board_poly
Board outline polygon.
std::bitset< LAYER_3D_END > GetVisibleLayers() const
void addFootprintShapes(const FOOTPRINT *aFootprint, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayerId, const std::bitset< LAYER_3D_END > &aVisibilityFlags)
MAP_POLY m_layerHoleIdPolys
Hole inner diameters (per layer)
int GetHolePlatingThickness() const noexcept
Get the hole plating thickness (NB: in BOARD UNITS!).
SHAPE_POLY_SET m_viaAnnuliPolys
Via annular ring outer diameters.
BVH_CONTAINER_2D * m_offboardPadsFront
float m_averageViaHoleDiameter
BVH_CONTAINER_2D m_viaTH_ODs
List of via hole outer diameters.
float m_averageHoleDiameter
SHAPE_POLY_SET m_viaTH_ODPolys
Via hole outer diameters.
const BOARD * GetBoard() const noexcept
BVH_CONTAINER_2D * m_platedPadsBack
void buildPadOutlineAsSegments(const PAD *aPad, PCB_LAYER_ID aLayer, CONTAINER_2D_BASE *aDstContainer, int aWidth)
MAP_POLY m_layers_poly
Amalgamated polygon contours for various types of items.
SHAPE_POLY_SET * m_backPlatedCopperPolys
EDA_3D_VIEWER_SETTINGS * m_Cfg
void addTable(const PCB_TABLE *aTable, CONTAINER_2D_BASE *aContainer, const BOARD_ITEM *aOwner)
void createPadHoleShape(const PAD *aPad, CONTAINER_2D_BASE *aDstContainer, int aInflateValue)
unsigned int m_holeCount
BVH_CONTAINER_2D m_viaAnnuli
List of via annular rings.
unsigned int m_copperLayersCount
BVH_CONTAINER_2D m_TH_IDs
List of PTH inner diameters.
BVH_CONTAINER_2D * m_platedPadsFront
void addShape(const PCB_SHAPE *aShape, CONTAINER_2D_BASE *aContainer, const BOARD_ITEM *aOwner, PCB_LAYER_ID aLayer)
SHAPE_POLY_SET m_NPTH_ODPolys
NPTH outer diameters.
bool Is3dLayerEnabled(PCB_LAYER_ID aLayer, const std::bitset< LAYER_3D_END > &aVisibilityFlags) const
Check if a layer is enabled.
double m_biuTo3Dunits
Scale factor to convert board internal units to 3D units normalized between -1.0 and 1....
void addText(const EDA_TEXT *aText, CONTAINER_2D_BASE *aDstContainer, const BOARD_ITEM *aOwner)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:79
int GetMaxError() const
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1040
void Add(OBJECT_2D *aObject)
static DELETED_BOARD_ITEM * GetInstance()
Definition board_item.h:490
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
DRAWINGS & GraphicalItems()
Definition footprint.h:227
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition lseq.h:47
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition lset.cpp:610
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition lset.cpp:296
Definition pad.h:54
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition pad.h:195
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(PCB_LAYER_ID aLayer, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Definition pad.cpp:525
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1068
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) const
Definition pad.h:264
Abstract dimension API.
const std::vector< std::shared_ptr< SHAPE > > & GetShapes() const
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition pcb_shape.h:71
bool IsBorderEnabled() const
Disables the border, this is done by changing the stroke internally.
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
Definition pcb_text.cpp:568
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the track shape to a closed polygon.
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
bool FlashLayer(int aLayer) const
Check to see whether the via should have a pad on the specific layer.
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition reporter.h:102
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
void TransformToPolygon(SHAPE_POLY_SET &aBuffer, int aError, ERROR_LOC aErrorLoc) const override
Fills a SHAPE_POLY_SET with a polygon representation of this shape.
Simple container to manage line stroke parameters.
int GetWidth() const
Handle a list of polygons defining a copper zone.
Definition zone.h:74
void TransformSolidAreasShapesToPolygon(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aBuffer) const
Convert solid areas full shapes to polygon set (the full shape is the polygon area with a thick outli...
Definition zone.cpp:1606
void TransformRingToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aCentre, int aRadius, int aWidth, int aError, ERROR_LOC aErrorLoc)
Convert arcs to multiple straight segments.
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
#define DELETE_AND_FREE_MAP(map)
void transformFPShapesToPolySet(const FOOTPRINT *aFootprint, PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aBuffer, int aMaxError, ERROR_LOC aErrorLoc)
void transformFPTextToPolySet(const FOOTPRINT *aFootprint, PCB_LAYER_ID aLayer, const std::bitset< LAYER_3D_END > &aFlags, SHAPE_POLY_SET &aBuffer, int aMaxError, ERROR_LOC aErrorLoc)
void buildPadOutlineAsPolygon(const PAD *aPad, PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aBuffer, int aWidth, int aMaxError, ERROR_LOC aErrorLoc)
#define DELETE_AND_FREE(ptr)
#define _(s)
static const wxChar * m_logTrace
Trace mask used to enable or disable debug output for this class.
bool IsSolderMaskLayer(int aLayer)
Definition layer_ids.h:744
@ LAYER_3D_SOLDERMASK_TOP
Definition layer_ids.h:557
@ LAYER_3D_SOLDERMASK_BOTTOM
Definition layer_ids.h:556
@ LAYER_FP_REFERENCES
Show footprints references (when texts are visible).
Definition layer_ids.h:265
@ LAYER_FP_TEXT
Definition layer_ids.h:239
@ LAYER_FP_VALUES
Show footprints values (when texts are visible).
Definition layer_ids.h:262
bool IsExternalCopperLayer(int aLayerId)
Test whether a layer is an external (F_Cu or B_Cu) copper layer.
Definition layer_ids.h:685
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ User_16
Definition layer_ids.h:139
@ User_29
Definition layer_ids.h:152
@ User_40
Definition layer_ids.h:163
@ User_15
Definition layer_ids.h:138
@ User_8
Definition layer_ids.h:131
@ User_11
Definition layer_ids.h:134
@ User_25
Definition layer_ids.h:148
@ User_34
Definition layer_ids.h:157
@ User_45
Definition layer_ids.h:168
@ B_Adhes
Definition layer_ids.h:103
@ User_36
Definition layer_ids.h:159
@ Dwgs_User
Definition layer_ids.h:107
@ F_Paste
Definition layer_ids.h:104
@ Cmts_User
Definition layer_ids.h:108
@ User_6
Definition layer_ids.h:129
@ User_7
Definition layer_ids.h:130
@ User_19
Definition layer_ids.h:142
@ User_23
Definition layer_ids.h:146
@ F_Adhes
Definition layer_ids.h:102
@ User_41
Definition layer_ids.h:164
@ B_Mask
Definition layer_ids.h:98
@ B_Cu
Definition layer_ids.h:65
@ User_14
Definition layer_ids.h:137
@ User_39
Definition layer_ids.h:162
@ User_5
Definition layer_ids.h:128
@ User_20
Definition layer_ids.h:143
@ Eco1_User
Definition layer_ids.h:109
@ F_Mask
Definition layer_ids.h:97
@ User_42
Definition layer_ids.h:165
@ User_43
Definition layer_ids.h:166
@ B_Paste
Definition layer_ids.h:105
@ User_10
Definition layer_ids.h:133
@ User_9
Definition layer_ids.h:132
@ User_27
Definition layer_ids.h:150
@ User_28
Definition layer_ids.h:151
@ F_SilkS
Definition layer_ids.h:100
@ UNDEFINED_LAYER
Definition layer_ids.h:61
@ Eco2_User
Definition layer_ids.h:110
@ User_35
Definition layer_ids.h:158
@ User_31
Definition layer_ids.h:154
@ User_3
Definition layer_ids.h:126
@ User_1
Definition layer_ids.h:124
@ User_12
Definition layer_ids.h:135
@ B_SilkS
Definition layer_ids.h:101
@ User_30
Definition layer_ids.h:153
@ User_37
Definition layer_ids.h:160
@ User_22
Definition layer_ids.h:145
@ User_38
Definition layer_ids.h:161
@ User_4
Definition layer_ids.h:127
@ User_21
Definition layer_ids.h:144
@ User_24
Definition layer_ids.h:147
@ User_13
Definition layer_ids.h:136
@ User_2
Definition layer_ids.h:125
@ User_17
Definition layer_ids.h:140
@ User_33
Definition layer_ids.h:156
@ User_26
Definition layer_ids.h:149
@ User_32
Definition layer_ids.h:155
@ User_18
Definition layer_ids.h:141
@ User_44
Definition layer_ids.h:167
@ F_Cu
Definition layer_ids.h:64
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:87
VIATYPE
Definition pcb_track.h:66
@ THROUGH
Definition pcb_track.h:67
int64_t GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
bool DifferentiatePlatedCopper()
return true if platted copper aeras and non platted copper areas must be drawn using a different colo...
void ConvertPolygonToTriangles(const SHAPE_POLY_SET &aPolyList, CONTAINER_2D_BASE &aDstContainer, float aBiuTo3dUnitsScale, const BOARD_ITEM &aBoardItem)
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
Definition typeinfo.h:252
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:88
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition typeinfo.h:105
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:102
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:97
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition typeinfo.h:103
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:93
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:92
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
Definition typeinfo.h:89
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:101
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition typeinfo.h:100
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition typeinfo.h:94
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition typeinfo.h:104
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
glm::vec2 SFVEC2F
Definition xv3d_types.h:42