221#ifdef PRINT_STATISTICS_3D_VIEWER
224 int64_t start_Time = stats_startCopperLayersTime;
242 std::vector<const PCB_TRACK*> trackList;
244 trackList.reserve(
m_board->Tracks().size() );
256 trackList.push_back( track );
278 std::vector<PCB_LAYER_ID> layer_ids;
287 layer_ids.push_back( layer );
314 if( aStatusReporter )
315 aStatusReporter->
Report(
_(
"Create tracks and vias" ) );
324 for(
const PCB_TRACK* track : trackList )
327 if( !track->IsOnLayer( layer ) )
349 unsigned int nTracks = trackList.size();
351 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
353 const PCB_TRACK *track = trackList[trackIdx];
368 const float thickness =
static_cast<float>( plating / 2.0f );
369 const float hole_inner_radius =
static_cast<float>( holediameter / 2.0f );
370 const float ring_radius =
static_cast<float>( viasize / 2.0f );
385 else if( layer == layer_ids[0] )
394 if( hole_inner_radius > 0.0 )
400 const double frontRadius =
via->GetFrontPostMachiningSize() *
m_biuTo3Dunits / 2.0;
404 && frontRadius > hole_inner_radius )
406 if( layer == layer_ids[0] )
415 layerHoleContainer->
Add(
new FILLED_CIRCLE_2D( via_center, frontRadius + thickness, *track ) );
419 const double backRadius =
via->GetBackPostMachiningSize() *
m_biuTo3Dunits / 2.0;
423 && backRadius > hole_inner_radius )
426 if( layer == layer_ids.back() )
435 layerHoleContainer->
Add(
new FILLED_CIRCLE_2D( via_center, backRadius + thickness, *track ) );
439 float backdrillRadius =
via->GetSecondaryDrillSize().value_or( 0 ) *
m_biuTo3Dunits / 2.0f ;
442 if( backdrillRadius > hole_inner_radius + thickness )
447 bool validLyPair = secStart >= 0 && secEnd >= 0;
457 if( validLyPair && layer == secStart )
462 float tertiaryDrillRadius =
via->GetTertiaryDrillSize().value_or( 0 ) *
m_biuTo3Dunits / 2.0f ;
465 if( tertiaryDrillRadius > hole_inner_radius + thickness )
470 bool validLyPair = terStart >= 0 && terEnd >= 0;
477 layerHoleContainer->
Add(
new FILLED_CIRCLE_2D( via_center, tertiaryDrillRadius, *track ) );
480 if( validLyPair && layer == terStart )
512 const unsigned int nTracks = trackList.size();
514 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
516 const PCB_TRACK *track = trackList[trackIdx];
538 const int holediameter =
via->GetDrillValue();
550 else if( layer == layer_ids[0] )
552 const int hole_outer_ring_radius =
KiROUND(
via->GetWidth( layer ) / 2.0 );
570 const auto frontMode =
via->GetFrontPostMachining();
572 if( frontMode.has_value()
576 const int frontRadiusBIU =
via->GetFrontPostMachiningSize() / 2;
578 if( frontRadiusBIU > holediameter / 2 )
585 frontRadiusBIU,
via->GetMaxError(),
591 frontRadiusBIU,
via->GetMaxError(),
596 frontRadiusOuterBIU,
via->GetMaxError(),
599 frontRadiusBIU,
via->GetMaxError(),
604 const auto backMode =
via->GetBackPostMachining();
606 if( backMode.has_value()
610 const int backRadiusBIU =
via->GetBackPostMachiningSize() / 2;
612 if( backRadiusBIU > holediameter / 2 )
619 backRadiusBIU,
via->GetMaxError(),
625 backRadiusBIU,
via->GetMaxError(),
630 backRadiusOuterBIU,
via->GetMaxError(),
633 backRadiusBIU,
via->GetMaxError(),
639 const auto secondaryDrillSize =
via->GetSecondaryDrillSize();
641 if( secondaryDrillSize.has_value() && secondaryDrillSize.value() > 0 )
643 const int backdrillRadiusBIU = secondaryDrillSize.value() / 2;
645 const int holeOuterRadiusBIU = hole_outer_radius;
648 if( backdrillOuterRadiusBIU > holeOuterRadiusBIU )
652 bool validLyPair = secStart >= 0 && secEnd >= 0;
658 backdrillOuterRadiusBIU,
via->GetMaxError(),
662 backdrillRadiusBIU,
via->GetMaxError(),
666 backdrillOuterRadiusBIU,
via->GetMaxError(),
673 const auto tertiaryDrillSize =
via->GetTertiaryDrillSize();
675 if( tertiaryDrillSize.has_value() && tertiaryDrillSize.value() > 0 )
677 const int backdrillRadiusBIU = tertiaryDrillSize.value() / 2;
679 const int holeOuterRadiusBIU = hole_outer_radius;
682 if( backdrillOuterRadiusBIU > holeOuterRadiusBIU )
686 bool validLyPair = terStart >= 0 && terEnd >= 0;
693 backdrillOuterRadiusBIU,
via->GetMaxError(),
697 backdrillRadiusBIU,
via->GetMaxError(),
701 backdrillOuterRadiusBIU,
via->GetMaxError(),
720 unsigned int nTracks = trackList.size();
722 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
724 const PCB_TRACK *track = trackList[trackIdx];
742 for(
PAD*
pad : footprint->Pads() )
745 if( !
pad->HasHole() )
749 double holeDiameter = (
pad->GetDrillSize().x +
pad->GetDrillSize().y ) / 2.0;
772 const float holeDiameterUnits =
static_cast<float>(
774 const float holeInnerRadius = holeDiameterUnits / 2.0f;
778 const auto frontMode =
pad->GetFrontPostMachining();
780 if( frontMode.has_value()
784 const float frontRadius =
pad->GetFrontPostMachiningSize() * 0.5f
787 if( frontRadius > holeInnerRadius )
802 const auto backMode =
pad->GetBackPostMachining();
804 if( backMode.has_value()
808 const float backRadius =
pad->GetBackPostMachiningSize() * 0.5f
811 if( backRadius > holeInnerRadius )
827 const VECTOR2I& secDrillSize =
pad->GetSecondaryDrillSize();
829 if( secDrillSize.
x > 0 || secDrillSize.
y > 0 )
831 const float backdrillRadius = ( secDrillSize.
x + secDrillSize.
y ) * 0.25f
835 const float holeOuterRadius = holeInnerRadius
840 if( backdrillRadius > holeOuterRadius )
844 bool validLyPair = secStart >= 0 && secEnd >= 0;
865 layerHoleContainer->
Add(
880 for(
PAD*
pad : footprint->Pads() )
882 if( !
pad->HasHole() )
906 const double holeDiameter = (
pad->GetDrillSize().x +
pad->GetDrillSize().y ) / 2.0;
907 const int holeRadius =
KiROUND( holeDiameter / 2.0 );
909 const auto frontMode =
pad->GetFrontPostMachining();
911 if( frontMode.has_value()
915 const int frontRadiusBIU =
pad->GetFrontPostMachiningSize() / 2;
917 if( frontRadiusBIU > holeRadius )
922 frontRadiusBIU,
pad->GetMaxError(),
928 frontRadiusBIU,
pad->GetMaxError(),
934 const auto backMode =
pad->GetBackPostMachining();
936 if( backMode.has_value()
940 const int backRadiusBIU =
pad->GetBackPostMachiningSize() / 2;
942 if( backRadiusBIU > holeRadius )
947 backRadiusBIU,
pad->GetMaxError(),
953 backRadiusBIU,
pad->GetMaxError(),
960 const VECTOR2I& secDrillSize =
pad->GetSecondaryDrillSize();
962 if( secDrillSize.
x > 0 || secDrillSize.
y > 0 )
964 const int backdrillRadiusBIU = ( secDrillSize.
x + secDrillSize.
y ) / 4;
965 const int holeOuterRadiusBIU = holeRadius + inflate;
968 if( backdrillRadiusBIU > holeOuterRadiusBIU )
972 bool validLyPair = secStart >= 0 && secEnd >= 0;
977 backdrillRadiusBIU,
pad->GetMaxError(),
998 backdrillRadiusBIU,
pad->GetMaxError(),
1016 addPads( fp, layerContainer, layer );
1024 fp->TransformPadsToPolySet( *layerPoly, layer, 0, fp->GetMaxError(),
ERROR_INSIDE );
1036 fp->TransformPadsToPolySet( *layerPoly, layer, 0, fp->GetMaxError(),
ERROR_INSIDE );
1053 if( !item->IsOnLayer( layer ) )
1056 switch( item->Type() )
1090 wxLogTrace(
m_logTrace, wxT(
"createLayers: item type: %d not implemented" ), item->Type() );
1107 text_box->PCB_SHAPE::TransformShapeToPolygon( *copperPolys, layer, 0, text_box->
GetMaxError(),
1117 item->TransformShapeToPolySet( *copperPolys, layer, 0, item->GetMaxError(),
ERROR_INSIDE );
1128 switch( item->Type() )
1131 item->TransformShapeToPolySet( *layerPoly, layer, 0, item->GetMaxError(),
ERROR_INSIDE );
1148 textbox->PCB_SHAPE::TransformShapeToPolygon( *layerPoly, layer, 0, textbox->
GetMaxError(),
1161 cell->TransformTextToPolySet( *layerPoly, 0, cell->GetMaxError(),
ERROR_INSIDE );
1191 for(
const std::shared_ptr<SHAPE>& shape : dimension->
GetShapes() )
1201 wxLogTrace(
m_logTrace, wxT(
"createLayers: item type: %d not implemented" ), item->Type() );
1210 if( aStatusReporter )
1211 aStatusReporter->
Report(
_(
"Create zones" ) );
1213 std::vector<std::pair<ZONE*, PCB_LAYER_ID>> zones;
1214 std::unordered_map<PCB_LAYER_ID, std::unique_ptr<std::mutex>> layer_lock;
1220 zones.emplace_back( std::make_pair( zone, layer ) );
1221 layer_lock.emplace( layer, std::make_unique<std::mutex>() );
1227 zone->TransformShapeToPolygon( *copperPolys, layer, 0, zone->GetMaxError(),
ERROR_INSIDE );
1233 std::atomic<size_t> nextZone( 0 );
1234 std::atomic<size_t> threadsFinished( 0 );
1236 size_t parallelThreadCount = std::min<size_t>( zones.size(),
1237 std::max<size_t>( std::thread::hardware_concurrency(), 2 ) );
1239 for(
size_t ii = 0; ii < parallelThreadCount; ++ii )
1241 std::thread t = std::thread( [&]()
1243 for(
size_t areaId = nextZone.fetch_add( 1 );
1244 areaId < zones.size();
1245 areaId = nextZone.fetch_add( 1 ) )
1247 ZONE* zone = zones[areaId].first;
1249 if( zone ==
nullptr )
1260 auto mut_it = layer_lock.find( layer );
1262 if( mut_it != layer_lock.end() )
1264 std::lock_guard< std::mutex > lock( *( mut_it->second ) );
1276 while( threadsFinished < parallelThreadCount )
1277 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1319 if( aStatusReporter )
1320 aStatusReporter->
Report(
_(
"Build Tech layers" ) );
1386 std::bitset<LAYER_3D_END> enabledFlags = visibilityFlags;
1396 if( aStatusReporter )
1397 aStatusReporter->
Report( wxString::Format(
_(
"Build Tech layer %d" ), (
int) layer ) );
1413 if( !item->IsOnLayer( layer ) )
1416 switch( item->Type() )
1456 if( !track->IsOnLayer( layer ) )
1466 if( !
via->FlashLayer( copper_layer ) )
1470 int maskExpansion = track->GetSolderMaskExpansion();
1476 const bool isPasteLayer = ( layer ==
F_Paste || layer ==
B_Paste );
1477 const wxString currentVariant =
m_board->GetCurrentVariant();
1482 bool skipForVariantDNP = isPasteLayer && footprint->GetDNPForVariant( currentVariant );
1488 for(
PAD*
pad : footprint->Pads() )
1490 if( !
pad->IsOnLayer( layer ) )
1496 else if( !skipForVariantDNP )
1498 addPads( footprint, layerContainer, layer );
1501 if( !skipForVariantDNP )
1510 if( zone->IsOnLayer( layer ) )
1524 if( !item->IsOnLayer( layer ) )
1527 switch( item->Type() )
1530 item->TransformShapeToPolySet( *layerPoly, layer, 0, item->GetMaxError(),
ERROR_INSIDE );
1547 textbox->PCB_SHAPE::TransformShapeToPolygon( *layerPoly, layer, 0, textbox->
GetMaxError(),
1560 cell->TransformTextToPolySet( *layerPoly, 0, cell->GetMaxError(),
ERROR_INSIDE );
1597 if(
via->FlashLayer( layer ) && !
via->IsTented( layer ) )
1599 track->TransformShapeToPolygon( *layerPoly, layer, maskExpansion, track->GetMaxError(),
1605 if( track->HasSolderMask() )
1607 track->TransformShapeToPolySet( *layerPoly, layer, maskExpansion, track->GetMaxError(),
1621 for(
PAD*
pad : footprint->Pads() )
1623 if(
pad->IsOnLayer( layer ) )
1632 footprint->TransformPadsToPolySet( *layerPoly, layer, 0, footprint->GetMaxError(),
ERROR_INSIDE );
1644 if( zone->IsOnLayer( layer ) )
1645 zone->TransformSolidAreasShapesToPolygon( layer, *layerPoly );
1663 if( !footprint->GetBoundingBox().Intersects( boardBBox ) )
1665 if( footprint->IsFlipped() )
1678 if( aStatusReporter )
1679 aStatusReporter->
Report(
_(
"Simplifying copper layer polygons" ) );
1683 if( aStatusReporter )
1684 aStatusReporter->
Report(
_(
"Calculating plated copper" ) );
1713 std::vector<PCB_LAYER_ID> &selected_layer_id = layer_ids;
1714 std::vector<PCB_LAYER_ID> layer_id_without_F_and_B;
1718 layer_id_without_F_and_B.clear();
1719 layer_id_without_F_and_B.reserve( layer_ids.size() );
1723 if( layer !=
F_Cu && layer !=
B_Cu )
1724 layer_id_without_F_and_B.push_back( layer );
1727 selected_layer_id = layer_id_without_F_and_B;
1730 if( selected_layer_id.size() > 0 )
1732 if( aStatusReporter )
1734 aStatusReporter->
Report( wxString::Format(
_(
"Simplifying %d copper layers" ),
1735 (
int) selected_layer_id.size() ) );
1738 std::atomic<size_t> nextItem( 0 );
1739 std::atomic<size_t> threadsFinished( 0 );
1741 size_t parallelThreadCount = std::min<size_t>(
1742 std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
1743 selected_layer_id.size() );
1745 for(
size_t ii = 0; ii < parallelThreadCount; ++ii )
1747 std::thread t = std::thread(
1748 [&nextItem, &threadsFinished, &selected_layer_id,
this]()
1750 for(
size_t i = nextItem.fetch_add( 1 );
1751 i < selected_layer_id.size();
1752 i = nextItem.fetch_add( 1 ) )
1768 while( threadsFinished < parallelThreadCount )
1769 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1774 if( aStatusReporter )
1775 aStatusReporter->
Report(
_(
"Simplify holes contours" ) );
1794 if( aStatusReporter )
1795 aStatusReporter->
Report(
_(
"Build BVH for holes and vias" ) );
1810 for( std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& hole :
m_layerHoleMap )
1811 hole.second->BuildBVH();