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 (C) 1992-2024 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
35#include "board_adapter.h"
36#include "../3d_rendering/raytracing/shapes2D/filled_circle_2d.h"
39#include <board.h>
40#include <footprint.h>
41#include <pad.h>
42#include <pcb_text.h>
43#include <pcb_textbox.h>
44#include <pcb_table.h>
45#include <pcb_shape.h>
46#include <zone.h>
48#include <trigo.h>
49#include <vector>
50#include <thread>
51#include <core/arraydim.h>
52#include <algorithm>
53#include <atomic>
54#include <wx/log.h>
55
56#ifdef PRINT_STATISTICS_3D_VIEWER
57#include <core/profile.h>
58#endif
59
60
61
62
63/*
64 * This is used to draw pad outlines on silk layers.
65 */
66void buildPadOutlineAsPolygon( const PAD* aPad, SHAPE_POLY_SET& aBuffer, int aWidth, int aMaxError,
67 ERROR_LOC aErrorLoc )
68{
69 if( aPad->GetShape() == PAD_SHAPE::CIRCLE ) // Draw a ring
70 {
71 TransformRingToPolygon( aBuffer, aPad->ShapePos(), aPad->GetSize().x / 2, aWidth,
72 aMaxError, aErrorLoc );
73 }
74 else
75 {
76 // For other shapes, add outlines as thick segments in polygon buffer
77 const SHAPE_LINE_CHAIN& path = aPad->GetEffectivePolygon( ERROR_INSIDE )->COutline( 0 );
78
79 for( int ii = 0; ii < path.PointCount(); ++ii )
80 {
81 const VECTOR2I& a = path.CPoint( ii );
82 const VECTOR2I& b = path.CPoint( ii + 1 );
83
84 TransformOvalToPolygon( aBuffer, a, b, aWidth, aMaxError, aErrorLoc );
85 }
86 }
87}
88
89
90void transformFPShapesToPolySet( const FOOTPRINT* aFootprint, PCB_LAYER_ID aLayer,
91 SHAPE_POLY_SET& aBuffer, int aMaxError, ERROR_LOC aErrorLoc )
92{
93 for( BOARD_ITEM* item : aFootprint->GraphicalItems() )
94 {
95 if( item->Type() == PCB_SHAPE_T || BaseType( item->Type() ) == PCB_DIMENSION_T )
96 {
97 if( item->GetLayer() == aLayer )
98 item->TransformShapeToPolygon( aBuffer, aLayer, 0, aMaxError, aErrorLoc );
99 }
100 }
101}
102
103
105{
106#define DELETE_AND_FREE( ptr ) \
107 { \
108 delete ptr; \
109 ptr = nullptr; \
110 } \
111
112#define DELETE_AND_FREE_MAP( map ) \
113 { \
114 for( auto& [ layer, poly ] : map ) \
115 delete poly; \
116 \
117 map.clear(); \
118 }
119
121
126
129
134
137
142
143 m_TH_ODs.Clear();
144 m_TH_IDs.Clear();
147}
148
149
150void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
151{
153
154 // Build Copper layers
155 // Based on:
156 // https://github.com/KiCad/kicad-source-mirror/blob/master/3d-viewer/3d_draw.cpp#L692
157
158#ifdef PRINT_STATISTICS_3D_VIEWER
159 int64_t stats_startCopperLayersTime = GetRunningMicroSecs();
160
161 int64_t start_Time = stats_startCopperLayersTime;
162#endif
163
166
168
169 std::bitset<LAYER_3D_END> visibilityFlags = GetVisibleLayers();
170
171 m_trackCount = 0;
173 m_viaCount = 0;
175 m_holeCount = 0;
177
178 if( !m_board )
179 return;
180
181 // Prepare track list, convert in a vector. Calc statistic for the holes
182 std::vector<const PCB_TRACK*> trackList;
183 trackList.clear();
184 trackList.reserve( m_board->Tracks().size() );
185
186 int maxError = m_board->GetDesignSettings().m_MaxError;
187
188 for( PCB_TRACK* track : m_board->Tracks() )
189 {
190 if( !Is3dLayerEnabled( track->GetLayer(), visibilityFlags ) ) // Skip non enabled layers
191 continue;
192
193 // Note: a PCB_TRACK holds normal segment tracks and also vias circles (that have also
194 // drill values)
195 trackList.push_back( track );
196
197 if( track->Type() == PCB_VIA_T )
198 {
199 const PCB_VIA *via = static_cast< const PCB_VIA*>( track );
200 m_viaCount++;
201 m_averageViaHoleDiameter += static_cast<float>( via->GetDrillValue() * m_biuTo3Dunits );
202 }
203 else
204 {
205 m_trackCount++;
206 }
207
208 m_averageTrackWidth += static_cast<float>( track->GetWidth() * m_biuTo3Dunits );
209 }
210
211 if( m_trackCount )
213
214 if( m_viaCount )
216
217 // Prepare copper layers index and containers
218 std::vector<PCB_LAYER_ID> layer_ids;
219 layer_ids.clear();
220 layer_ids.reserve( m_copperLayersCount );
221
222 for( unsigned i = 0; i < arrayDim( cu_seq ); ++i )
223 cu_seq[i] = ToLAYER_ID( B_Cu - i );
224
225 for( LSEQ cu = cu_set.Seq( cu_seq, arrayDim( cu_seq ) ); cu; ++cu )
226 {
227 const PCB_LAYER_ID layer = *cu;
228
229 if( !Is3dLayerEnabled( layer, visibilityFlags ) ) // Skip non enabled layers
230 continue;
231
232 layer_ids.push_back( layer );
233
234 BVH_CONTAINER_2D *layerContainer = new BVH_CONTAINER_2D;
235 m_layerMap[layer] = layerContainer;
236
237 if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL )
238 {
239 SHAPE_POLY_SET* layerPoly = new SHAPE_POLY_SET;
240 m_layers_poly[layer] = layerPoly;
241 }
242 }
243
245 {
250
253 }
254
255 if( cfg.show_off_board_silk )
256 {
259 }
260
261 if( aStatusReporter )
262 aStatusReporter->Report( _( "Create tracks and vias" ) );
263
264 // Create tracks as objects and add it to container
265 for( PCB_LAYER_ID layer : layer_ids )
266 {
267 wxASSERT( m_layerMap.find( layer ) != m_layerMap.end() );
268
269 BVH_CONTAINER_2D *layerContainer = m_layerMap[layer];
270
271 for( const PCB_TRACK* track : trackList )
272 {
273 // NOTE: Vias can be on multiple layers
274 if( !track->IsOnLayer( layer ) )
275 continue;
276
277 // Skip vias annulus when not flashed on this layer
278 if( track->Type() == PCB_VIA_T
279 && !static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
280 {
281 continue;
282 }
283
284 // Add object item to layer container
285 createTrack( track, layerContainer );
286 }
287 }
288
289 // Create VIAS and THTs objects and add it to holes containers
290 for( PCB_LAYER_ID layer : layer_ids )
291 {
292 // ADD TRACKS
293 unsigned int nTracks = trackList.size();
294
295 for( unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
296 {
297 const PCB_TRACK *track = trackList[trackIdx];
298
299 if( !track->IsOnLayer( layer ) )
300 continue;
301
302 // ADD VIAS and THT
303 if( track->Type() == PCB_VIA_T )
304 {
305 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
306 const VIATYPE viatype = via->GetViaType();
307 const double holediameter = via->GetDrillValue() * BiuTo3dUnits();
308 const double viasize = via->GetWidth() * BiuTo3dUnits();
309 const double plating = GetHolePlatingThickness() * BiuTo3dUnits();
310
311 // holes and layer copper extend half info cylinder wall to hide transition
312 const float thickness = static_cast<float>( plating / 2.0f );
313 const float hole_inner_radius = static_cast<float>( holediameter / 2.0f );
314 const float ring_radius = static_cast<float>( viasize / 2.0f );
315
316 const SFVEC2F via_center( via->GetStart().x * m_biuTo3Dunits,
317 -via->GetStart().y * m_biuTo3Dunits );
318
319 if( viatype != VIATYPE::THROUGH )
320 {
321 // Add hole objects
322 BVH_CONTAINER_2D *layerHoleContainer = nullptr;
323
324 // Check if the layer is already created
325 if( m_layerHoleMap.find( layer ) == m_layerHoleMap.end() )
326 {
327 // not found, create a new container
328 layerHoleContainer = new BVH_CONTAINER_2D;
329 m_layerHoleMap[layer] = layerHoleContainer;
330 }
331 else
332 {
333 // found
334 layerHoleContainer = m_layerHoleMap[layer];
335 }
336
337 // Add a hole for this layer
338 layerHoleContainer->Add( new FILLED_CIRCLE_2D( via_center,
339 hole_inner_radius + thickness,
340 *track ) );
341 }
342 else if( layer == layer_ids[0] ) // it only adds once the THT holes
343 {
344 // Add through hole object
345 m_TH_ODs.Add( new FILLED_CIRCLE_2D( via_center, hole_inner_radius + thickness,
346 *track ) );
347 m_viaTH_ODs.Add( new FILLED_CIRCLE_2D( via_center, hole_inner_radius + thickness,
348 *track ) );
349
350 if( cfg.clip_silk_on_via_annuli && ring_radius > 0.0 )
351 m_viaAnnuli.Add( new FILLED_CIRCLE_2D( via_center, ring_radius, *track ) );
352
353 if( hole_inner_radius > 0.0 )
354 m_TH_IDs.Add( new FILLED_CIRCLE_2D( via_center, hole_inner_radius, *track ) );
355 }
356 }
357
358 if( cfg.differentiate_plated_copper && layer == F_Cu )
359 {
361 ERROR_INSIDE );
362 }
363 else if( cfg.differentiate_plated_copper && layer == B_Cu )
364 {
366 ERROR_INSIDE );
367 }
368 }
369 }
370
371 // Create VIAS and THTs objects and add it to holes containers
372 for( PCB_LAYER_ID layer : layer_ids )
373 {
374 // ADD TRACKS
375 const unsigned int nTracks = trackList.size();
376
377 for( unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
378 {
379 const PCB_TRACK *track = trackList[trackIdx];
380
381 if( !track->IsOnLayer( layer ) )
382 continue;
383
384 // ADD VIAS and THT
385 if( track->Type() == PCB_VIA_T )
386 {
387 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
388 const VIATYPE viatype = via->GetViaType();
389
390 if( viatype != VIATYPE::THROUGH )
391 {
392 // Add PCB_VIA hole contours
393
394 // Add outer holes of VIAs
395 SHAPE_POLY_SET *layerOuterHolesPoly = nullptr;
396 SHAPE_POLY_SET *layerInnerHolesPoly = nullptr;
397
398 // Check if the layer is already created
399 if( m_layerHoleOdPolys.find( layer ) == m_layerHoleOdPolys.end() )
400 {
401 // not found, create a new container
402 layerOuterHolesPoly = new SHAPE_POLY_SET;
403 m_layerHoleOdPolys[layer] = layerOuterHolesPoly;
404
405 wxASSERT( m_layerHoleIdPolys.find( layer ) == m_layerHoleIdPolys.end() );
406
407 layerInnerHolesPoly = new SHAPE_POLY_SET;
408 m_layerHoleIdPolys[layer] = layerInnerHolesPoly;
409 }
410 else
411 {
412 // found
413 layerOuterHolesPoly = m_layerHoleOdPolys[layer];
414
415 wxASSERT( m_layerHoleIdPolys.find( layer ) != m_layerHoleIdPolys.end() );
416
417 layerInnerHolesPoly = m_layerHoleIdPolys[layer];
418 }
419
420 const int holediameter = via->GetDrillValue();
421 const int hole_outer_radius = (holediameter / 2) + GetHolePlatingThickness();
422
423 TransformCircleToPolygon( *layerOuterHolesPoly, via->GetStart(),
424 hole_outer_radius, maxError, ERROR_INSIDE );
425
426 TransformCircleToPolygon( *layerInnerHolesPoly, via->GetStart(),
427 holediameter / 2, maxError, ERROR_INSIDE );
428 }
429 else if( layer == layer_ids[0] ) // it only adds once the THT holes
430 {
431 const int holediameter = via->GetDrillValue();
432 const int hole_outer_radius = (holediameter / 2) + GetHolePlatingThickness();
433 const int hole_outer_ring_radius = KiROUND( via->GetWidth() / 2.0 );
434
435 // Add through hole contours
436 TransformCircleToPolygon( m_TH_ODPolys, via->GetStart(), hole_outer_radius,
437 maxError, ERROR_INSIDE );
438
439 // Add same thing for vias only
440 TransformCircleToPolygon( m_viaTH_ODPolys, via->GetStart(), hole_outer_radius,
441 maxError, ERROR_INSIDE );
442
444 {
446 hole_outer_ring_radius, maxError, ERROR_INSIDE );
447 }
448 }
449 }
450 }
451 }
452
453 // Creates vertical outline contours of the tracks and add it to the poly of the layer
454 if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL )
455 {
456 for( PCB_LAYER_ID layer : layer_ids )
457 {
458 wxASSERT( m_layers_poly.find( layer ) != m_layers_poly.end() );
459
460 SHAPE_POLY_SET *layerPoly = m_layers_poly[layer];
461
462 // ADD TRACKS
463 unsigned int nTracks = trackList.size();
464
465 for( unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
466 {
467 const PCB_TRACK *track = trackList[trackIdx];
468
469 if( !track->IsOnLayer( layer ) )
470 continue;
471
472 // Skip vias annulus when not flashed on this layer
473 if( track->Type() == PCB_VIA_T
474 && !static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
475 {
476 continue;
477 }
478
479 // Add the track/via contour
480 track->TransformShapeToPolygon( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
481 }
482 }
483 }
484
485 // Add holes of footprints
486 for( FOOTPRINT* footprint : m_board->Footprints() )
487 {
488 for( PAD* pad : footprint->Pads() )
489 {
490 const VECTOR2I padHole = pad->GetDrillSize();
491
492 if( !padHole.x ) // Not drilled pad like SMD pad
493 continue;
494
495 // The hole in the body is inflated by copper thickness, if not plated, no copper
496 int inflate = 0;
497
498 if( pad->GetAttribute () != PAD_ATTRIB::NPTH )
499 inflate = KiROUND( GetHolePlatingThickness() / 2.0 );
500
501 m_holeCount++;
502 double holeDiameter = ( pad->GetDrillSize().x + pad->GetDrillSize().y ) / 2.0;
503 m_averageHoleDiameter += static_cast<float>( holeDiameter * m_biuTo3Dunits );
504
505 createPadWithHole( pad, &m_TH_ODs, inflate );
506
508 createPadWithHole( pad, &m_viaAnnuli, inflate );
509
511 }
512 }
513
514 if( m_holeCount )
516
517 // Add contours of the pad holes (pads can be Circle or Segment holes)
518 for( FOOTPRINT* footprint : m_board->Footprints() )
519 {
520 for( PAD* pad : footprint->Pads() )
521 {
522 const VECTOR2I padHole = pad->GetDrillSize();
523
524 if( !padHole.x ) // Not drilled pad like SMD pad
525 continue;
526
527 // The hole in the body is inflated by copper thickness.
528 const int inflate = GetHolePlatingThickness();
529
530 if( pad->GetAttribute () != PAD_ATTRIB::NPTH )
531 {
533 pad->TransformHoleToPolygon( m_viaAnnuliPolys, inflate, maxError, ERROR_INSIDE );
534
535 pad->TransformHoleToPolygon( m_TH_ODPolys, inflate, maxError, ERROR_INSIDE );
536 }
537 else
538 {
539 // If not plated, no copper.
541 pad->TransformHoleToPolygon( m_viaAnnuliPolys, 0, maxError, ERROR_INSIDE );
542
543 pad->TransformHoleToPolygon( m_NPTH_ODPolys, 0, maxError, ERROR_INSIDE );
544 }
545 }
546 }
547
548 // Add footprints PADs objects to containers
549 for( PCB_LAYER_ID layer : layer_ids )
550 {
551 wxASSERT( m_layerMap.find( layer ) != m_layerMap.end() );
552
553 BVH_CONTAINER_2D *layerContainer = m_layerMap[layer];
554
555 // ADD PADS
556 for( FOOTPRINT* footprint : m_board->Footprints() )
557 {
558 addPads( footprint, layerContainer, layer, cfg.differentiate_plated_copper, false );
559
560 // Micro-wave footprints may have items on copper layers
561 addFootprintShapes( footprint, layerContainer, layer, visibilityFlags );
562 }
563 }
564
565 // Add footprints PADs poly contours (vertical outlines)
566 if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL )
567 {
568 for( PCB_LAYER_ID layer : layer_ids )
569 {
570 wxASSERT( m_layers_poly.find( layer ) != m_layers_poly.end() );
571
572 SHAPE_POLY_SET *layerPoly = m_layers_poly[layer];
573
574 // Add pads to polygon list
575 for( FOOTPRINT* footprint : m_board->Footprints() )
576 {
577 // Note: NPTH pads are not drawn on copper layers when the pad has same shape as
578 // its hole
579 footprint->TransformPadsToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE,
580 true, cfg.differentiate_plated_copper, false );
581
582 transformFPShapesToPolySet( footprint, layer, *layerPoly, maxError, ERROR_INSIDE );
583 }
584 }
585
587 {
588 // ADD PLATED PADS contours
589 for( FOOTPRINT* footprint : m_board->Footprints() )
590 {
591 footprint->TransformPadsToPolySet( *m_frontPlatedPadAndGraphicPolys, F_Cu, 0, maxError,
592 ERROR_INSIDE, true, false, true );
593
594 footprint->TransformPadsToPolySet( *m_backPlatedPadAndGraphicPolys, B_Cu, 0, maxError,
595 ERROR_INSIDE, true, false, true );
596 }
597 }
598 }
599
600 // Add graphic item on copper layers to object containers
601 for( PCB_LAYER_ID layer : layer_ids )
602 {
603 wxASSERT( m_layerMap.find( layer ) != m_layerMap.end() );
604
605 BVH_CONTAINER_2D *layerContainer = m_layerMap[layer];
606
607 // Add graphic items on copper layers (texts and other graphics)
608 for( BOARD_ITEM* item : m_board->Drawings() )
609 {
610 if( !item->IsOnLayer( layer ) )
611 continue;
612
613 switch( item->Type() )
614 {
615 case PCB_SHAPE_T:
616 addShape( static_cast<PCB_SHAPE*>( item ), layerContainer, item );
617 break;
618
619 case PCB_TEXT_T:
620 addText( static_cast<PCB_TEXT*>( item ), layerContainer, item );
621 break;
622
623 case PCB_TEXTBOX_T:
624 addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
625 break;
626
627 case PCB_TABLE_T:
628 addTable( static_cast<PCB_TABLE*>( item ), layerContainer, item );
629 break;
630
632 case PCB_DIM_CENTER_T:
633 case PCB_DIM_RADIAL_T:
635 case PCB_DIM_LEADER_T:
636 addShape( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer, item );
637 break;
638
639 default:
640 wxLogTrace( m_logTrace, wxT( "createLayers: item type: %d not implemented" ),
641 item->Type() );
642 break;
643 }
644
645 // add also this shape to the plated copper polygon list if required
647 {
648 if( layer == F_Cu )
649 item->TransformShapeToPolygon( *m_frontPlatedCopperPolys, F_Cu,
650 0, maxError, ERROR_INSIDE );
651 else if( layer == B_Cu )
652 item->TransformShapeToPolygon( *m_backPlatedCopperPolys, B_Cu,
653 0, maxError, ERROR_INSIDE );
654 }
655 }
656 }
657
658 // Add graphic item on copper layers to poly contours (vertical outlines)
659 if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL )
660 {
661 for( PCB_LAYER_ID layer : layer_ids )
662 {
663 wxASSERT( m_layers_poly.find( layer ) != m_layers_poly.end() );
664
665 SHAPE_POLY_SET *layerPoly = m_layers_poly[layer];
666
667 // Add graphic items on copper layers (texts and other )
668 for( BOARD_ITEM* item : m_board->Drawings() )
669 {
670 if( !item->IsOnLayer( layer ) )
671 continue;
672
673 switch( item->Type() )
674 {
675 case PCB_SHAPE_T:
676 item->TransformShapeToPolygon( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
677 break;
678
679 case PCB_TEXT_T:
680 {
681 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
682
683 text->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
684 break;
685 }
686
687 case PCB_TEXTBOX_T:
688 {
689 PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
690
691 textbox->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
692 break;
693 }
694
695 case PCB_TABLE_T:
696 // JEY TODO: tables
697 break;
698
699 default:
700 wxLogTrace( m_logTrace, wxT( "createLayers: item type: %d not implemented" ),
701 item->Type() );
702 break;
703 }
704 }
705 }
706 }
707
708 if( cfg.show_zones )
709 {
710 if( aStatusReporter )
711 aStatusReporter->Report( _( "Create zones" ) );
712
713 std::vector<std::pair<ZONE*, PCB_LAYER_ID>> zones;
714 std::unordered_map<PCB_LAYER_ID, std::unique_ptr<std::mutex>> layer_lock;
715
716 for( ZONE* zone : m_board->Zones() )
717 {
718 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
719 {
720 zones.emplace_back( std::make_pair( zone, layer ) );
721 layer_lock.emplace( layer, std::make_unique<std::mutex>() );
722
723 if( cfg.differentiate_plated_copper && layer == F_Cu )
724 {
725 zone->TransformShapeToPolygon( *m_frontPlatedCopperPolys, F_Cu, 0, maxError,
726 ERROR_INSIDE );
727 }
728 else if( cfg.differentiate_plated_copper && layer == B_Cu )
729 {
730 zone->TransformShapeToPolygon( *m_backPlatedCopperPolys, B_Cu, 0, maxError,
731 ERROR_INSIDE );
732 }
733 }
734 }
735
736 // Add zones objects
737 std::atomic<size_t> nextZone( 0 );
738 std::atomic<size_t> threadsFinished( 0 );
739
740 size_t parallelThreadCount = std::min<size_t>( zones.size(),
741 std::max<size_t>( std::thread::hardware_concurrency(), 2 ) );
742
743 for( size_t ii = 0; ii < parallelThreadCount; ++ii )
744 {
745 std::thread t = std::thread( [&]()
746 {
747 for( size_t areaId = nextZone.fetch_add( 1 );
748 areaId < zones.size();
749 areaId = nextZone.fetch_add( 1 ) )
750 {
751 ZONE* zone = zones[areaId].first;
752
753 if( zone == nullptr )
754 break;
755
756 PCB_LAYER_ID layer = zones[areaId].second;
757
758 auto layerContainer = m_layerMap.find( layer );
759 auto layerPolyContainer = m_layers_poly.find( layer );
760
761 if( layerContainer != m_layerMap.end() )
762 addSolidAreasShapes( zone, layerContainer->second, layer );
763
764 if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL
765 && layerPolyContainer != m_layers_poly.end() )
766 {
767 auto mut_it = layer_lock.find( layer );
768
769 std::lock_guard< std::mutex > lock( *( mut_it->second ) );
770 zone->TransformSolidAreasShapesToPolygon( layer, *layerPolyContainer->second );
771 }
772 }
773
774 threadsFinished++;
775 } );
776
777 t.detach();
778 }
779
780 while( threadsFinished < parallelThreadCount )
781 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
782 }
783 // End Build Copper layers
784
785 // This will make a union of all added contours
786 m_TH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
787 m_NPTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
788 m_viaTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
789 m_viaAnnuliPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
790
791 // Build Tech layers
792 // Based on:
793 // https://github.com/KiCad/kicad-source-mirror/blob/master/3d-viewer/3d_draw.cpp#L1059
794 if( aStatusReporter )
795 aStatusReporter->Report( _( "Build Tech layers" ) );
796
797 // draw graphic items, on technical layers
798
799 static const PCB_LAYER_ID techLayerList[] = {
800 B_Adhes,
801 F_Adhes,
802 B_Paste,
803 F_Paste,
804 B_SilkS,
805 F_SilkS,
806 B_Mask,
807 F_Mask,
808
809 // Aux Layers
810 Dwgs_User,
811 Cmts_User,
812 Eco1_User,
814 };
815
816 std::bitset<LAYER_3D_END> enabledFlags = visibilityFlags;
817
818 if( cfg.subtract_mask_from_silk || cfg.differentiate_plated_copper )
819 {
820 enabledFlags.set( LAYER_3D_SOLDERMASK_TOP );
821 enabledFlags.set( LAYER_3D_SOLDERMASK_BOTTOM );
822 }
823
824 for( PCB_LAYER_ID layer : LSET::AllNonCuMask().Seq( techLayerList, arrayDim( techLayerList ) ) )
825 {
826 if( aStatusReporter )
827 aStatusReporter->Report( wxString::Format( _( "Build Tech layer %d" ), (int) layer ) );
828
829 if( !Is3dLayerEnabled( layer, enabledFlags ) )
830 continue;
831
832 BVH_CONTAINER_2D *layerContainer = new BVH_CONTAINER_2D;
833 m_layerMap[layer] = layerContainer;
834
835 SHAPE_POLY_SET *layerPoly = new SHAPE_POLY_SET;
836 m_layers_poly[layer] = layerPoly;
837
838 if( Is3dLayerEnabled( layer, visibilityFlags ) )
839 {
840 // Add drawing objects
841 for( BOARD_ITEM* item : m_board->Drawings() )
842 {
843 if( !item->IsOnLayer( layer ) )
844 continue;
845
846 switch( item->Type() )
847 {
848 case PCB_SHAPE_T:
849 addShape( static_cast<PCB_SHAPE*>( item ), layerContainer, item );
850 break;
851
852 case PCB_TEXT_T:
853 addText( static_cast<PCB_TEXT*>( item ), layerContainer, item );
854 break;
855
856 case PCB_TEXTBOX_T:
857 addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
858 break;
859
860 case PCB_TABLE_T:
861 // JEY TODO: tables
862 break;
863
865 case PCB_DIM_CENTER_T:
866 case PCB_DIM_RADIAL_T:
868 case PCB_DIM_LEADER_T:
869 addShape( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer, item );
870 break;
871
872 default:
873 break;
874 }
875 }
876
877 // Add via tech layers
878 if( ( layer == F_Mask || layer == B_Mask ) && !m_board->GetTentVias() )
879 {
880 int maskExpansion = GetBoard()->GetDesignSettings().m_SolderMaskExpansion;
881
882 for( PCB_TRACK* track : m_board->Tracks() )
883 {
884 if( track->Type() == PCB_VIA_T
885 && static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
886 {
887 createViaWithMargin( track, layerContainer, maskExpansion );
888 }
889 }
890 }
891
892 // Add footprints tech layers - objects
893 for( FOOTPRINT* footprint : m_board->Footprints() )
894 {
895 if( layer == F_SilkS || layer == B_SilkS )
896 {
897 int linewidth = m_board->GetDesignSettings().m_LineThickness[ LAYER_CLASS_SILK ];
898
899 for( PAD* pad : footprint->Pads() )
900 {
901 if( !pad->IsOnLayer( layer ) )
902 continue;
903
904 buildPadOutlineAsSegments( pad, layerContainer, linewidth );
905 }
906 }
907 else
908 {
909 addPads( footprint, layerContainer, layer, false, false );
910 }
911
912 addFootprintShapes( footprint, layerContainer, layer, visibilityFlags );
913 }
914
915 // Draw non copper zones
916 if( cfg.show_zones )
917 {
918 for( ZONE* zone : m_board->Zones() )
919 {
920 if( zone->IsOnLayer( layer ) )
921 addSolidAreasShapes( zone, layerContainer, layer );
922 }
923 }
924 }
925
926 // Add item contours. We need these if we're building vertical walls or if this is a
927 // mask layer and we're differentiating copper from plated copper.
928 if( ( cfg.engine == RENDER_ENGINE::OPENGL && cfg.opengl_copper_thickness )
929 || ( cfg.differentiate_plated_copper && ( layer == F_Mask || layer == B_Mask ) ) )
930 {
931 // DRAWINGS
932 for( BOARD_ITEM* item : m_board->Drawings() )
933 {
934 if( !item->IsOnLayer( layer ) )
935 continue;
936
937 switch( item->Type() )
938 {
939 case PCB_SHAPE_T:
940 item->TransformShapeToPolygon( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
941 break;
942
943 case PCB_TEXT_T:
944 {
945 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
946
947 text->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
948 break;
949 }
950
951 case PCB_TEXTBOX_T:
952 {
953 PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
954
955 textbox->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
956 break;
957 }
958
959 case PCB_TABLE_T:
960 // JEY TODO: tables
961 break;
962
963 default:
964 break;
965 }
966 }
967
968 // NON-TENTED VIAS
969 if( ( layer == F_Mask || layer == B_Mask ) && !m_board->GetTentVias() )
970 {
971 int maskExpansion = GetBoard()->GetDesignSettings().m_SolderMaskExpansion;
972
973 for( PCB_TRACK* track : m_board->Tracks() )
974 {
975 if( track->Type() == PCB_VIA_T
976 && static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
977 {
978 track->TransformShapeToPolygon( *layerPoly, layer, maskExpansion, maxError,
979 ERROR_INSIDE );
980 }
981 }
982 }
983
984 // FOOTPRINT CHILDREN
985 for( FOOTPRINT* footprint : m_board->Footprints() )
986 {
987 if( layer == F_SilkS || layer == B_SilkS )
988 {
989 int linewidth = m_board->GetDesignSettings().m_LineThickness[ LAYER_CLASS_SILK ];
990
991 for( PAD* pad : footprint->Pads() )
992 {
993 if( pad->IsOnLayer( layer ) )
994 {
995 buildPadOutlineAsPolygon( pad, *layerPoly, linewidth, maxError,
996 ERROR_INSIDE );
997 }
998 }
999 }
1000 else
1001 {
1002 footprint->TransformPadsToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
1003 }
1004
1005 // On tech layers, use a poor circle approximation, only for texts (stroke font)
1006 footprint->TransformFPTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
1007
1008 // Add the remaining things with dynamic seg count for circles
1009 transformFPShapesToPolySet( footprint, layer, *layerPoly, maxError, ERROR_INSIDE );
1010 }
1011
1012 if( cfg.show_zones || layer == F_Mask || layer == B_Mask )
1013 {
1014 for( ZONE* zone : m_board->Zones() )
1015 {
1016 if( zone->IsOnLayer( layer ) )
1017 zone->TransformSolidAreasShapesToPolygon( layer, *layerPoly );
1018 }
1019 }
1020
1021 // This will make a union of all added contours
1022 layerPoly->Simplify( SHAPE_POLY_SET::PM_FAST );
1023 }
1024 }
1025 // End Build Tech layers
1026
1027 // If we're rendering off-board silk, also render pads of footprints which are entirely
1028 // outside the board outline. This makes off-board footprints more visually recognizable.
1029 if( cfg.show_off_board_silk )
1030 {
1031 BOX2I boardBBox = m_board_poly.BBox();
1032
1033 for( FOOTPRINT* footprint : m_board->Footprints() )
1034 {
1035 if( !footprint->GetBoundingBox().Intersects( boardBBox ) )
1036 {
1037 if( footprint->IsFlipped() )
1038 addPads( footprint, m_offboardPadsBack, B_Cu, false, false );
1039 else
1040 addPads( footprint, m_offboardPadsFront, F_Cu, false, false );
1041 }
1042 }
1043
1044 m_offboardPadsFront->BuildBVH();
1045 m_offboardPadsBack->BuildBVH();
1046 }
1047
1048 // Simplify layer polygons
1049
1050 if( aStatusReporter )
1051 aStatusReporter->Report( _( "Simplifying copper layer polygons" ) );
1052
1053 if( cfg.differentiate_plated_copper )
1054 {
1055 if( aStatusReporter )
1056 aStatusReporter->Report( _( "Calculating plated copper" ) );
1057
1058 // TRIM PLATED COPPER TO SOLDERMASK
1059 if( m_layers_poly.find( F_Mask ) != m_layers_poly.end() )
1060 {
1061 m_frontPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( F_Mask ),
1063 }
1064
1065 if( m_layers_poly.find( B_Mask ) != m_layers_poly.end() )
1066 {
1067 m_backPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( B_Mask ),
1069 }
1070
1071 // Subtract plated copper from unplated copper
1072 bool hasF_Cu = false;
1073 bool hasB_Cu = false;
1074
1075 if( m_layers_poly.find( F_Cu ) != m_layers_poly.end() )
1076 {
1077 m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedPadAndGraphicPolys, SHAPE_POLY_SET::PM_FAST );
1078 m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
1079 hasF_Cu = true;
1080 }
1081
1082 if( m_layers_poly.find( B_Cu ) != m_layers_poly.end() )
1083 {
1084 m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedPadAndGraphicPolys, SHAPE_POLY_SET::PM_FAST );
1085 m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
1086 hasB_Cu = true;
1087 }
1088
1089 // Add plated graphic items to build vertical walls
1090 if( hasF_Cu && m_frontPlatedCopperPolys->OutlineCount() )
1091 m_frontPlatedPadAndGraphicPolys->Append( *m_frontPlatedCopperPolys );
1092
1093 if( hasB_Cu && m_backPlatedCopperPolys->OutlineCount() )
1094 m_backPlatedPadAndGraphicPolys->Append( *m_backPlatedCopperPolys );
1095
1096 m_frontPlatedPadAndGraphicPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
1097 m_backPlatedPadAndGraphicPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
1098 m_frontPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
1099 m_backPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
1100
1101 // ADD PLATED PADS
1102 for( FOOTPRINT* footprint : m_board->Footprints() )
1103 {
1104 addPads( footprint, m_platedPadsFront, F_Cu, false, true );
1105 addPads( footprint, m_platedPadsBack, B_Cu, false, true );
1106 }
1107
1108 // ADD PLATED COPPER
1109 ConvertPolygonToTriangles( *m_frontPlatedCopperPolys, *m_platedPadsFront, m_biuTo3Dunits,
1110 *m_board->GetItem( niluuid ) );
1111
1112 ConvertPolygonToTriangles( *m_backPlatedCopperPolys, *m_platedPadsBack, m_biuTo3Dunits,
1113 *m_board->GetItem( niluuid ) );
1114
1115 m_platedPadsFront->BuildBVH();
1116 m_platedPadsBack->BuildBVH();
1117 }
1118
1119 if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL )
1120 {
1121 std::vector<PCB_LAYER_ID> &selected_layer_id = layer_ids;
1122 std::vector<PCB_LAYER_ID> layer_id_without_F_and_B;
1123
1124 if( cfg.differentiate_plated_copper )
1125 {
1126 layer_id_without_F_and_B.clear();
1127 layer_id_without_F_and_B.reserve( layer_ids.size() );
1128
1129 for( PCB_LAYER_ID layer: layer_ids )
1130 {
1131 if( layer != F_Cu && layer != B_Cu )
1132 layer_id_without_F_and_B.push_back( layer );
1133 }
1134
1135 selected_layer_id = layer_id_without_F_and_B;
1136 }
1137
1138 if( selected_layer_id.size() > 0 )
1139 {
1140 if( aStatusReporter )
1141 {
1142 aStatusReporter->Report( wxString::Format( _( "Simplifying %d copper layers" ),
1143 (int) selected_layer_id.size() ) );
1144 }
1145
1146 std::atomic<size_t> nextItem( 0 );
1147 std::atomic<size_t> threadsFinished( 0 );
1148
1149 size_t parallelThreadCount = std::min<size_t>(
1150 std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
1151 selected_layer_id.size() );
1152
1153 for( size_t ii = 0; ii < parallelThreadCount; ++ii )
1154 {
1155 std::thread t = std::thread(
1156 [&nextItem, &threadsFinished, &selected_layer_id, this]()
1157 {
1158 for( size_t i = nextItem.fetch_add( 1 );
1159 i < selected_layer_id.size();
1160 i = nextItem.fetch_add( 1 ) )
1161 {
1162 auto layerPoly = m_layers_poly.find( selected_layer_id[i] );
1163
1164 if( layerPoly != m_layers_poly.end() )
1165 {
1166 // This will make a union of all added contours
1167 layerPoly->second->ClearArcs();
1168 layerPoly->second->Simplify( SHAPE_POLY_SET::PM_FAST );
1169 }
1170 }
1171
1172 threadsFinished++;
1173 } );
1174
1175 t.detach();
1176 }
1177
1178 while( threadsFinished < parallelThreadCount )
1179 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1180 }
1181 }
1182
1183 // Simplify holes polygon contours
1184 if( aStatusReporter )
1185 aStatusReporter->Report( _( "Simplify holes contours" ) );
1186
1187 for( PCB_LAYER_ID layer : layer_ids )
1188 {
1189 if( m_layerHoleOdPolys.find( layer ) != m_layerHoleOdPolys.end() )
1190 {
1191 // found
1192 SHAPE_POLY_SET *polyLayer = m_layerHoleOdPolys[layer];
1193 polyLayer->Simplify( SHAPE_POLY_SET::PM_FAST );
1194
1195 wxASSERT( m_layerHoleIdPolys.find( layer ) != m_layerHoleIdPolys.end() );
1196
1197 polyLayer = m_layerHoleIdPolys[layer];
1198 polyLayer->Simplify( SHAPE_POLY_SET::PM_FAST );
1199 }
1200 }
1201
1202 // Build BVH (Bounding volume hierarchy) for holes and vias
1203
1204 if( aStatusReporter )
1205 aStatusReporter->Report( _( "Build BVH for holes and vias" ) );
1206
1207 m_TH_IDs.BuildBVH();
1208 m_TH_ODs.BuildBVH();
1209 m_viaAnnuli.BuildBVH();
1210
1211 if( !m_layerHoleMap.empty() )
1212 {
1213 for( std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& hole : m_layerHoleMap )
1214 hole.second->BuildBVH();
1215 }
1216
1217 // We only need the Solder mask to initialize the BVH
1218 // because..?
1219 if( m_layerMap[B_Mask] )
1220 m_layerMap[B_Mask]->BuildBVH();
1221
1222 if( m_layerMap[F_Mask] )
1223 m_layerMap[F_Mask]->BuildBVH();
1224}
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
@ LAYER_CLASS_SILK
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.
unsigned int m_viaCount
MAP_POLY m_layerHoleOdPolys
Hole outer diameters (per layer)
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.
SHAPE_POLY_SET * m_frontPlatedPadAndGraphicPolys
unsigned int m_trackCount
float m_averageTrackWidth
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 addPads(const FOOTPRINT *aFootprint, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads)
BVH_CONTAINER_2D * m_platedPadsBack
void createPadWithHole(const PAD *aPad, CONTAINER_2D_BASE *aDstContainer, int aInflateValue)
void addShape(const PCB_SHAPE *aShape, CONTAINER_2D_BASE *aContainer, const BOARD_ITEM *aOwner)
void createTrack(const PCB_TRACK *aTrack, CONTAINER_2D_BASE *aDstContainer)
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)
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
SHAPE_POLY_SET m_NPTH_ODPolys
NPTH outer diameters.
SHAPE_POLY_SET * m_backPlatedPadAndGraphicPolys
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:77
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition: board_item.h:291
const ZONES & Zones() const
Definition: board.h:327
const FOOTPRINTS & Footprints() const
Definition: board.h:323
const TRACKS & Tracks() const
Definition: board.h:321
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:797
const DRAWINGS & Drawings() const
Definition: board.h:325
void Clear() override
void Add(OBJECT_2D *aObject)
Definition: container_2d.h:49
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
DRAWINGS & GraphicalItems()
Definition: footprint.h:194
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:521
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:575
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:418
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:884
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:863
Definition: pad.h:59
VECTOR2I ShapePos() const
Definition: pad.cpp:951
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Definition: pad.cpp:514
PAD_SHAPE GetShape() const
Definition: pad.h:193
const VECTOR2I & GetSize() const
Definition: pad.h:247
Abstract dimension API.
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 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.
Definition: pcb_track.cpp:1641
bool FlashLayer(int aLayer) const
Check to see whether the via should have a pad on the specific layer.
Definition: pcb_track.cpp:1010
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:71
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
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 RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void Simplify(POLYGON_MODE aFastMode)
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFastMo...
Handle a list of polygons defining a copper zone.
Definition: zone.h:72
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.
void buildPadOutlineAsPolygon(const PAD *aPad, SHAPE_POLY_SET &aBuffer, int aWidth, int aMaxError, ERROR_LOC aErrorLoc)
#define DELETE_AND_FREE_MAP(map)
void transformFPShapesToPolySet(const FOOTPRINT *aFootprint, PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aBuffer, int aMaxError, ERROR_LOC aErrorLoc)
#define DELETE_AND_FREE(ptr)
#define _(s)
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ ERROR_INSIDE
static const wxChar * m_logTrace
Trace mask used to enable or disable debug output for this class.
KIID niluuid(0)
@ LAYER_3D_SOLDERMASK_TOP
Definition: layer_ids.h:459
@ LAYER_3D_SOLDERMASK_BOTTOM
Definition: layer_ids.h:458
#define MAX_CU_LAYERS
Definition: layer_ids.h:142
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Adhes
Definition: layer_ids.h:97
@ Dwgs_User
Definition: layer_ids.h:109
@ F_Paste
Definition: layer_ids.h:101
@ Cmts_User
Definition: layer_ids.h:110
@ F_Adhes
Definition: layer_ids.h:98
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ Eco1_User
Definition: layer_ids.h:111
@ F_Mask
Definition: layer_ids.h:107
@ B_Paste
Definition: layer_ids.h:100
@ F_SilkS
Definition: layer_ids.h:104
@ Eco2_User
Definition: layer_ids.h:112
@ B_SilkS
Definition: layer_ids.h:103
@ F_Cu
Definition: layer_ids.h:64
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:1022
VIATYPE
Definition: pcb_track.h:64
BOARD * GetBoard()
int64_t GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
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:248
@ 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_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
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:118
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42