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 <lset.h>
42#include <pad.h>
43#include <pcb_text.h>
44#include <pcb_textbox.h>
45#include <pcb_table.h>
46#include <pcb_shape.h>
47#include <zone.h>
49#include <trigo.h>
50#include <vector>
51#include <thread>
52#include <core/arraydim.h>
53#include <algorithm>
54#include <atomic>
55#include <wx/log.h>
56
57#ifdef PRINT_STATISTICS_3D_VIEWER
58#include <core/profile.h>
59#endif
60
61
62
63
64/*
65 * This is used to draw pad outlines on silk layers.
66 */
67void buildPadOutlineAsPolygon( const PAD* aPad, SHAPE_POLY_SET& aBuffer, int aWidth, int aMaxError,
68 ERROR_LOC aErrorLoc )
69{
70 if( aPad->GetShape() == PAD_SHAPE::CIRCLE ) // Draw a ring
71 {
72 TransformRingToPolygon( aBuffer, aPad->ShapePos(), aPad->GetSize().x / 2, aWidth,
73 aMaxError, aErrorLoc );
74 }
75 else
76 {
77 // For other shapes, add outlines as thick segments in polygon buffer
78 const SHAPE_LINE_CHAIN& path = aPad->GetEffectivePolygon( ERROR_INSIDE )->COutline( 0 );
79
80 for( int ii = 0; ii < path.PointCount(); ++ii )
81 {
82 const VECTOR2I& a = path.CPoint( ii );
83 const VECTOR2I& b = path.CPoint( ii + 1 );
84
85 TransformOvalToPolygon( aBuffer, a, b, aWidth, aMaxError, aErrorLoc );
86 }
87 }
88}
89
90
91void transformFPShapesToPolySet( const FOOTPRINT* aFootprint, PCB_LAYER_ID aLayer,
92 SHAPE_POLY_SET& aBuffer, int aMaxError, ERROR_LOC aErrorLoc )
93{
94 for( BOARD_ITEM* item : aFootprint->GraphicalItems() )
95 {
96 if( item->Type() == PCB_SHAPE_T || BaseType( item->Type() ) == PCB_DIMENSION_T )
97 {
98 if( item->GetLayer() == aLayer )
99 item->TransformShapeToPolygon( aBuffer, aLayer, 0, aMaxError, aErrorLoc );
100 }
101 }
102}
103
104
106{
107#define DELETE_AND_FREE( ptr ) \
108 { \
109 delete ptr; \
110 ptr = nullptr; \
111 } \
112
113#define DELETE_AND_FREE_MAP( map ) \
114 { \
115 for( auto& [ layer, poly ] : map ) \
116 delete poly; \
117 \
118 map.clear(); \
119 }
120
122
127
130
135
138
143
144 m_TH_ODs.Clear();
145 m_TH_IDs.Clear();
148}
149
150
151void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
152{
154
155 // Build Copper layers
156 // Based on:
157 // https://github.com/KiCad/kicad-source-mirror/blob/master/3d-viewer/3d_draw.cpp#L692
158
159#ifdef PRINT_STATISTICS_3D_VIEWER
160 int64_t stats_startCopperLayersTime = GetRunningMicroSecs();
161
162 int64_t start_Time = stats_startCopperLayersTime;
163#endif
164
167
169
170 std::bitset<LAYER_3D_END> visibilityFlags = GetVisibleLayers();
171
172 m_trackCount = 0;
174 m_viaCount = 0;
176 m_holeCount = 0;
178
179 if( !m_board )
180 return;
181
182 // Prepare track list, convert in a vector. Calc statistic for the holes
183 std::vector<const PCB_TRACK*> trackList;
184 trackList.clear();
185 trackList.reserve( m_board->Tracks().size() );
186
187 int maxError = m_board->GetDesignSettings().m_MaxError;
188
189 for( PCB_TRACK* track : m_board->Tracks() )
190 {
191 if( !Is3dLayerEnabled( track->GetLayer(), visibilityFlags ) ) // Skip non enabled layers
192 continue;
193
194 // Note: a PCB_TRACK holds normal segment tracks and also vias circles (that have also
195 // drill values)
196 trackList.push_back( track );
197
198 if( track->Type() == PCB_VIA_T )
199 {
200 const PCB_VIA *via = static_cast< const PCB_VIA*>( track );
201 m_viaCount++;
202 m_averageViaHoleDiameter += static_cast<float>( via->GetDrillValue() * m_biuTo3Dunits );
203 }
204 else
205 {
206 m_trackCount++;
207 }
208
209 m_averageTrackWidth += static_cast<float>( track->GetWidth() * m_biuTo3Dunits );
210 }
211
212 if( m_trackCount )
214
215 if( m_viaCount )
217
218 // Prepare copper layers index and containers
219 std::vector<PCB_LAYER_ID> layer_ids;
220 layer_ids.clear();
221 layer_ids.reserve( m_copperLayersCount );
222
223 for( unsigned i = 0; i < arrayDim( cu_seq ); ++i )
224 cu_seq[i] = ToLAYER_ID( B_Cu - i );
225
226 for( PCB_LAYER_ID layer : cu_set.Seq( cu_seq, arrayDim( cu_seq ) ) )
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 ) )
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 && !static_cast<const PCB_VIA*>( track )->IsTented( 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 ) )
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 && !static_cast<const PCB_VIA*>( track )->IsTented( layer ) )
978 {
979 track->TransformShapeToPolygon( *layerPoly, layer, maskExpansion, maxError,
980 ERROR_INSIDE );
981 }
982 }
983 }
984
985 // FOOTPRINT CHILDREN
986 for( FOOTPRINT* footprint : m_board->Footprints() )
987 {
988 if( layer == F_SilkS || layer == B_SilkS )
989 {
990 int linewidth = m_board->GetDesignSettings().m_LineThickness[ LAYER_CLASS_SILK ];
991
992 for( PAD* pad : footprint->Pads() )
993 {
994 if( pad->IsOnLayer( layer ) )
995 {
996 buildPadOutlineAsPolygon( pad, *layerPoly, linewidth, maxError,
997 ERROR_INSIDE );
998 }
999 }
1000 }
1001 else
1002 {
1003 footprint->TransformPadsToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
1004 }
1005
1006 // On tech layers, use a poor circle approximation, only for texts (stroke font)
1007 footprint->TransformFPTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
1008
1009 // Add the remaining things with dynamic seg count for circles
1010 transformFPShapesToPolySet( footprint, layer, *layerPoly, maxError, ERROR_INSIDE );
1011 }
1012
1013 if( cfg.show_zones || layer == F_Mask || layer == B_Mask )
1014 {
1015 for( ZONE* zone : m_board->Zones() )
1016 {
1017 if( zone->IsOnLayer( layer ) )
1018 zone->TransformSolidAreasShapesToPolygon( layer, *layerPoly );
1019 }
1020 }
1021
1022 // This will make a union of all added contours
1023 layerPoly->Simplify( SHAPE_POLY_SET::PM_FAST );
1024 }
1025 }
1026 // End Build Tech layers
1027
1028 // If we're rendering off-board silk, also render pads of footprints which are entirely
1029 // outside the board outline. This makes off-board footprints more visually recognizable.
1030 if( cfg.show_off_board_silk )
1031 {
1032 BOX2I boardBBox = m_board_poly.BBox();
1033
1034 for( FOOTPRINT* footprint : m_board->Footprints() )
1035 {
1036 if( !footprint->GetBoundingBox().Intersects( boardBBox ) )
1037 {
1038 if( footprint->IsFlipped() )
1039 addPads( footprint, m_offboardPadsBack, B_Cu, false, false );
1040 else
1041 addPads( footprint, m_offboardPadsFront, F_Cu, false, false );
1042 }
1043 }
1044
1045 m_offboardPadsFront->BuildBVH();
1046 m_offboardPadsBack->BuildBVH();
1047 }
1048
1049 // Simplify layer polygons
1050
1051 if( aStatusReporter )
1052 aStatusReporter->Report( _( "Simplifying copper layer polygons" ) );
1053
1054 if( cfg.differentiate_plated_copper )
1055 {
1056 if( aStatusReporter )
1057 aStatusReporter->Report( _( "Calculating plated copper" ) );
1058
1059 // TRIM PLATED COPPER TO SOLDERMASK
1060 if( m_layers_poly.find( F_Mask ) != m_layers_poly.end() )
1061 {
1062 m_frontPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( F_Mask ),
1064 }
1065
1066 if( m_layers_poly.find( B_Mask ) != m_layers_poly.end() )
1067 {
1068 m_backPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( B_Mask ),
1070 }
1071
1072 // Subtract plated copper from unplated copper
1073 bool hasF_Cu = false;
1074 bool hasB_Cu = false;
1075
1076 if( m_layers_poly.find( F_Cu ) != m_layers_poly.end() )
1077 {
1078 m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedPadAndGraphicPolys, SHAPE_POLY_SET::PM_FAST );
1079 m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
1080 hasF_Cu = true;
1081 }
1082
1083 if( m_layers_poly.find( B_Cu ) != m_layers_poly.end() )
1084 {
1085 m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedPadAndGraphicPolys, SHAPE_POLY_SET::PM_FAST );
1086 m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
1087 hasB_Cu = true;
1088 }
1089
1090 // Add plated graphic items to build vertical walls
1091 if( hasF_Cu && m_frontPlatedCopperPolys->OutlineCount() )
1092 m_frontPlatedPadAndGraphicPolys->Append( *m_frontPlatedCopperPolys );
1093
1094 if( hasB_Cu && m_backPlatedCopperPolys->OutlineCount() )
1095 m_backPlatedPadAndGraphicPolys->Append( *m_backPlatedCopperPolys );
1096
1097 m_frontPlatedPadAndGraphicPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
1098 m_backPlatedPadAndGraphicPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
1099 m_frontPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
1100 m_backPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
1101
1102 // ADD PLATED PADS
1103 for( FOOTPRINT* footprint : m_board->Footprints() )
1104 {
1105 addPads( footprint, m_platedPadsFront, F_Cu, false, true );
1106 addPads( footprint, m_platedPadsBack, B_Cu, false, true );
1107 }
1108
1109 // ADD PLATED COPPER
1110 ConvertPolygonToTriangles( *m_frontPlatedCopperPolys, *m_platedPadsFront, m_biuTo3Dunits,
1111 *m_board->GetItem( niluuid ) );
1112
1113 ConvertPolygonToTriangles( *m_backPlatedCopperPolys, *m_platedPadsBack, m_biuTo3Dunits,
1114 *m_board->GetItem( niluuid ) );
1115
1116 m_platedPadsFront->BuildBVH();
1117 m_platedPadsBack->BuildBVH();
1118 }
1119
1120 if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL )
1121 {
1122 std::vector<PCB_LAYER_ID> &selected_layer_id = layer_ids;
1123 std::vector<PCB_LAYER_ID> layer_id_without_F_and_B;
1124
1125 if( cfg.differentiate_plated_copper )
1126 {
1127 layer_id_without_F_and_B.clear();
1128 layer_id_without_F_and_B.reserve( layer_ids.size() );
1129
1130 for( PCB_LAYER_ID layer: layer_ids )
1131 {
1132 if( layer != F_Cu && layer != B_Cu )
1133 layer_id_without_F_and_B.push_back( layer );
1134 }
1135
1136 selected_layer_id = layer_id_without_F_and_B;
1137 }
1138
1139 if( selected_layer_id.size() > 0 )
1140 {
1141 if( aStatusReporter )
1142 {
1143 aStatusReporter->Report( wxString::Format( _( "Simplifying %d copper layers" ),
1144 (int) selected_layer_id.size() ) );
1145 }
1146
1147 std::atomic<size_t> nextItem( 0 );
1148 std::atomic<size_t> threadsFinished( 0 );
1149
1150 size_t parallelThreadCount = std::min<size_t>(
1151 std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
1152 selected_layer_id.size() );
1153
1154 for( size_t ii = 0; ii < parallelThreadCount; ++ii )
1155 {
1156 std::thread t = std::thread(
1157 [&nextItem, &threadsFinished, &selected_layer_id, this]()
1158 {
1159 for( size_t i = nextItem.fetch_add( 1 );
1160 i < selected_layer_id.size();
1161 i = nextItem.fetch_add( 1 ) )
1162 {
1163 auto layerPoly = m_layers_poly.find( selected_layer_id[i] );
1164
1165 if( layerPoly != m_layers_poly.end() )
1166 {
1167 // This will make a union of all added contours
1168 layerPoly->second->ClearArcs();
1169 layerPoly->second->Simplify( SHAPE_POLY_SET::PM_FAST );
1170 }
1171 }
1172
1173 threadsFinished++;
1174 } );
1175
1176 t.detach();
1177 }
1178
1179 while( threadsFinished < parallelThreadCount )
1180 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1181 }
1182 }
1183
1184 // Simplify holes polygon contours
1185 if( aStatusReporter )
1186 aStatusReporter->Report( _( "Simplify holes contours" ) );
1187
1188 for( PCB_LAYER_ID layer : layer_ids )
1189 {
1190 if( m_layerHoleOdPolys.find( layer ) != m_layerHoleOdPolys.end() )
1191 {
1192 // found
1193 SHAPE_POLY_SET *polyLayer = m_layerHoleOdPolys[layer];
1194 polyLayer->Simplify( SHAPE_POLY_SET::PM_FAST );
1195
1196 wxASSERT( m_layerHoleIdPolys.find( layer ) != m_layerHoleIdPolys.end() );
1197
1198 polyLayer = m_layerHoleIdPolys[layer];
1199 polyLayer->Simplify( SHAPE_POLY_SET::PM_FAST );
1200 }
1201 }
1202
1203 // Build BVH (Bounding volume hierarchy) for holes and vias
1204
1205 if( aStatusReporter )
1206 aStatusReporter->Report( _( "Build BVH for holes and vias" ) );
1207
1208 m_TH_IDs.BuildBVH();
1209 m_TH_ODs.BuildBVH();
1210 m_viaAnnuli.BuildBVH();
1211
1212 if( !m_layerHoleMap.empty() )
1213 {
1214 for( std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& hole : m_layerHoleMap )
1215 hole.second->BuildBVH();
1216 }
1217
1218 // We only need the Solder mask to initialize the BVH
1219 // because..?
1220 if( m_layerMap[B_Mask] )
1221 m_layerMap[B_Mask]->BuildBVH();
1222
1223 if( m_layerMap[F_Mask] )
1224 m_layerMap[F_Mask]->BuildBVH();
1225}
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:79
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition: board_item.h:307
const ZONES & Zones() const
Definition: board.h:334
const FOOTPRINTS & Footprints() const
Definition: board.h:330
const TRACKS & Tracks() const
Definition: board.h:328
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:874
const DRAWINGS & Drawings() const
Definition: board.h:332
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:101
DRAWINGS & GraphicalItems()
Definition: footprint.h:198
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:35
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:392
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:753
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:732
Definition: pad.h:54
VECTOR2I ShapePos() const
Definition: pad.cpp:896
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Definition: pad.cpp:453
PAD_SHAPE GetShape() const
Definition: pad.h:193
const VECTOR2I & GetSize() const
Definition: pad.h:256
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:1678
bool IsTented(PCB_LAYER_ID aLayer) const override
Checks if the given object is tented (its copper shape is covered by solder mask) on a given side of ...
Definition: pcb_track.cpp:828
bool FlashLayer(int aLayer) const
Check to see whether the via should have a pad on the specific layer.
Definition: pcb_track.cpp:1024
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:73
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:461
@ LAYER_3D_SOLDERMASK_BOTTOM
Definition: layer_ids.h:460
#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:875
VIATYPE
Definition: pcb_track.h:66
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:121
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42