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