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