214#ifdef PRINT_STATISTICS_3D_VIEWER
217 int64_t start_Time = stats_startCopperLayersTime;
235 std::vector<const PCB_TRACK*> trackList;
237 trackList.reserve(
m_board->Tracks().size() );
249 trackList.push_back( track );
271 std::vector<PCB_LAYER_ID> layer_ids;
280 layer_ids.push_back( layer );
307 if( aStatusReporter )
308 aStatusReporter->
Report(
_(
"Create tracks and vias" ) );
317 for(
const PCB_TRACK* track : trackList )
320 if( !track->IsOnLayer( layer ) )
342 unsigned int nTracks = trackList.size();
344 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
346 const PCB_TRACK *track = trackList[trackIdx];
361 const float thickness =
static_cast<float>( plating / 2.0f );
362 const float hole_inner_radius =
static_cast<float>( holediameter / 2.0f );
363 const float ring_radius =
static_cast<float>( viasize / 2.0f );
378 else if( layer == layer_ids[0] )
387 if( hole_inner_radius > 0.0 )
393 const double frontRadius =
via->GetFrontPostMachiningSize() *
m_biuTo3Dunits / 2.0;
397 && frontRadius > hole_inner_radius )
399 if( layer == layer_ids[0] )
408 layerHoleContainer->
Add(
new FILLED_CIRCLE_2D( via_center, frontRadius + thickness, *track ) );
412 const double backRadius =
via->GetBackPostMachiningSize() *
m_biuTo3Dunits / 2.0;
416 && backRadius > hole_inner_radius )
419 if( layer == layer_ids.back() )
428 layerHoleContainer->
Add(
new FILLED_CIRCLE_2D( via_center, backRadius + thickness, *track ) );
432 float backdrillRadius =
via->GetSecondaryDrillSize().value_or( 0 ) *
m_biuTo3Dunits / 2.0f ;
435 if( backdrillRadius > hole_inner_radius + thickness )
440 bool validLyPair = secStart >= 0 && secEnd >= 0;
450 if( validLyPair && layer == secStart )
455 float tertiaryDrillRadius =
via->GetTertiaryDrillSize().value_or( 0 ) *
m_biuTo3Dunits / 2.0f ;
458 if( tertiaryDrillRadius > hole_inner_radius + thickness )
463 bool validLyPair = terStart >= 0 && terEnd >= 0;
470 layerHoleContainer->
Add(
new FILLED_CIRCLE_2D( via_center, tertiaryDrillRadius, *track ) );
473 if( validLyPair && layer == terStart )
505 const unsigned int nTracks = trackList.size();
507 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
509 const PCB_TRACK *track = trackList[trackIdx];
531 const int holediameter =
via->GetDrillValue();
543 else if( layer == layer_ids[0] )
545 const int hole_outer_ring_radius =
KiROUND(
via->GetWidth( layer ) / 2.0 );
563 const auto frontMode =
via->GetFrontPostMachining();
565 if( frontMode.has_value()
569 const int frontRadiusBIU =
via->GetFrontPostMachiningSize() / 2;
571 if( frontRadiusBIU > holediameter / 2 )
578 frontRadiusBIU,
via->GetMaxError(),
584 frontRadiusBIU,
via->GetMaxError(),
589 frontRadiusOuterBIU,
via->GetMaxError(),
592 frontRadiusBIU,
via->GetMaxError(),
597 const auto backMode =
via->GetBackPostMachining();
599 if( backMode.has_value()
603 const int backRadiusBIU =
via->GetBackPostMachiningSize() / 2;
605 if( backRadiusBIU > holediameter / 2 )
612 backRadiusBIU,
via->GetMaxError(),
618 backRadiusBIU,
via->GetMaxError(),
623 backRadiusOuterBIU,
via->GetMaxError(),
626 backRadiusBIU,
via->GetMaxError(),
632 const auto secondaryDrillSize =
via->GetSecondaryDrillSize();
634 if( secondaryDrillSize.has_value() && secondaryDrillSize.value() > 0 )
636 const int backdrillRadiusBIU = secondaryDrillSize.value() / 2;
638 const int holeOuterRadiusBIU = hole_outer_radius;
641 if( backdrillOuterRadiusBIU > holeOuterRadiusBIU )
645 bool validLyPair = secStart >= 0 && secEnd >= 0;
651 backdrillOuterRadiusBIU,
via->GetMaxError(),
655 backdrillRadiusBIU,
via->GetMaxError(),
659 backdrillOuterRadiusBIU,
via->GetMaxError(),
666 const auto tertiaryDrillSize =
via->GetTertiaryDrillSize();
668 if( tertiaryDrillSize.has_value() && tertiaryDrillSize.value() > 0 )
670 const int backdrillRadiusBIU = tertiaryDrillSize.value() / 2;
672 const int holeOuterRadiusBIU = hole_outer_radius;
675 if( backdrillOuterRadiusBIU > holeOuterRadiusBIU )
679 bool validLyPair = terStart >= 0 && terEnd >= 0;
686 backdrillOuterRadiusBIU,
via->GetMaxError(),
690 backdrillRadiusBIU,
via->GetMaxError(),
694 backdrillOuterRadiusBIU,
via->GetMaxError(),
713 unsigned int nTracks = trackList.size();
715 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
717 const PCB_TRACK *track = trackList[trackIdx];
735 for(
PAD*
pad : footprint->Pads() )
738 if( !
pad->HasHole() )
742 double holeDiameter = (
pad->GetDrillSize().x +
pad->GetDrillSize().y ) / 2.0;
765 const float holeDiameterUnits =
static_cast<float>(
767 const float holeInnerRadius = holeDiameterUnits / 2.0f;
771 const auto frontMode =
pad->GetFrontPostMachining();
773 if( frontMode.has_value()
777 const float frontRadius =
pad->GetFrontPostMachiningSize() * 0.5f
780 if( frontRadius > holeInnerRadius )
795 const auto backMode =
pad->GetBackPostMachining();
797 if( backMode.has_value()
801 const float backRadius =
pad->GetBackPostMachiningSize() * 0.5f
804 if( backRadius > holeInnerRadius )
820 const VECTOR2I& secDrillSize =
pad->GetSecondaryDrillSize();
822 if( secDrillSize.
x > 0 || secDrillSize.
y > 0 )
824 const float backdrillRadius = ( secDrillSize.
x + secDrillSize.
y ) * 0.25f
828 const float holeOuterRadius = holeInnerRadius
833 if( backdrillRadius > holeOuterRadius )
837 bool validLyPair = secStart >= 0 && secEnd >= 0;
858 layerHoleContainer->
Add(
873 for(
PAD*
pad : footprint->Pads() )
875 if( !
pad->HasHole() )
899 const double holeDiameter = (
pad->GetDrillSize().x +
pad->GetDrillSize().y ) / 2.0;
900 const int holeRadius =
KiROUND( holeDiameter / 2.0 );
902 const auto frontMode =
pad->GetFrontPostMachining();
904 if( frontMode.has_value()
908 const int frontRadiusBIU =
pad->GetFrontPostMachiningSize() / 2;
910 if( frontRadiusBIU > holeRadius )
915 frontRadiusBIU,
pad->GetMaxError(),
921 frontRadiusBIU,
pad->GetMaxError(),
927 const auto backMode =
pad->GetBackPostMachining();
929 if( backMode.has_value()
933 const int backRadiusBIU =
pad->GetBackPostMachiningSize() / 2;
935 if( backRadiusBIU > holeRadius )
940 backRadiusBIU,
pad->GetMaxError(),
946 backRadiusBIU,
pad->GetMaxError(),
953 const VECTOR2I& secDrillSize =
pad->GetSecondaryDrillSize();
955 if( secDrillSize.
x > 0 || secDrillSize.
y > 0 )
957 const int backdrillRadiusBIU = ( secDrillSize.
x + secDrillSize.
y ) / 4;
958 const int holeOuterRadiusBIU = holeRadius + inflate;
961 if( backdrillRadiusBIU > holeOuterRadiusBIU )
965 bool validLyPair = secStart >= 0 && secEnd >= 0;
970 backdrillRadiusBIU,
pad->GetMaxError(),
991 backdrillRadiusBIU,
pad->GetMaxError(),
1009 addPads( fp, layerContainer, layer );
1017 fp->TransformPadsToPolySet( *layerPoly, layer, 0, fp->GetMaxError(),
ERROR_INSIDE );
1029 fp->TransformPadsToPolySet( *layerPoly, layer, 0, fp->GetMaxError(),
ERROR_INSIDE );
1046 if( !item->IsOnLayer( layer ) )
1049 switch( item->Type() )
1083 wxLogTrace(
m_logTrace, wxT(
"createLayers: item type: %d not implemented" ), item->Type() );
1100 text_box->PCB_SHAPE::TransformShapeToPolygon( *copperPolys, layer, 0, text_box->
GetMaxError(),
1110 item->TransformShapeToPolySet( *copperPolys, layer, 0, item->GetMaxError(),
ERROR_INSIDE );
1121 switch( item->Type() )
1124 item->TransformShapeToPolySet( *layerPoly, layer, 0, item->GetMaxError(),
ERROR_INSIDE );
1141 textbox->PCB_SHAPE::TransformShapeToPolygon( *layerPoly, layer, 0, textbox->
GetMaxError(),
1154 cell->TransformTextToPolySet( *layerPoly, 0, cell->GetMaxError(),
ERROR_INSIDE );
1184 for(
const std::shared_ptr<SHAPE>& shape : dimension->
GetShapes() )
1194 wxLogTrace(
m_logTrace, wxT(
"createLayers: item type: %d not implemented" ), item->Type() );
1203 if( aStatusReporter )
1204 aStatusReporter->
Report(
_(
"Create zones" ) );
1206 std::vector<std::pair<ZONE*, PCB_LAYER_ID>> zones;
1207 std::unordered_map<PCB_LAYER_ID, std::unique_ptr<std::mutex>> layer_lock;
1213 zones.emplace_back( std::make_pair( zone, layer ) );
1214 layer_lock.emplace( layer, std::make_unique<std::mutex>() );
1220 zone->TransformShapeToPolygon( *copperPolys, layer, 0, zone->GetMaxError(),
ERROR_INSIDE );
1226 std::atomic<size_t> nextZone( 0 );
1227 std::atomic<size_t> threadsFinished( 0 );
1229 size_t parallelThreadCount = std::min<size_t>( zones.size(),
1230 std::max<size_t>( std::thread::hardware_concurrency(), 2 ) );
1232 for(
size_t ii = 0; ii < parallelThreadCount; ++ii )
1234 std::thread t = std::thread( [&]()
1236 for(
size_t areaId = nextZone.fetch_add( 1 );
1237 areaId < zones.size();
1238 areaId = nextZone.fetch_add( 1 ) )
1240 ZONE* zone = zones[areaId].first;
1242 if( zone ==
nullptr )
1253 auto mut_it = layer_lock.find( layer );
1255 if( mut_it != layer_lock.end() )
1257 std::lock_guard< std::mutex > lock( *( mut_it->second ) );
1269 while( threadsFinished < parallelThreadCount )
1270 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1312 if( aStatusReporter )
1313 aStatusReporter->
Report(
_(
"Build Tech layers" ) );
1379 std::bitset<LAYER_3D_END> enabledFlags = visibilityFlags;
1389 if( aStatusReporter )
1390 aStatusReporter->
Report( wxString::Format(
_(
"Build Tech layer %d" ), (
int) layer ) );
1406 if( !item->IsOnLayer( layer ) )
1409 switch( item->Type() )
1449 if( !track->IsOnLayer( layer ) )
1459 if( !
via->FlashLayer( copper_layer ) )
1463 int maskExpansion = track->GetSolderMaskExpansion();
1469 const bool isPasteLayer = ( layer ==
F_Paste || layer ==
B_Paste );
1470 const wxString currentVariant =
m_board->GetCurrentVariant();
1475 bool skipForVariantDNP = isPasteLayer && footprint->GetDNPForVariant( currentVariant );
1481 for(
PAD*
pad : footprint->Pads() )
1483 if( !
pad->IsOnLayer( layer ) )
1489 else if( !skipForVariantDNP )
1491 addPads( footprint, layerContainer, layer );
1494 if( !skipForVariantDNP )
1503 if( zone->IsOnLayer( layer ) )
1517 if( !item->IsOnLayer( layer ) )
1520 switch( item->Type() )
1523 item->TransformShapeToPolySet( *layerPoly, layer, 0, item->GetMaxError(),
ERROR_INSIDE );
1540 textbox->PCB_SHAPE::TransformShapeToPolygon( *layerPoly, layer, 0, textbox->
GetMaxError(),
1553 cell->TransformTextToPolySet( *layerPoly, 0, cell->GetMaxError(),
ERROR_INSIDE );
1590 if(
via->FlashLayer( layer ) && !
via->IsTented( layer ) )
1592 track->TransformShapeToPolygon( *layerPoly, layer, maskExpansion, track->GetMaxError(),
1598 if( track->HasSolderMask() )
1600 track->TransformShapeToPolySet( *layerPoly, layer, maskExpansion, track->GetMaxError(),
1614 for(
PAD*
pad : footprint->Pads() )
1616 if(
pad->IsOnLayer( layer ) )
1625 footprint->TransformPadsToPolySet( *layerPoly, layer, 0, footprint->GetMaxError(),
ERROR_INSIDE );
1637 if( zone->IsOnLayer( layer ) )
1638 zone->TransformSolidAreasShapesToPolygon( layer, *layerPoly );
1656 if( !footprint->GetBoundingBox().Intersects( boardBBox ) )
1658 if( footprint->IsFlipped() )
1671 if( aStatusReporter )
1672 aStatusReporter->
Report(
_(
"Simplifying copper layer polygons" ) );
1676 if( aStatusReporter )
1677 aStatusReporter->
Report(
_(
"Calculating plated copper" ) );
1706 std::vector<PCB_LAYER_ID> &selected_layer_id = layer_ids;
1707 std::vector<PCB_LAYER_ID> layer_id_without_F_and_B;
1711 layer_id_without_F_and_B.clear();
1712 layer_id_without_F_and_B.reserve( layer_ids.size() );
1716 if( layer !=
F_Cu && layer !=
B_Cu )
1717 layer_id_without_F_and_B.push_back( layer );
1720 selected_layer_id = layer_id_without_F_and_B;
1723 if( selected_layer_id.size() > 0 )
1725 if( aStatusReporter )
1727 aStatusReporter->
Report( wxString::Format(
_(
"Simplifying %d copper layers" ),
1728 (
int) selected_layer_id.size() ) );
1731 std::atomic<size_t> nextItem( 0 );
1732 std::atomic<size_t> threadsFinished( 0 );
1734 size_t parallelThreadCount = std::min<size_t>(
1735 std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
1736 selected_layer_id.size() );
1738 for(
size_t ii = 0; ii < parallelThreadCount; ++ii )
1740 std::thread t = std::thread(
1741 [&nextItem, &threadsFinished, &selected_layer_id,
this]()
1743 for(
size_t i = nextItem.fetch_add( 1 );
1744 i < selected_layer_id.size();
1745 i = nextItem.fetch_add( 1 ) )
1761 while( threadsFinished < parallelThreadCount )
1762 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1767 if( aStatusReporter )
1768 aStatusReporter->
Report(
_(
"Simplify holes contours" ) );
1787 if( aStatusReporter )
1788 aStatusReporter->
Report(
_(
"Build BVH for holes and vias" ) );
1803 for( std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& hole :
m_layerHoleMap )
1804 hole.second->BuildBVH();