217#ifdef PRINT_STATISTICS_3D_VIEWER
220 int64_t start_Time = stats_startCopperLayersTime;
238 std::vector<const PCB_TRACK*> trackList;
240 trackList.reserve(
m_board->Tracks().size() );
252 trackList.push_back( track );
274 std::vector<PCB_LAYER_ID> layer_ids;
283 layer_ids.push_back( layer );
310 if( aStatusReporter )
311 aStatusReporter->
Report(
_(
"Create tracks and vias" ) );
320 for(
const PCB_TRACK* track : trackList )
323 if( !track->IsOnLayer( layer ) )
345 unsigned int nTracks = trackList.size();
347 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
349 const PCB_TRACK *track = trackList[trackIdx];
364 const float thickness =
static_cast<float>( plating / 2.0f );
365 const float hole_inner_radius =
static_cast<float>( holediameter / 2.0f );
366 const float ring_radius =
static_cast<float>( viasize / 2.0f );
381 else if( layer == layer_ids[0] )
390 if( hole_inner_radius > 0.0 )
396 const double frontRadius =
via->GetFrontPostMachiningSize() *
m_biuTo3Dunits / 2.0;
400 && frontRadius > hole_inner_radius )
402 if( layer == layer_ids[0] )
411 layerHoleContainer->
Add(
new FILLED_CIRCLE_2D( via_center, frontRadius + thickness, *track ) );
415 const double backRadius =
via->GetBackPostMachiningSize() *
m_biuTo3Dunits / 2.0;
419 && backRadius > hole_inner_radius )
422 if( layer == layer_ids.back() )
431 layerHoleContainer->
Add(
new FILLED_CIRCLE_2D( via_center, backRadius + thickness, *track ) );
435 float backdrillRadius =
via->GetSecondaryDrillSize().value_or( 0 ) *
m_biuTo3Dunits / 2.0f ;
438 if( backdrillRadius > hole_inner_radius + thickness )
443 bool validLyPair = secStart >= 0 && secEnd >= 0;
453 if( validLyPair && layer == secStart )
458 float tertiaryDrillRadius =
via->GetTertiaryDrillSize().value_or( 0 ) *
m_biuTo3Dunits / 2.0f ;
461 if( tertiaryDrillRadius > hole_inner_radius + thickness )
466 bool validLyPair = terStart >= 0 && terEnd >= 0;
473 layerHoleContainer->
Add(
new FILLED_CIRCLE_2D( via_center, tertiaryDrillRadius, *track ) );
476 if( validLyPair && layer == terStart )
508 const unsigned int nTracks = trackList.size();
510 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
512 const PCB_TRACK *track = trackList[trackIdx];
534 const int holediameter =
via->GetDrillValue();
546 else if( layer == layer_ids[0] )
548 const int hole_outer_ring_radius =
KiROUND(
via->GetWidth( layer ) / 2.0 );
566 const auto frontMode =
via->GetFrontPostMachining();
568 if( frontMode.has_value()
572 const int frontRadiusBIU =
via->GetFrontPostMachiningSize() / 2;
574 if( frontRadiusBIU > holediameter / 2 )
581 frontRadiusBIU,
via->GetMaxError(),
587 frontRadiusBIU,
via->GetMaxError(),
592 frontRadiusOuterBIU,
via->GetMaxError(),
595 frontRadiusBIU,
via->GetMaxError(),
600 const auto backMode =
via->GetBackPostMachining();
602 if( backMode.has_value()
606 const int backRadiusBIU =
via->GetBackPostMachiningSize() / 2;
608 if( backRadiusBIU > holediameter / 2 )
615 backRadiusBIU,
via->GetMaxError(),
621 backRadiusBIU,
via->GetMaxError(),
626 backRadiusOuterBIU,
via->GetMaxError(),
629 backRadiusBIU,
via->GetMaxError(),
635 const auto secondaryDrillSize =
via->GetSecondaryDrillSize();
637 if( secondaryDrillSize.has_value() && secondaryDrillSize.value() > 0 )
639 const int backdrillRadiusBIU = secondaryDrillSize.value() / 2;
641 const int holeOuterRadiusBIU = hole_outer_radius;
644 if( backdrillOuterRadiusBIU > holeOuterRadiusBIU )
648 bool validLyPair = secStart >= 0 && secEnd >= 0;
654 backdrillOuterRadiusBIU,
via->GetMaxError(),
658 backdrillRadiusBIU,
via->GetMaxError(),
662 backdrillOuterRadiusBIU,
via->GetMaxError(),
669 const auto tertiaryDrillSize =
via->GetTertiaryDrillSize();
671 if( tertiaryDrillSize.has_value() && tertiaryDrillSize.value() > 0 )
673 const int backdrillRadiusBIU = tertiaryDrillSize.value() / 2;
675 const int holeOuterRadiusBIU = hole_outer_radius;
678 if( backdrillOuterRadiusBIU > holeOuterRadiusBIU )
682 bool validLyPair = terStart >= 0 && terEnd >= 0;
689 backdrillOuterRadiusBIU,
via->GetMaxError(),
693 backdrillRadiusBIU,
via->GetMaxError(),
697 backdrillOuterRadiusBIU,
via->GetMaxError(),
716 unsigned int nTracks = trackList.size();
718 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
720 const PCB_TRACK *track = trackList[trackIdx];
738 for(
PAD*
pad : footprint->Pads() )
741 if( !
pad->HasHole() )
745 double holeDiameter = (
pad->GetDrillSize().x +
pad->GetDrillSize().y ) / 2.0;
768 const float holeDiameterUnits =
static_cast<float>(
770 const float holeInnerRadius = holeDiameterUnits / 2.0f;
774 const auto frontMode =
pad->GetFrontPostMachining();
776 if( frontMode.has_value()
780 const float frontRadius =
pad->GetFrontPostMachiningSize() * 0.5f
783 if( frontRadius > holeInnerRadius )
798 const auto backMode =
pad->GetBackPostMachining();
800 if( backMode.has_value()
804 const float backRadius =
pad->GetBackPostMachiningSize() * 0.5f
807 if( backRadius > holeInnerRadius )
823 const VECTOR2I& secDrillSize =
pad->GetSecondaryDrillSize();
825 if( secDrillSize.
x > 0 || secDrillSize.
y > 0 )
827 const float backdrillRadius = ( secDrillSize.
x + secDrillSize.
y ) * 0.25f
831 const float holeOuterRadius = holeInnerRadius
836 if( backdrillRadius > holeOuterRadius )
840 bool validLyPair = secStart >= 0 && secEnd >= 0;
861 layerHoleContainer->
Add(
876 for(
PAD*
pad : footprint->Pads() )
878 if( !
pad->HasHole() )
902 const double holeDiameter = (
pad->GetDrillSize().x +
pad->GetDrillSize().y ) / 2.0;
903 const int holeRadius =
KiROUND( holeDiameter / 2.0 );
905 const auto frontMode =
pad->GetFrontPostMachining();
907 if( frontMode.has_value()
911 const int frontRadiusBIU =
pad->GetFrontPostMachiningSize() / 2;
913 if( frontRadiusBIU > holeRadius )
918 frontRadiusBIU,
pad->GetMaxError(),
924 frontRadiusBIU,
pad->GetMaxError(),
930 const auto backMode =
pad->GetBackPostMachining();
932 if( backMode.has_value()
936 const int backRadiusBIU =
pad->GetBackPostMachiningSize() / 2;
938 if( backRadiusBIU > holeRadius )
943 backRadiusBIU,
pad->GetMaxError(),
949 backRadiusBIU,
pad->GetMaxError(),
956 const VECTOR2I& secDrillSize =
pad->GetSecondaryDrillSize();
958 if( secDrillSize.
x > 0 || secDrillSize.
y > 0 )
960 const int backdrillRadiusBIU = ( secDrillSize.
x + secDrillSize.
y ) / 4;
961 const int holeOuterRadiusBIU = holeRadius + inflate;
964 if( backdrillRadiusBIU > holeOuterRadiusBIU )
968 bool validLyPair = secStart >= 0 && secEnd >= 0;
973 backdrillRadiusBIU,
pad->GetMaxError(),
994 backdrillRadiusBIU,
pad->GetMaxError(),
1012 addPads( fp, layerContainer, layer );
1020 fp->TransformPadsToPolySet( *layerPoly, layer, 0, fp->GetMaxError(),
ERROR_INSIDE );
1032 fp->TransformPadsToPolySet( *layerPoly, layer, 0, fp->GetMaxError(),
ERROR_INSIDE );
1049 if( !item->IsOnLayer( layer ) )
1052 switch( item->Type() )
1086 wxLogTrace(
m_logTrace, wxT(
"createLayers: item type: %d not implemented" ), item->Type() );
1103 text_box->PCB_SHAPE::TransformShapeToPolygon( *copperPolys, layer, 0, text_box->
GetMaxError(),
1113 item->TransformShapeToPolySet( *copperPolys, layer, 0, item->GetMaxError(),
ERROR_INSIDE );
1124 switch( item->Type() )
1127 item->TransformShapeToPolySet( *layerPoly, layer, 0, item->GetMaxError(),
ERROR_INSIDE );
1144 textbox->PCB_SHAPE::TransformShapeToPolygon( *layerPoly, layer, 0, textbox->
GetMaxError(),
1157 cell->TransformTextToPolySet( *layerPoly, 0, cell->GetMaxError(),
ERROR_INSIDE );
1187 for(
const std::shared_ptr<SHAPE>& shape : dimension->
GetShapes() )
1197 wxLogTrace(
m_logTrace, wxT(
"createLayers: item type: %d not implemented" ), item->Type() );
1206 if( aStatusReporter )
1207 aStatusReporter->
Report(
_(
"Create zones" ) );
1209 std::vector<std::pair<ZONE*, PCB_LAYER_ID>> zones;
1210 std::unordered_map<PCB_LAYER_ID, std::unique_ptr<std::mutex>> layer_lock;
1216 zones.emplace_back( std::make_pair( zone, layer ) );
1217 layer_lock.emplace( layer, std::make_unique<std::mutex>() );
1223 zone->TransformShapeToPolygon( *copperPolys, layer, 0, zone->GetMaxError(),
ERROR_INSIDE );
1229 std::atomic<size_t> nextZone( 0 );
1230 std::atomic<size_t> threadsFinished( 0 );
1232 size_t parallelThreadCount = std::min<size_t>( zones.size(),
1233 std::max<size_t>( std::thread::hardware_concurrency(), 2 ) );
1235 for(
size_t ii = 0; ii < parallelThreadCount; ++ii )
1237 std::thread t = std::thread( [&]()
1239 for(
size_t areaId = nextZone.fetch_add( 1 );
1240 areaId < zones.size();
1241 areaId = nextZone.fetch_add( 1 ) )
1243 ZONE* zone = zones[areaId].first;
1245 if( zone ==
nullptr )
1256 auto mut_it = layer_lock.find( layer );
1258 if( mut_it != layer_lock.end() )
1260 std::lock_guard< std::mutex > lock( *( mut_it->second ) );
1272 while( threadsFinished < parallelThreadCount )
1273 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1315 if( aStatusReporter )
1316 aStatusReporter->
Report(
_(
"Build Tech layers" ) );
1382 std::bitset<LAYER_3D_END> enabledFlags = visibilityFlags;
1392 if( aStatusReporter )
1393 aStatusReporter->
Report( wxString::Format(
_(
"Build Tech layer %d" ), (
int) layer ) );
1409 if( !item->IsOnLayer( layer ) )
1412 switch( item->Type() )
1452 if( !track->IsOnLayer( layer ) )
1462 if( !
via->FlashLayer( copper_layer ) )
1466 int maskExpansion = track->GetSolderMaskExpansion();
1480 for(
PAD*
pad : footprint->Pads() )
1482 if( !
pad->IsOnLayer( layer ) )
1490 addPads( footprint, layerContainer, layer );
1501 if( zone->IsOnLayer( layer ) )
1515 if( !item->IsOnLayer( layer ) )
1518 switch( item->Type() )
1521 item->TransformShapeToPolySet( *layerPoly, layer, 0, item->GetMaxError(),
ERROR_INSIDE );
1538 textbox->PCB_SHAPE::TransformShapeToPolygon( *layerPoly, layer, 0, textbox->
GetMaxError(),
1551 cell->TransformTextToPolySet( *layerPoly, 0, cell->GetMaxError(),
ERROR_INSIDE );
1588 if(
via->FlashLayer( layer ) && !
via->IsTented( layer ) )
1590 track->TransformShapeToPolygon( *layerPoly, layer, maskExpansion, track->GetMaxError(),
1596 if( track->HasSolderMask() )
1598 track->TransformShapeToPolySet( *layerPoly, layer, maskExpansion, track->GetMaxError(),
1612 for(
PAD*
pad : footprint->Pads() )
1614 if(
pad->IsOnLayer( layer ) )
1623 footprint->TransformPadsToPolySet( *layerPoly, layer, 0, footprint->GetMaxError(),
ERROR_INSIDE );
1635 if( zone->IsOnLayer( layer ) )
1636 zone->TransformSolidAreasShapesToPolygon( layer, *layerPoly );
1654 if( !footprint->GetBoundingBox().Intersects( boardBBox ) )
1656 if( footprint->IsFlipped() )
1669 if( aStatusReporter )
1670 aStatusReporter->
Report(
_(
"Simplifying copper layer polygons" ) );
1674 if( aStatusReporter )
1675 aStatusReporter->
Report(
_(
"Calculating plated copper" ) );
1704 std::vector<PCB_LAYER_ID> &selected_layer_id = layer_ids;
1705 std::vector<PCB_LAYER_ID> layer_id_without_F_and_B;
1709 layer_id_without_F_and_B.clear();
1710 layer_id_without_F_and_B.reserve( layer_ids.size() );
1714 if( layer !=
F_Cu && layer !=
B_Cu )
1715 layer_id_without_F_and_B.push_back( layer );
1718 selected_layer_id = layer_id_without_F_and_B;
1721 if( selected_layer_id.size() > 0 )
1723 if( aStatusReporter )
1725 aStatusReporter->
Report( wxString::Format(
_(
"Simplifying %d copper layers" ),
1726 (
int) selected_layer_id.size() ) );
1729 std::atomic<size_t> nextItem( 0 );
1730 std::atomic<size_t> threadsFinished( 0 );
1732 size_t parallelThreadCount = std::min<size_t>(
1733 std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
1734 selected_layer_id.size() );
1736 for(
size_t ii = 0; ii < parallelThreadCount; ++ii )
1738 std::thread t = std::thread(
1739 [&nextItem, &threadsFinished, &selected_layer_id,
this]()
1741 for(
size_t i = nextItem.fetch_add( 1 );
1742 i < selected_layer_id.size();
1743 i = nextItem.fetch_add( 1 ) )
1759 while( threadsFinished < parallelThreadCount )
1760 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1765 if( aStatusReporter )
1766 aStatusReporter->
Report(
_(
"Simplify holes contours" ) );
1785 if( aStatusReporter )
1786 aStatusReporter->
Report(
_(
"Build BVH for holes and vias" ) );
1801 for( std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& hole :
m_layerHoleMap )
1802 hole.second->BuildBVH();