235 if( aStop.stop_requested() )
242#ifdef PRINT_STATISTICS_3D_VIEWER
245 int64_t start_Time = stats_startCopperLayersTime;
263 std::vector<const PCB_TRACK*> trackList;
265 trackList.reserve(
m_board->Tracks().size() );
277 trackList.push_back( track );
299 std::vector<PCB_LAYER_ID> layer_ids;
308 layer_ids.push_back( layer );
335 if( aStop.stop_requested() )
338 if( aStatusReporter )
339 aStatusReporter->Report(
_(
"Create tracks and vias" ) );
348 for(
const PCB_TRACK* track : trackList )
351 if( !track->IsOnLayer( layer ) )
363 if( aStop.stop_requested() )
376 unsigned int nTracks = trackList.size();
378 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
380 const PCB_TRACK *track = trackList[trackIdx];
395 const float thickness =
static_cast<float>( plating / 2.0f );
396 const float hole_inner_radius =
static_cast<float>( holediameter / 2.0f );
397 const float ring_radius =
static_cast<float>( viasize / 2.0f );
414 else if( layer == layer_ids[0] )
426 if( hole_inner_radius > 0.0 )
432 const double frontRadius =
via->GetFrontPostMachiningSize() *
m_biuTo3Dunits / 2.0;
436 && frontRadius > hole_inner_radius )
438 if( layer == layer_ids[0] )
447 layerHoleContainer->
Add(
new FILLED_CIRCLE_2D( via_center, frontRadius + thickness, *track ) );
451 const double backRadius =
via->GetBackPostMachiningSize() *
m_biuTo3Dunits / 2.0;
455 && backRadius > hole_inner_radius )
458 if( layer == layer_ids.back() )
467 layerHoleContainer->
Add(
new FILLED_CIRCLE_2D( via_center, backRadius + thickness, *track ) );
471 float backdrillRadius =
via->GetSecondaryDrillSize().value_or( 0 ) *
m_biuTo3Dunits / 2.0f ;
474 if( backdrillRadius > hole_inner_radius + thickness )
479 bool validLyPair = secStart >= 0 && secEnd >= 0;
489 if( validLyPair && layer == secStart )
494 float tertiaryDrillRadius =
via->GetTertiaryDrillSize().value_or( 0 ) *
m_biuTo3Dunits / 2.0f ;
497 if( tertiaryDrillRadius > hole_inner_radius + thickness )
502 bool validLyPair = terStart >= 0 && terEnd >= 0;
509 layerHoleContainer->
Add(
new FILLED_CIRCLE_2D( via_center, tertiaryDrillRadius, *track ) );
512 if( validLyPair && layer == terStart )
529 if( aStop.stop_requested() )
547 const unsigned int nTracks = trackList.size();
549 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
551 const PCB_TRACK *track = trackList[trackIdx];
573 const int holediameter =
via->GetDrillValue();
585 else if( layer == layer_ids[0] )
587 const int hole_outer_ring_radius =
KiROUND(
via->GetWidth( layer ) / 2.0 );
605 const auto frontMode =
via->GetFrontPostMachining();
607 if( frontMode.has_value()
611 const int frontRadiusBIU =
via->GetFrontPostMachiningSize() / 2;
613 if( frontRadiusBIU > holediameter / 2 )
635 const auto backMode =
via->GetBackPostMachining();
637 if( backMode.has_value()
641 const int backRadiusBIU =
via->GetBackPostMachiningSize() / 2;
643 if( backRadiusBIU > holediameter / 2 )
666 const auto secondaryDrillSize =
via->GetSecondaryDrillSize();
668 if( secondaryDrillSize.has_value() && secondaryDrillSize.value() > 0 )
670 const int backdrillRadiusBIU = secondaryDrillSize.value() / 2;
672 const int holeOuterRadiusBIU = hole_outer_radius;
675 if( backdrillOuterRadiusBIU > holeOuterRadiusBIU )
679 bool validLyPair = secStart >= 0 && secEnd >= 0;
697 const auto tertiaryDrillSize =
via->GetTertiaryDrillSize();
699 if( tertiaryDrillSize.has_value() && tertiaryDrillSize.value() > 0 )
701 const int backdrillRadiusBIU = tertiaryDrillSize.value() / 2;
703 const int holeOuterRadiusBIU = hole_outer_radius;
706 if( backdrillOuterRadiusBIU > holeOuterRadiusBIU )
710 bool validLyPair = terStart >= 0 && terEnd >= 0;
729 if( aStop.stop_requested() )
744 unsigned int nTracks = trackList.size();
746 for(
unsigned int trackIdx = 0; trackIdx < nTracks; ++trackIdx )
748 const PCB_TRACK *track = trackList[trackIdx];
763 if( aStop.stop_requested() )
769 for(
PAD*
pad : footprint->Pads() )
772 if( !
pad->HasHole() )
776 double holeDiameter = (
pad->GetDrillSize().x +
pad->GetDrillSize().y ) / 2.0;
799 const float holeDiameterUnits =
static_cast<float>( (
pad->GetDrillSize().x +
pad->GetDrillSize().y )
801 const float holeInnerRadius = holeDiameterUnits / 2.0f;
805 const auto frontMode =
pad->GetFrontPostMachining();
807 if( frontMode.has_value()
811 float frontRadius =
pad->GetFrontPostMachiningSize() * 0.5f *
static_cast<float>(
m_biuTo3Dunits );
813 if( frontRadius > holeInnerRadius )
826 const auto backMode =
pad->GetBackPostMachining();
828 if( backMode.has_value()
832 float backRadius =
pad->GetBackPostMachiningSize() * 0.5f *
static_cast<float>(
m_biuTo3Dunits );
834 if( backRadius > holeInnerRadius )
848 const VECTOR2I& secDrillSize =
pad->GetSecondaryDrillSize();
850 if( secDrillSize.
x > 0 || secDrillSize.
y > 0 )
852 const float backdrillRadius = ( secDrillSize.
x + secDrillSize.
y ) * 0.25f
856 const float holeOuterRadius = holeInnerRadius
860 if( backdrillRadius > holeOuterRadius )
864 bool validLyPair = secStart >= 0 && secEnd >= 0;
891 if( aStop.stop_requested() )
901 for(
PAD*
pad : footprint->Pads() )
903 if( !
pad->HasHole() )
927 const double holeDiameter = (
pad->GetDrillSize().x +
pad->GetDrillSize().y ) / 2.0;
928 const int holeRadius =
KiROUND( holeDiameter / 2.0 );
930 const std::optional<PAD_DRILL_POST_MACHINING_MODE> frontMode =
pad->GetFrontPostMachining();
932 if( frontMode.has_value()
936 const int frontRadiusBIU =
pad->GetFrontPostMachiningSize() / 2;
938 if( frontRadiusBIU > holeRadius )
953 const std::optional<PAD_DRILL_POST_MACHINING_MODE> backMode =
pad->GetBackPostMachining();
955 if( backMode.has_value()
959 const int backRadiusBIU =
pad->GetBackPostMachiningSize() / 2;
961 if( backRadiusBIU > holeRadius )
977 const VECTOR2I& secDrillSize =
pad->GetSecondaryDrillSize();
979 if( secDrillSize.
x > 0 || secDrillSize.
y > 0 )
981 const int backdrillRadiusBIU = ( secDrillSize.
x + secDrillSize.
y ) / 4;
982 const int holeOuterRadiusBIU = holeRadius + inflate;
985 if( backdrillRadiusBIU > holeOuterRadiusBIU )
989 bool validLyPair = secStart >= 0 && secEnd >= 0;
1020 if( aStop.stop_requested() )
1033 addPads( fp, layerContainer, layer );
1041 fp->TransformPadsToPolySet( *layerPoly, layer, 0, fp->GetMaxError(),
ERROR_INSIDE );
1053 fp->TransformPadsToPolySet( *layerPoly, layer, 0, fp->GetMaxError(),
ERROR_INSIDE );
1058 if( aStop.stop_requested() )
1073 if( !item->IsOnLayer( layer ) )
1076 switch( item->Type() )
1110 wxLogTrace(
m_logTrace, wxT(
"createLayers: item type: %d not implemented" ), item->Type() );
1127 text_box->PCB_SHAPE::TransformShapeToPolygon( *copperPolys, layer, 0, text_box->
GetMaxError(),
1137 item->TransformShapeToPolySet( *copperPolys, layer, 0, item->GetMaxError(),
ERROR_INSIDE );
1148 switch( item->Type() )
1151 item->TransformShapeToPolySet( *layerPoly, layer, 0, item->GetMaxError(),
ERROR_INSIDE );
1168 textbox->PCB_SHAPE::TransformShapeToPolygon( *layerPoly, layer, 0, textbox->
GetMaxError(),
1181 cell->TransformTextToPolySet( *layerPoly, 0, cell->GetMaxError(),
ERROR_INSIDE );
1211 for(
const std::shared_ptr<SHAPE>& shape : dimension->
GetShapes() )
1221 wxLogTrace(
m_logTrace, wxT(
"createLayers: item type: %d not implemented" ), item->Type() );
1227 if( aStop.stop_requested() )
1231 if( aStop.stop_requested() )
1236 if( aStatusReporter )
1237 aStatusReporter->Report(
_(
"Create zones" ) );
1239 std::vector<std::pair<ZONE*, PCB_LAYER_ID>> zones;
1240 std::unordered_map<PCB_LAYER_ID, std::unique_ptr<std::mutex>> layer_lock;
1246 zones.emplace_back( std::make_pair( zone, layer ) );
1247 layer_lock.emplace( layer, std::make_unique<std::mutex>() );
1253 zone->TransformShapeToPolygon( *copperPolys, layer, 0, zone->GetMaxError(),
ERROR_INSIDE );
1257 if( aStop.stop_requested() )
1262 std::atomic<size_t> nextZone( 0 );
1263 std::atomic<size_t> threadsFinished( 0 );
1265 size_t parallelThreadCount = std::min<size_t>( zones.size(),
1266 std::max<size_t>( std::thread::hardware_concurrency(), 2 ) );
1268 for(
size_t ii = 0; ii < parallelThreadCount; ++ii )
1270 std::thread t = std::thread( [&]()
1272 for(
size_t areaId = nextZone.fetch_add( 1 );
1273 areaId < zones.size();
1274 areaId = nextZone.fetch_add( 1 ) )
1276 ZONE* zone = zones[areaId].first;
1278 if( zone ==
nullptr )
1289 auto mut_it = layer_lock.find( layer );
1291 if( mut_it != layer_lock.end() )
1293 std::lock_guard< std::mutex > lock( *( mut_it->second ) );
1305 while( threadsFinished < parallelThreadCount )
1306 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1310 if( aStop.stop_requested() )
1351 if( aStatusReporter )
1352 aStatusReporter->Report(
_(
"Build Tech layers" ) );
1422 std::bitset<LAYER_3D_END> enabledFlags = visibilityFlags;
1430 if( aStop.stop_requested() )
1435 if( aStatusReporter )
1436 aStatusReporter->Report( wxString::Format(
_(
"Build Tech layer %d" ), (
int) layer ) );
1452 if( !item->IsOnLayer( layer ) )
1455 switch( item->Type() )
1495 if( !track->IsOnLayer( layer ) )
1505 if( !
via->FlashLayer( copper_layer ) )
1509 int maskExpansion = track->GetSolderMaskExpansion();
1523 for(
PAD*
pad : footprint->Pads() )
1525 if( !
pad->IsOnLayer( layer ) )
1533 addPads( footprint, layerContainer, layer );
1544 if( zone->IsOnLayer( layer ) )
1550 if( aStop.stop_requested() )
1561 if( !item->IsOnLayer( layer ) )
1564 switch( item->Type() )
1574 item->TransformShapeToPolySet( *layerPoly, layer, margin, item->GetMaxError(),
ERROR_INSIDE );
1592 textbox->PCB_SHAPE::TransformShapeToPolygon( *layerPoly, layer, 0, textbox->
GetMaxError(),
1605 cell->TransformTextToPolySet( *layerPoly, 0, cell->GetMaxError(),
ERROR_INSIDE );
1631 if( aStop.stop_requested() )
1645 if(
via->FlashLayer( layer ) && !
via->IsTented( layer ) )
1647 track->TransformShapeToPolygon( *layerPoly, layer, maskExpansion, track->GetMaxError(),
1653 if( track->HasSolderMask() )
1655 track->TransformShapeToPolySet( *layerPoly, layer, maskExpansion, track->GetMaxError(),
1662 if( aStop.stop_requested() )
1672 for(
PAD*
pad : footprint->Pads() )
1674 if(
pad->IsOnLayer( layer ) )
1683 footprint->TransformPadsToPolySet( *layerPoly, layer, 0, footprint->GetMaxError(),
ERROR_INSIDE );
1691 if( aStop.stop_requested() )
1698 if( zone->IsOnLayer( layer ) )
1699 zone->TransformSolidAreasShapesToPolygon( layer, *layerPoly );
1703 if( aStop.stop_requested() )
1709 if( aStop.stop_requested() )
1715 if( aStop.stop_requested() )
1726 if( !footprint->GetBoundingBox().Intersects( boardBBox ) )
1728 if( footprint->IsFlipped() )
1739 if( aStop.stop_requested() )
1743 if( aStatusReporter )
1744 aStatusReporter->Report(
_(
"Simplifying copper layer polygons" ) );
1748 if( aStatusReporter )
1749 aStatusReporter->Report(
_(
"Calculating plated copper" ) );
1775 if( aStop.stop_requested() )
1781 std::vector<PCB_LAYER_ID> &selected_layer_id = layer_ids;
1782 std::vector<PCB_LAYER_ID> layer_id_without_F_and_B;
1786 layer_id_without_F_and_B.clear();
1787 layer_id_without_F_and_B.reserve( layer_ids.size() );
1791 if( layer !=
F_Cu && layer !=
B_Cu )
1792 layer_id_without_F_and_B.push_back( layer );
1795 selected_layer_id = layer_id_without_F_and_B;
1798 if( selected_layer_id.size() > 0 )
1800 if( aStatusReporter )
1802 aStatusReporter->Report( wxString::Format(
_(
"Simplifying %d copper layers" ),
1803 (
int) selected_layer_id.size() ) );
1806 std::atomic<size_t> nextItem( 0 );
1807 std::atomic<size_t> threadsFinished( 0 );
1809 size_t parallelThreadCount = std::min<size_t>(
1810 std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
1811 selected_layer_id.size() );
1813 for(
size_t ii = 0; ii < parallelThreadCount; ++ii )
1815 std::thread t = std::thread(
1816 [&nextItem, &threadsFinished, &selected_layer_id,
this]()
1818 for(
size_t i = nextItem.fetch_add( 1 );
1819 i < selected_layer_id.size();
1820 i = nextItem.fetch_add( 1 ) )
1836 while( threadsFinished < parallelThreadCount )
1837 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1840 if( aStop.stop_requested() )
1845 if( aStatusReporter )
1846 aStatusReporter->Report(
_(
"Simplify holes contours" ) );
1862 if( aStop.stop_requested() )
1868 if( aStatusReporter )
1869 aStatusReporter->Report(
_(
"Build BVH for holes and vias" ) );
1875 if( aStop.stop_requested() )
1885 if( aStop.stop_requested() )
1890 for( std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& hole :
m_layerHoleMap )
1891 hole.second->BuildBVH();
1894 if( aStop.stop_requested() )