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