KiCad PCB EDA Suite
Loading...
Searching...
No Matches
board_design_settings.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
22
23#include <algorithm>
24#include <cmath>
25
28#include <magic_enum.hpp>
29#include <pcb_dimension.h>
30#include <pcb_track.h>
31#include <layer_ids.h>
32#include <lset.h>
33#include <kiface_base.h>
34#include <pad.h>
36#include <drc/drc_item.h>
37#include <drc/drc_engine.h>
39#include <settings/parameters.h>
41#include <advanced_config.h>
42#include <wx/debug.h>
43
44const int bdsSchemaVersion = 3;
45
46
47BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
48 NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aParent, aPath )
49{
50 // We want to leave alone parameters that aren't found in the project JSON as they may be
51 // initialized by the board file parser before NESTED_SETTINGS::LoadFromFile is called.
53
54 // Create a default NET_SETTINGS so that things don't break horribly if there's no project
55 // loaded. This also is used during file load for legacy boards that have netclasses stored
56 // in the file. After load, this information will be moved to the project and the pointer
57 // updated.
58 m_NetSettings = std::make_shared<NET_SETTINGS>( nullptr, "" );
59
60 m_HasStackup = false; // no stackup defined by default
61
62 LSET all_set = LSET().set();
63 m_enabledLayers = all_set; // All layers enabled at first.
64 // SetCopperLayerCount() will adjust this.
65
66 // Default design is a double layer board with 4 user defined layers
69
71
72 // if true, when creating a new track starting on an existing track, use this track width
75
76 // First is always the reference designator
77 m_DefaultFPTextItems.emplace_back( wxT( "REF**" ), true, F_SilkS );
78 // Second is always the value
79 m_DefaultFPTextItems.emplace_back( wxT( "" ), true, F_Fab );
80 // Any following ones are freebies
81 m_DefaultFPTextItems.emplace_back( wxT( "${REFERENCE}" ), true, F_Fab );
82
89
96
97 // Edges & Courtyards; text properties aren't used but better to have them holding
98 // reasonable values than not.
101 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
105
108 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
112
115 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
117 m_TextItalic[ LAYER_CLASS_FAB ] = false;
119
122 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
126
127 m_StyleFPFields = false;
128 m_StyleFPText = false;
129 m_StyleFPShapes = false;
130 m_StyleFPDimensions = false;
131 m_StyleFPBarcodes = false;
132
141
142 m_useCustomTrackVia = false;
144 m_customViaSize.m_Diameter = pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE );
146
147 m_useCustomDiffPair = false;
151
168
169 for( int errorCode = DRCE_FIRST; errorCode <= DRCE_LAST; ++errorCode )
170 m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
171
174
178
182
185
188
191
199
205
207
210
212
215
218
220
224
225 m_BomExportFileName = wxS( "${PROJECTNAME}.csv" );
226 m_BomSettings = BOM_PRESET::DefaultEditing();
228
229 // Global mask margins:
233
234 // Solder paste margin absolute value
236 // Solder paste margin as a ratio of pad size
237 // The final margin is the sum of these 2 values
238 // Usually < 0 because the mask is smaller than pad
240
242 m_TentViasFront = true;
243 m_TentViasBack = true;
244
245 m_CoverViasFront = false;
246 m_CoverViasBack = false;
247
248 m_PlugViasFront = false;
249 m_PlugViasBack = false;
250
251 m_CapVias = false;
252
253 m_FillVias = false;
254
255 // Layer thickness for 3D viewer
257
258 // Default spacing for meanders
262
263 m_viaSizeIndex = 0;
264 m_viaStackIndex = 0;
266 m_diffPairIndex = 0;
267
268 // Parameters stored in JSON in the project file
269
270 // NOTE: Previously, BOARD_DESIGN_SETTINGS stored the basic board layer information (layer
271 // names and enable/disable state) in the project file even though this information is also
272 // stored in the board file. This was implemented for importing these settings from another
273 // project. Going forward, the import feature will just import from other board files (since
274 // we could have multi-board projects in the future anyway) so this functionality is dropped.
275
276 m_params.emplace_back( new PARAM<wxString>( "bom_export_filename",
277 &m_BomExportFileName, "${PROJECTNAME}.csv" ) );
278
279 m_params.emplace_back( new PARAM<BOM_PRESET>( "bom_settings",
280 &m_BomSettings, BOM_PRESET::DefaultEditing() ) );
281 m_params.emplace_back( new PARAM_LIST<BOM_PRESET>( "bom_presets",
282 &m_BomPresets, {} ) );
283
284 m_params.emplace_back( new PARAM<BOM_FMT_PRESET>( "bom_fmt_settings",
286 m_params.emplace_back( new PARAM_LIST<BOM_FMT_PRESET>( "bom_fmt_presets",
287 &m_BomFmtPresets, {} ) );
288
289 m_params.emplace_back( new PARAM<bool>( "rules.use_height_for_length_calcs",
290 &m_UseHeightForLengthCalcs, true ) );
291
292 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_clearance",
294 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
295
296 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_connection",
298 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
299
300 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_track_width",
302 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
303
304 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_annular_width",
306 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
307
308 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_diameter",
310 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
311
312 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_through_hole_diameter",
314 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
315
316 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_diameter",
318 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), pcbIUScale.MM_PER_IU ) );
319
320 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_drill",
322 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), pcbIUScale.MM_PER_IU ) );
323
324 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_to_hole",
326 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), pcbIUScale.MM_PER_IU ) );
327
328 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_clearance",
330 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
331
332 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_silk_clearance",
334 pcbIUScale.mmToIU( -10.0 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
335
336 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_groove_width",
338 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
339
340 // While the maximum *effective* value is 4, we've had users interpret this as the count on
341 // all layers, and enter something like 10. They'll figure it out soon enough *unless* we
342 // enforce a max of 4 (and therefore reset it back to the default of 2), at which point it
343 // just looks buggy.
344 m_params.emplace_back( new PARAM<int>( "rules.min_resolved_spokes",
346
347 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_height",
349 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
350
351 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_thickness",
353 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
354
355 // Note: a clearance of -0.01 is a flag indicating we should use the legacy (pre-6.0) method
356 // based on the edge cut thicknesses.
357 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_copper_edge_clearance",
359 pcbIUScale.mmToIU( -0.01 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
360
361 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
362 [&]() -> nlohmann::json
363 {
364 nlohmann::json ret = {};
365
366 for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
367 {
368 wxString name = item.GetSettingsKey();
369 int code = item.GetErrorCode();
370
371 if( name.IsEmpty() || m_DRCSeverities.count( code ) == 0 )
372 continue;
373
374 ret[std::string( name.ToUTF8() )] = SeverityToString( m_DRCSeverities[code] );
375 }
376
377 return ret;
378 },
379 [&]( const nlohmann::json& aJson )
380 {
381 if( !aJson.is_object() )
382 return;
383
384 // Load V8 'hole_near_hole' token first (if present). Any current 'hole_to_hole' token
385 // found will then overwrite it.
386 // We can't use the migration architecture because we forgot to bump the version number
387 // when the change was made. But this is a one-off as any future deprecations should
388 // bump the version number and use registerMigration().
389 if( aJson.contains( "hole_near_hole" ) )
391
392 for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
393 {
394 wxString name = item.GetSettingsKey();
395 std::string key( name.ToUTF8() );
396
397 if( aJson.contains( key ) )
398 m_DRCSeverities[item.GetErrorCode()] = SeverityFromString( aJson[key] );
399 }
400 }, {} ) );
401
402 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "drc_exclusions",
403 [&]() -> nlohmann::json
404 {
405 nlohmann::json js = nlohmann::json::array();
406
407 for( const DRC_EXCLUSION& exclusion : m_DrcExclusions )
408 js.push_back( exclusion );
409
410 return js;
411 },
412 [&]( const nlohmann::json& aObj )
413 {
414 m_DrcExclusions.clear();
415
416 if( !aObj.is_array() )
417 return;
418
419 for( const nlohmann::json& entry : aObj )
420 {
421 if( entry.is_object() )
422 {
423 DRC_EXCLUSION exclusion = entry.get<DRC_EXCLUSION>();
424
425 if( !exclusion.GetSortKey().empty() )
426 m_DrcExclusions.insert( exclusion );
427 }
428 }
429 },
430 {} ) );
431
432 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "track_widths",
433 [&]() -> nlohmann::json
434 {
435 nlohmann::json js = nlohmann::json::array();
436
437 for( const int& width : m_TrackWidthList )
438 js.push_back( pcbIUScale.IUTomm( width ) );
439
440 return js;
441 },
442 [&]( const nlohmann::json& aJson )
443 {
444 if( !aJson.is_array() )
445 return;
446
447 m_TrackWidthList.clear();
448
449 for( const nlohmann::json& entry : aJson )
450 {
451 if( entry.empty() )
452 continue;
453
454 m_TrackWidthList.emplace_back( pcbIUScale.mmToIU( entry.get<double>() ) );
455 }
456 },
457 {} ) );
458
459 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "via_dimensions",
460 [&]() -> nlohmann::json
461 {
462 nlohmann::json js = nlohmann::json::array();
463
464 for( const auto& via : m_ViasDimensionsList )
465 {
466 nlohmann::json entry = {};
467
468 entry["diameter"] = pcbIUScale.IUTomm( via.m_Diameter );
469 entry["drill"] = pcbIUScale.IUTomm( via.m_Drill );
470
471 js.push_back( entry );
472 }
473
474 return js;
475 },
476 [&]( const nlohmann::json& aObj )
477 {
478 if( !aObj.is_array() )
479 return;
480
481 m_ViasDimensionsList.clear();
482
483 for( const nlohmann::json& entry : aObj )
484 {
485 if( entry.empty() || !entry.is_object() )
486 continue;
487
488 if( !entry.contains( "diameter" ) || !entry.contains( "drill" ) )
489 continue;
490
491 int diameter = pcbIUScale.mmToIU( entry["diameter"].get<double>() );
492 int drill = pcbIUScale.mmToIU( entry["drill"].get<double>() );
493
494 m_ViasDimensionsList.emplace_back( VIA_DIMENSION( diameter, drill ) );
495 }
496 },
497 {} ) );
498
499 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
500 "via_stack_presets",
501 [&]() -> nlohmann::json
502 {
503 nlohmann::json js = nlohmann::json::array();
504
505 for( const VIA_STACK_PRESET& preset : m_ViaStackPresets )
506 {
507 nlohmann::json entry = {};
508
509 entry["name"] = preset.m_Name.ToUTF8();
510 entry["start_layer"] = LSET::Name( preset.m_StartLayer );
511 entry["end_layer"] = LSET::Name( preset.m_EndLayer );
512 entry["staggered"] = preset.m_Staggered;
513 entry["via_size"] = pcbIUScale.IUTomm( preset.m_ViaSize );
514 entry["via_drill"] = pcbIUScale.IUTomm( preset.m_ViaDrill );
515 entry["use_netclass"] = preset.m_UseNetclass;
516 entry["filled"] = preset.m_Filled;
517 entry["capped"] = preset.m_Capped;
518 entry["pitch"] = pcbIUScale.IUTomm( preset.m_Pitch );
519
520 js.push_back( entry );
521 }
522
523 return js;
524 },
525 [&]( const nlohmann::json& aObj )
526 {
527 if( !aObj.is_array() )
528 return;
529
530 m_ViaStackPresets.clear();
531
532 // An odd or non-copper layer from a hand-edited file would make every
533 // LAYER_RANGE built from the preset throw or never terminate.
534 auto copperLayer = []( const nlohmann::json& aEntry, const char* aKey,
535 PCB_LAYER_ID aFallback ) -> PCB_LAYER_ID
536 {
537 if( !aEntry.contains( aKey ) || !aEntry[aKey].is_string() )
538 return aFallback;
539
540 wxString name = wxString::FromUTF8( aEntry[aKey].get<std::string>() );
541 int layer = LSET::NameToLayer( name );
542
543 if( layer >= 0 && layer < PCB_LAYER_ID_COUNT && !( layer & 1 ) && IsCopperLayer( layer ) )
544 return ToLAYER_ID( layer );
545
546 return aFallback;
547 };
548
549 auto boolOr = []( const nlohmann::json& aEntry, const char* aKey, bool aFallback )
550 {
551 return aEntry.contains( aKey ) && aEntry[aKey].is_boolean() ? aEntry[aKey].get<bool>() : aFallback;
552 };
553
554 auto mmOr = []( const nlohmann::json& aEntry, const char* aKey )
555 {
556 if( !aEntry.contains( aKey ) || !aEntry[aKey].is_number() )
557 return 0;
558
559 double mm = aEntry[aKey].get<double>();
560
561 if( mm < 0.0 || mm > pcbIUScale.IUTomm( std::numeric_limits<int>::max() ) )
562 return 0;
563
564 return pcbIUScale.mmToIU( mm );
565 };
566
567 // Bound in mm, before the conversion to IU, because an absurd hand-edited
568 // value overflows int on the way in and lands past the limit as a negative
569 auto boundedMmOr = []( const nlohmann::json& aEntry, const char* aKey, double aMaxMM )
570 {
571 if( !aEntry.contains( aKey ) || !aEntry[aKey].is_number() )
572 return 0;
573
574 return pcbIUScale.mmToIU( std::clamp( aEntry[aKey].get<double>(), 0.0, aMaxMM ) );
575 };
576
577 for( const nlohmann::json& entry : aObj )
578 {
579 if( entry.empty() || !entry.is_object() || !entry.contains( "name" ) || !entry["name"].is_string() )
580 {
581 continue;
582 }
583
584 VIA_STACK_PRESET preset;
585
586 preset.m_Name = wxString::FromUTF8( entry["name"].get<std::string>() );
587 preset.m_StartLayer = copperLayer( entry, "start_layer", F_Cu );
588 preset.m_EndLayer = copperLayer( entry, "end_layer", In1_Cu );
589 preset.m_Staggered = boolOr( entry, "staggered", false );
590 preset.m_ViaSize = mmOr( entry, "via_size" );
591 preset.m_ViaDrill = mmOr( entry, "via_drill" );
592 preset.m_UseNetclass = boolOr( entry, "use_netclass", false );
593 preset.m_Filled = boolOr( entry, "filled", true );
594 preset.m_Capped = boolOr( entry, "capped", false );
595 preset.m_Pitch = boundedMmOr( entry, "pitch", MAX_MICROVIA_STACK_PITCH_MM );
596
597 // Presets are referenced by name, so a duplicate would be ambiguous.
598 auto sameName = [&]( const VIA_STACK_PRESET& aOther )
599 {
600 return aOther.m_Name.CmpNoCase( preset.m_Name ) == 0;
601 };
602
603 if( std::none_of( m_ViaStackPresets.begin(), m_ViaStackPresets.end(), sameName ) )
604 m_ViaStackPresets.push_back( preset );
605 }
606 },
607 {} ) );
608
609 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "diff_pair_dimensions",
610 [&]() -> nlohmann::json
611 {
612 nlohmann::json js = nlohmann::json::array();
613
614 for( const auto& pair : m_DiffPairDimensionsList )
615 {
616 nlohmann::json entry = {};
617
618 entry["width"] = pcbIUScale.IUTomm( pair.m_Width );
619 entry["gap"] = pcbIUScale.IUTomm( pair.m_Gap );
620 entry["via_gap"] = pcbIUScale.IUTomm( pair.m_ViaGap );
621
622 js.push_back( entry );
623 }
624
625 return js;
626 },
627 [&]( const nlohmann::json& aObj )
628 {
629 if( !aObj.is_array() )
630 return;
631
633
634 for( const nlohmann::json& entry : aObj )
635 {
636 if( entry.empty() || !entry.is_object() )
637 continue;
638
639 if( !entry.contains( "width" )
640 || !entry.contains( "gap" )
641 || !entry.contains( "via_gap" ) )
642 {
643 continue;
644 }
645
646 int width = pcbIUScale.mmToIU( entry["width"].get<double>() );
647 int gap = pcbIUScale.mmToIU( entry["gap"].get<double>() );
648 int via_gap = pcbIUScale.mmToIU( entry["via_gap"].get<double>() );
649
650 m_DiffPairDimensionsList.emplace_back( DIFF_PAIR_DIMENSION( width, gap, via_gap ) );
651 }
652 },
653 {} ) );
654
655 // Handle options for teardrops (targets and some others):
656 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_options",
657 [&]() -> nlohmann::json
658 {
659 nlohmann::json js = nlohmann::json::array();
660 nlohmann::json entry = {};
661
662 entry["td_onvia"] = m_TeardropParamsList.m_TargetVias;
663 entry["td_onpthpad"] = m_TeardropParamsList.m_TargetPTHPads;
664 entry["td_onsmdpad"] = m_TeardropParamsList.m_TargetSMDPads;
665 entry["td_ontrackend"] = m_TeardropParamsList.m_TargetTrack2Track;
666 entry["td_onroundshapesonly"] = m_TeardropParamsList.m_UseRoundShapesOnly;
667
668 js.push_back( entry );
669
670 return js;
671 },
672 [&]( const nlohmann::json& aObj )
673 {
674 if( !aObj.is_array() )
675 return;
676
677 for( const nlohmann::json& entry : aObj )
678 {
679 if( entry.empty() || !entry.is_object() )
680 continue;
681
682 if( entry.contains( "td_onvia" ) )
683 m_TeardropParamsList.m_TargetVias = entry["td_onvia"].get<bool>();
684
685 if( entry.contains( "td_onpthpad" ) )
686 m_TeardropParamsList.m_TargetPTHPads = entry["td_onpthpad"].get<bool>();
687
688 if( entry.contains( "td_onsmdpad" ) )
689 m_TeardropParamsList.m_TargetSMDPads = entry["td_onsmdpad"].get<bool>();
690
691 if( entry.contains( "td_ontrackend" ) )
692 m_TeardropParamsList.m_TargetTrack2Track = entry["td_ontrackend"].get<bool>();
693
694 if( entry.contains( "td_onroundshapesonly" ) )
695 m_TeardropParamsList.m_UseRoundShapesOnly = entry["td_onroundshapesonly"].get<bool>();
696
697 // Legacy settings
698 for( int ii = 0; ii < 3; ++ii )
699 {
700 TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)ii );
701
702 if( entry.contains( "td_allow_use_two_tracks" ) )
703 td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
704
705 if( entry.contains( "td_curve_segcount" ) )
706 {
707 if( entry["td_curve_segcount"].get<int>() > 0 )
708 td_prm->m_CurvedEdges = true;
709 }
710
711 if( entry.contains( "td_on_pad_in_zone" ) )
712 td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
713 }
714 }
715 },
716 {} ) );
717
718 // Handle parameters (sizes, shape) for each type of teardrop:
719 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_parameters",
720 [&]() -> nlohmann::json
721 {
722 nlohmann::json js = nlohmann::json::array();
723
724 for( size_t ii = 0; ii < m_TeardropParamsList.GetParametersCount(); ii++ )
725 {
726 nlohmann::json entry = {};
727 TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)ii );
728
729 entry["td_target_name"] = GetTeardropTargetCanonicalName( (TARGET_TD)ii );
730 entry["td_enabled"] = td_prm->m_Enabled;
731 entry["td_maxlen"] = pcbIUScale.IUTomm( td_prm->m_TdMaxLen );
732 entry["td_maxheight"] = pcbIUScale.IUTomm( td_prm->m_TdMaxWidth );
733 entry["td_length_ratio"] = td_prm->m_BestLengthRatio;
734 entry["td_height_ratio"] = td_prm->m_BestWidthRatio;
735 entry["td_curve_segcount"] = td_prm->m_CurvedEdges ? 1 : 0;
736 entry["td_width_to_size_filter_ratio"] = td_prm->m_WidthtoSizeFilterRatio;
737 entry["td_allow_use_two_tracks"] = td_prm->m_AllowUseTwoTracks;
738 entry["td_on_pad_in_zone"] = td_prm->m_TdOnPadsInZones;
739
740 js.push_back( entry );
741 }
742
743 return js;
744 },
745 [&]( const nlohmann::json& aObj )
746 {
747 if( !aObj.is_array() )
748 return;
749
750 for( const nlohmann::json& entry : aObj )
751 {
752 if( entry.empty() || !entry.is_object() )
753 continue;
754
755 if( !entry.contains( "td_target_name" ) )
756 continue;
757
758 int idx = GetTeardropTargetTypeFromCanonicalName( entry["td_target_name"].get<std::string>() );
759
760 if( idx >= 0 && idx < 3 )
761 {
762 TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)idx );
763
764 // Pads and vias carry their enable in the board file; this one has
765 // nowhere else to live.
766 if( entry.contains( "td_enabled" ) )
767 td_prm->m_Enabled = entry["td_enabled"].get<bool>();
768
769 if( entry.contains( "td_maxlen" ) )
770 td_prm->m_TdMaxLen = pcbIUScale.mmToIU( entry["td_maxlen"].get<double>() );
771
772 if( entry.contains( "td_maxheight" ) )
773 td_prm->m_TdMaxWidth = pcbIUScale.mmToIU( entry["td_maxheight"].get<double>() );
774
775 if( entry.contains( "td_length_ratio" ) )
776 td_prm->m_BestLengthRatio = entry["td_length_ratio"].get<double>();
777
778 if( entry.contains( "td_height_ratio" ) )
779 td_prm->m_BestWidthRatio = entry["td_height_ratio"].get<double>();
780
781 if( entry.contains( "td_curve_segcount" ) )
782 {
783 if( entry["td_curve_segcount"].get<int>() > 0 )
784 td_prm->m_CurvedEdges = true;
785 }
786
787 if( entry.contains( "td_width_to_size_filter_ratio" ) )
788 td_prm->m_WidthtoSizeFilterRatio = entry["td_width_to_size_filter_ratio"].get<double>();
789
790 if( entry.contains( "td_allow_use_two_tracks" ) )
791 td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
792
793 if( entry.contains( "td_on_pad_in_zone" ) )
794 td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
795 }
796 }
797 },
798 {} ) );
799
800 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "tuning_pattern_settings",
801 [&]() -> nlohmann::json
802 {
803 nlohmann::json js = {};
804
805 auto make_settings =
806 []( const PNS::MEANDER_SETTINGS& aSettings )
807 {
808 nlohmann::json entry = {};
809
810 entry["min_amplitude"] = pcbIUScale.IUTomm( aSettings.m_minAmplitude );
811 entry["max_amplitude"] = pcbIUScale.IUTomm( aSettings.m_maxAmplitude );
812 entry["spacing"] = pcbIUScale.IUTomm( aSettings.m_spacing );
813 entry["corner_style"] = aSettings.m_cornerStyle == PNS::MEANDER_STYLE_CHAMFER ? 0 : 1;
814 entry["corner_radius_percentage"] = aSettings.m_cornerRadiusPercentage;
815 entry["single_sided"] = aSettings.m_singleSided;
816
817 return entry;
818 };
819
820 js["single_track_defaults"] = make_settings( m_SingleTrackMeanderSettings );
821 js["diff_pair_defaults"] = make_settings( m_DiffPairMeanderSettings );
822 js["diff_pair_skew_defaults"] = make_settings( m_SkewMeanderSettings );
823
824 return js;
825 },
826 [&]( const nlohmann::json& aObj )
827 {
828 auto read_settings =
829 []( const nlohmann::json& entry ) -> PNS::MEANDER_SETTINGS
830 {
831 PNS::MEANDER_SETTINGS settings;
832
833 if( entry.contains( "min_amplitude" ) )
834 settings.m_minAmplitude = pcbIUScale.mmToIU( entry["min_amplitude"].get<double>() );
835
836 if( entry.contains( "max_amplitude" ) )
837 settings.m_maxAmplitude = pcbIUScale.mmToIU( entry["max_amplitude"].get<double>() );
838
839 if( entry.contains( "spacing" ) )
840 settings.m_spacing = pcbIUScale.mmToIU( entry["spacing"].get<double>() );
841
842 if( entry.contains( "corner_style" ) )
843 {
844 settings.m_cornerStyle = entry["corner_style"] == 0 ? PNS::MEANDER_STYLE_CHAMFER
846 }
847
848 if( entry.contains( "corner_radius_percentage" ) )
849 settings.m_cornerRadiusPercentage = entry["corner_radius_percentage"].get<int>();
850
851 if( entry.contains( "single_sided" ) )
852 settings.m_singleSided = entry["single_sided"].get<bool>();
853
854 return settings;
855 };
856
857 if( aObj.contains( "single_track_defaults" ) )
858 m_SingleTrackMeanderSettings = read_settings( aObj["single_track_defaults"] );
859
860 if( aObj.contains( "diff_pair_defaults" ) )
861 m_DiffPairMeanderSettings = read_settings( aObj["diff_pair_defaults"] );
862
863 if( aObj.contains( "diff_pair_skew_defaults" ) )
864 m_SkewMeanderSettings = read_settings( aObj["diff_pair_skew_defaults"] );
865 },
866 {} ) );
867
868 int minTextSize = pcbIUScale.mmToIU( TEXT_MIN_SIZE_MM );
869 int maxTextSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
870 int minStroke = 1;
871 int maxStroke = pcbIUScale.mmToIU( 100 );
872
873 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_line_width",
875 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
876
877 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_v",
879 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
880
881 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_h",
883 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
884
885 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_thickness",
887 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
888
889 m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_italic",
890 &m_TextItalic[LAYER_CLASS_SILK], false ) );
891
892 m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_upright",
893 &m_TextUpright[ LAYER_CLASS_SILK ], true ) );
894
895 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_line_width",
897 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
898
899 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_v",
901 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
902
903 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_h",
905 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
906
907 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_thickness",
909 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
910
911 m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_italic",
912 &m_TextItalic[LAYER_CLASS_COPPER], false ) );
913
914 m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_upright",
916
917 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.board_outline_line_width",
919 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
920
921 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.courtyard_line_width",
923 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
924
925 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_line_width",
927 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
928
929 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_v",
931 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
932
933 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_h",
935 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
936
937 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_thickness",
939 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
940
941 m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_italic",
942 &m_TextItalic[LAYER_CLASS_FAB], false ) );
943
944 m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_upright",
945 &m_TextUpright[LAYER_CLASS_FAB], true ) );
946
947 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_line_width",
949 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
950
951 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_v",
953 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
954
955 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_h",
957 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
958
959 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_thickness",
961 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
962
963 m_params.emplace_back( new PARAM<bool>( "defaults.other_text_italic",
964 &m_TextItalic[LAYER_CLASS_OTHERS], false ) );
965
966 m_params.emplace_back( new PARAM<bool>( "defaults.other_text_upright",
968
969 m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_MODE>( "defaults.dimension_units",
972
973 m_params.emplace_back( new PARAM_ENUM<DIM_PRECISION>( "defaults.dimension_precision",
975
976 m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_FORMAT>( "defaults.dimensions.units_format",
979
980 m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.suppress_zeroes",
981 &m_DimensionSuppressZeroes, true ) );
982
983 // NOTE: excluding DIM_TEXT_POSITION::MANUAL from the valid range here
984 m_params.emplace_back( new PARAM_ENUM<DIM_TEXT_POSITION>( "defaults.dimensions.text_position",
987
988 m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.keep_text_aligned",
990
991 m_params.emplace_back( new PARAM<int>( "defaults.dimensions.arrow_length",
994
995 m_params.emplace_back( new PARAM<int>( "defaults.dimensions.extension_offset",
998
999 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_fields",
1000 &m_StyleFPFields, false ) );
1001 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_text",
1002 &m_StyleFPText, false ) );
1003 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_shapes",
1004 &m_StyleFPShapes, false ) );
1005 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_dimensions",
1006 &m_StyleFPDimensions, false ) );
1007 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_barcodes",
1008 &m_StyleFPBarcodes, false ) );
1009
1010 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.zones.min_clearance",
1011 &m_defaultZoneSettings.m_ZoneClearance, pcbIUScale.mmToIU( ZONE_CLEARANCE_MM ),
1012 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1013
1014 m_params.emplace_back( new PARAM_SCALED<int>(
1015 "defaults.zones.min_thickness", &m_defaultZoneSettings.m_ZoneMinThickness,
1017 pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1018
1019 m_params.emplace_back( new PARAM_ENUM<ZONE_FILL_MODE>( "defaults.zones.fill_mode",
1023
1024 m_params.emplace_back(
1025 new PARAM_SCALED<int>( "defaults.zones.hatch_thickness", &m_defaultZoneSettings.m_HatchThickness,
1026 std::max( pcbIUScale.mmToIU( ZONE_THICKNESS_MM ) * 4, pcbIUScale.mmToIU( 1.0 ) ),
1027 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1028
1029 m_params.emplace_back(
1030 new PARAM_SCALED<int>( "defaults.zones.hatch_gap", &m_defaultZoneSettings.m_HatchGap,
1031 std::max( pcbIUScale.mmToIU( ZONE_THICKNESS_MM ) * 6, pcbIUScale.mmToIU( 1.5 ) ),
1032 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1033
1034 m_params.emplace_back( new PARAM_LAMBDA<double>(
1035 "defaults.zones.hatch_orientation",
1036 [&]() -> double
1037 {
1038 return m_defaultZoneSettings.m_HatchOrientation.AsDegrees();
1039 },
1040 [&]( double aVal )
1041 {
1042 m_defaultZoneSettings.m_HatchOrientation = EDA_ANGLE( aVal, DEGREES_T );
1043 },
1044 0.0 ) );
1045
1046 m_params.emplace_back( new PARAM<int>( "defaults.zones.hatch_smoothing_level",
1047 &m_defaultZoneSettings.m_HatchSmoothingLevel, 0, 0, 3 ) );
1048
1049 m_params.emplace_back( new PARAM<double>( "defaults.zones.hatch_smoothing_value",
1050 &m_defaultZoneSettings.m_HatchSmoothingValue, 0.1, 0.0, 1.0 ) );
1051
1053 "defaults.zones.border_display_style", &m_defaultZoneSettings.m_ZoneBorderDisplayStyle,
1056
1057 m_params.emplace_back( new PARAM_SCALED<int>(
1058 "defaults.zones.border_hatch_pitch", &m_defaultZoneSettings.m_BorderHatchPitch,
1060 pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MAXDIST_MM ), pcbIUScale.MM_PER_IU ) );
1061
1062 m_params.emplace_back(
1063 new PARAM_SCALED<long>( "defaults.zones.thermal_relief_gap", &m_defaultZoneSettings.m_ThermalReliefGap,
1064 pcbIUScale.mmToIU( ZONE_THERMAL_RELIEF_GAP_MM ), pcbIUScale.mmToIU( 0.0 ),
1065 pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1066
1067 m_params.emplace_back( new PARAM_SCALED<long>(
1068 "defaults.zones.thermal_relief_spoke_width", &m_defaultZoneSettings.m_ThermalReliefSpokeWidth,
1070 pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1071
1072 m_params.emplace_back( new PARAM_LAMBDA<int>(
1073 "defaults.zones.pad_connection",
1074 [&]() -> int
1075 {
1076 return static_cast<int>( m_defaultZoneSettings.GetPadConnection() );
1077 },
1078 [&]( int aVal )
1079 {
1080 m_defaultZoneSettings.SetPadConnection( static_cast<ZONE_CONNECTION>( aVal ) );
1081 },
1082 static_cast<int>( ZONE_CONNECTION::THERMAL ) ) );
1083
1084 m_params.emplace_back( new PARAM_LAMBDA<int>(
1085 "defaults.zones.corner_smoothing",
1086 [&]() -> int
1087 {
1088 return static_cast<int>( m_defaultZoneSettings.GetCornerSmoothingType() );
1089 },
1090 [&]( int aVal )
1091 {
1092 m_defaultZoneSettings.SetCornerSmoothingType(
1093 magic_enum::enum_cast<ZONE_SETTINGS::CORNER_SMOOTHING>( aVal ).value_or(
1095 },
1096 static_cast<int>( ZONE_SETTINGS::CORNER_SMOOTHING::NO_SMOOTHING ) ) );
1097
1098 m_params.emplace_back( new PARAM_LAMBDA<double>(
1099 "defaults.zones.corner_radius",
1100 [&]() -> double
1101 {
1102 return pcbIUScale.IUTomm( m_defaultZoneSettings.GetCornerRadius() );
1103 },
1104 [&]( double aVal )
1105 {
1106 m_defaultZoneSettings.SetCornerRadius( pcbIUScale.mmToIU( aVal ) );
1107 },
1108 0.0 ) );
1109
1110 m_params.emplace_back( new PARAM_LAMBDA<int>(
1111 "defaults.zones.remove_islands",
1112 [&]() -> int
1113 {
1114 return static_cast<int>( m_defaultZoneSettings.GetIslandRemovalMode() );
1115 },
1116 [&]( int aVal )
1117 {
1118 m_defaultZoneSettings.SetIslandRemovalMode( static_cast<ISLAND_REMOVAL_MODE>( aVal ) );
1119 },
1120 static_cast<int>( ISLAND_REMOVAL_MODE::ALWAYS ) ) );
1121
1122 m_params.emplace_back( new PARAM_LAMBDA<double>(
1123 "defaults.zones.min_island_area",
1124 [&]() -> double
1125 {
1126 const double iuPerMm2 = pcbIUScale.IU_PER_MM * pcbIUScale.IU_PER_MM;
1127 return static_cast<double>( m_defaultZoneSettings.GetMinIslandArea() ) / iuPerMm2;
1128 },
1129 [&]( double aVal )
1130 {
1131 const double iuPerMm2 = pcbIUScale.IU_PER_MM * pcbIUScale.IU_PER_MM;
1132 m_defaultZoneSettings.SetMinIslandArea( static_cast<long long int>( aVal * iuPerMm2 ) );
1133 },
1134 10.0 ) );
1135
1136 m_params.emplace_back( new PARAM_SCALED<int>( "rules.max_error",
1138 pcbIUScale.mmToIU( 0.0001 ), pcbIUScale.mmToIU( 1.0 ), pcbIUScale.MM_PER_IU ) );
1139
1140 m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_mask_to_copper_clearance",
1142 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1143
1144 m_params.emplace_back( new PARAM<bool>( "zones_allow_external_fillets",
1145 &m_ZoneKeepExternalFillets, false ) );
1146
1147
1149
1150 registerMigration( 1, 2,
1151 [&]() -> bool
1152 {
1153 // Schema 1 to 2: move mask and paste margin settings back to board.
1154 // The parameters are removed, so we just have to manually load them here and
1155 // they will get saved with the board
1156 if( std::optional<double> optval = Get<double>( "rules.solder_mask_clearance" ) )
1157 m_SolderMaskExpansion = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
1158
1159 if( std::optional<double> optval = Get<double>( "rules.solder_mask_min_width" ) )
1160 m_SolderMaskMinWidth = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
1161
1162 if( std::optional<double> optval = Get<double>( "rules.solder_paste_clearance" ) )
1163 m_SolderPasteMargin = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
1164
1165 if( std::optional<double> optval = Get<double>( "rules.solder_paste_margin_ratio" ) )
1166 m_SolderPasteMarginRatio = *optval;
1167
1168 try
1169 {
1170 At( "rules" ).erase( "solder_mask_clearance" );
1171 At( "rules" ).erase( "solder_mask_min_width" );
1172 At( "rules" ).erase( "solder_paste_clearance" );
1173 At( "rules" ).erase( "solder_paste_margin_ratio" );
1174 }
1175 catch( ... )
1176 {}
1177
1178 return true;
1179 } );
1180
1182}
1183
1184
1186{
1187 if( m_parent )
1188 {
1189 m_parent->ReleaseNestedSettings( this );
1190 m_parent = nullptr;
1191 }
1192}
1193
1194
1195// Detached so a discarded copy cannot flush its values into the project file
1197 NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, nullptr, aOther.m_path )
1198{
1199 initFromOther( aOther );
1200}
1201
1202
1204{
1205 initFromOther( aOther );
1206 return *this;
1207}
1208
1209
1211{
1212 // Copy of NESTED_SETTINGS around is not allowed, so let's just update the params.
1222 m_MinConn = aOther.m_MinConn;
1239 m_MaxError = aOther.m_MaxError;
1252 m_CapVias = aOther.m_CapVias;
1253 m_FillVias = aOther.m_FillVias;
1256
1257 std::copy( std::begin( aOther.m_LineThickness ), std::end( aOther.m_LineThickness ),
1258 std::begin( m_LineThickness ) );
1259
1260 std::copy( std::begin( aOther.m_TextSize ), std::end( aOther.m_TextSize ),
1261 std::begin( m_TextSize ) );
1262
1263 std::copy( std::begin( aOther.m_TextThickness ), std::end( aOther.m_TextThickness ),
1264 std::begin( m_TextThickness ) );
1265
1266 std::copy( std::begin( aOther.m_TextItalic ), std::end( aOther.m_TextItalic ),
1267 std::begin( m_TextItalic ) );
1268
1269 std::copy( std::begin( aOther.m_TextUpright ), std::end( aOther.m_TextUpright ),
1270 std::begin( m_TextUpright ) );
1271
1280
1281 m_auxOrigin = aOther.m_auxOrigin;
1282 m_gridOrigin = aOther.m_gridOrigin;
1283 m_HasStackup = aOther.m_HasStackup;
1287 m_BomPresets = aOther.m_BomPresets;
1290
1305 m_stackup = aOther.m_stackup;
1308
1314}
1315
1316
1318{
1319 if( m_TrackWidthList != aOther.m_TrackWidthList ) return false;
1320 if( m_ViasDimensionsList != aOther.m_ViasDimensionsList ) return false;
1321 if( m_ViaStackPresets != aOther.m_ViaStackPresets )
1322 return false;
1323 if( m_DiffPairDimensionsList != aOther.m_DiffPairDimensionsList ) return false;
1324 if( m_CurrentViaType != aOther.m_CurrentViaType ) return false;
1325 if( m_UseConnectedTrackWidth != aOther.m_UseConnectedTrackWidth ) return false;
1326 if( m_TempOverrideTrackWidth != aOther.m_TempOverrideTrackWidth ) return false;
1327 if( m_MinClearance != aOther.m_MinClearance ) return false;
1328 if( m_MinGrooveWidth != aOther.m_MinGrooveWidth ) return false;
1329 if( m_MinConn != aOther.m_MinConn ) return false;
1330 if( m_TrackMinWidth != aOther.m_TrackMinWidth ) return false;
1331 if( m_ViasMinAnnularWidth != aOther.m_ViasMinAnnularWidth ) return false;
1332 if( m_ViasMinSize != aOther.m_ViasMinSize ) return false;
1333 if( m_MinThroughDrill != aOther.m_MinThroughDrill ) return false;
1335 return false;
1336 if( m_MicroViasMinDrill != aOther.m_MicroViasMinDrill ) return false;
1337 if( m_CopperEdgeClearance != aOther.m_CopperEdgeClearance ) return false;
1338 if( m_HoleClearance != aOther.m_HoleClearance ) return false;
1339 if( m_HoleToHoleMin != aOther.m_HoleToHoleMin ) return false;
1340 if( m_SilkClearance != aOther.m_SilkClearance ) return false;
1341 if( m_MinResolvedSpokes != aOther.m_MinResolvedSpokes ) return false;
1342 if( m_MinSilkTextHeight != aOther.m_MinSilkTextHeight ) return false;
1343 if( m_MinSilkTextThickness != aOther.m_MinSilkTextThickness ) return false;
1344 if( m_DRCSeverities != aOther.m_DRCSeverities ) return false;
1345 if( m_DrcExclusions != aOther.m_DrcExclusions ) return false;
1346 if( m_ZoneKeepExternalFillets != aOther.m_ZoneKeepExternalFillets ) return false;
1347 if( m_MaxError != aOther.m_MaxError ) return false;
1348 if( m_SolderMaskExpansion != aOther.m_SolderMaskExpansion ) return false;
1349 if( m_SolderMaskMinWidth != aOther.m_SolderMaskMinWidth ) return false;
1351 if( m_SolderPasteMargin != aOther.m_SolderPasteMargin ) return false;
1352 if( m_SolderPasteMarginRatio != aOther.m_SolderPasteMarginRatio ) return false;
1354 if( m_TentViasFront != aOther.m_TentViasFront ) return false;
1355 if( m_TentViasBack != aOther.m_TentViasBack ) return false;
1356 if( m_CoverViasFront != aOther.m_CoverViasFront ) return false;
1357 if( m_CoverViasBack != aOther.m_CoverViasBack ) return false;
1358 if( m_PlugViasFront != aOther.m_PlugViasFront ) return false;
1359 if( m_PlugViasBack != aOther.m_PlugViasBack ) return false;
1360 if( m_CapVias != aOther.m_CapVias ) return false;
1361 if( m_FillVias != aOther.m_FillVias ) return false;
1362 if( m_DefaultFPTextItems != aOther.m_DefaultFPTextItems ) return false;
1363 if( m_UserLayerNames != aOther.m_UserLayerNames ) return false;
1364
1365 if( !std::equal( std::begin( m_LineThickness ), std::end( m_LineThickness ),
1366 std::begin( aOther.m_LineThickness ) ) )
1367 return false;
1368
1369 if( !std::equal( std::begin( m_TextSize ), std::end( m_TextSize ),
1370 std::begin( aOther.m_TextSize ) ) )
1371 return false;
1372
1373 if( !std::equal( std::begin( m_TextThickness ), std::end( m_TextThickness ),
1374 std::begin( aOther.m_TextThickness ) ) )
1375 return false;
1376
1377 if( !std::equal( std::begin( m_TextItalic ), std::end( m_TextItalic ),
1378 std::begin( aOther.m_TextItalic ) ) )
1379 return false;
1380
1381 if( !std::equal( std::begin( m_TextUpright ), std::end( m_TextUpright ),
1382 std::begin( aOther.m_TextUpright ) ) )
1383 return false;
1384
1385 if( m_DimensionUnitsMode != aOther.m_DimensionUnitsMode ) return false;
1386 if( m_DimensionPrecision != aOther.m_DimensionPrecision ) return false;
1387 if( m_DimensionUnitsFormat != aOther.m_DimensionUnitsFormat ) return false;
1388 if( m_DimensionSuppressZeroes != aOther.m_DimensionSuppressZeroes ) return false;
1389 if( m_DimensionTextPosition != aOther.m_DimensionTextPosition ) return false;
1390 if( m_DimensionKeepTextAligned != aOther.m_DimensionKeepTextAligned ) return false;
1391 if( m_DimensionArrowLength != aOther.m_DimensionArrowLength ) return false;
1392 if( m_DimensionExtensionOffset != aOther.m_DimensionExtensionOffset ) return false;
1393 if( m_auxOrigin != aOther.m_auxOrigin ) return false;
1394 if( m_gridOrigin != aOther.m_gridOrigin ) return false;
1395 if( m_HasStackup != aOther.m_HasStackup ) return false;
1396 if( m_UseHeightForLengthCalcs != aOther.m_UseHeightForLengthCalcs ) return false;
1397 if( m_BomExportFileName != aOther.m_BomExportFileName ) return false;
1398 if( m_BomSettings != aOther.m_BomSettings ) return false;
1399 if( m_BomPresets != aOther.m_BomPresets ) return false;
1400 if( m_BomFmtSettings != aOther.m_BomFmtSettings ) return false;
1401 if( m_BomFmtPresets != aOther.m_BomFmtPresets ) return false;
1402 if( m_trackWidthIndex != aOther.m_trackWidthIndex ) return false;
1403 if( m_viaSizeIndex != aOther.m_viaSizeIndex ) return false;
1404 if( m_viaStackIndex != aOther.m_viaStackIndex )
1405 return false;
1406 if( m_diffPairIndex != aOther.m_diffPairIndex ) return false;
1407 if( m_useCustomTrackVia != aOther.m_useCustomTrackVia ) return false;
1408 if( m_customTrackWidth != aOther.m_customTrackWidth ) return false;
1409 if( m_customViaSize != aOther.m_customViaSize ) return false;
1410 if( m_useCustomDiffPair != aOther.m_useCustomDiffPair ) return false;
1411 if( m_customDiffPair != aOther.m_customDiffPair ) return false;
1412 if( m_copperLayerCount != aOther.m_copperLayerCount ) return false;
1413 if( m_userDefinedLayerCount != aOther.m_userDefinedLayerCount ) return false;
1414 if( m_enabledLayers != aOther.m_enabledLayers ) return false;
1415 if( m_boardThickness != aOther.m_boardThickness ) return false;
1416 if( m_currentNetClassName != aOther.m_currentNetClassName ) return false;
1417 if( m_stackup != aOther.m_stackup ) return false;
1418 if( *m_NetSettings != *aOther.m_NetSettings ) return false;
1419 if( m_defaultZoneSettings != aOther.m_defaultZoneSettings ) return false;
1420
1421 if( m_StyleFPFields != aOther.m_StyleFPFields ) return false;
1422 if( m_StyleFPText != aOther.m_StyleFPText ) return false;
1423 if( m_StyleFPShapes != aOther.m_StyleFPShapes ) return false;
1424 if( m_StyleFPDimensions != aOther.m_StyleFPDimensions ) return false;
1425 if( m_StyleFPBarcodes != aOther.m_StyleFPBarcodes ) return false;
1426
1427 return true;
1428}
1429
1430
1432{
1450 std::string units_ptr( "defaults.dimension_units" );
1451 std::string precision_ptr( "defaults.dimension_precision" );
1452
1453 if( !( Contains( units_ptr )
1454 && Contains( precision_ptr )
1455 && At( units_ptr ).is_number_integer()
1456 && At( precision_ptr ).is_number_integer() ) )
1457 {
1458 // if either is missing or invalid, migration doesn't make sense
1459 return true;
1460 }
1461
1462 int units = *Get<int>( units_ptr );
1463 int precision = *Get<int>( precision_ptr );
1464
1465 // The enum maps directly to precision if the units is mils
1466 int extraDigits = 0;
1467
1468 switch( units )
1469 {
1470 case 0: extraDigits = 3; break;
1471 case 2: extraDigits = 2; break;
1472 default: break;
1473 }
1474
1475 precision += extraDigits;
1476
1477 Set( precision_ptr, precision );
1478
1479 return true;
1480}
1481
1482
1484{
1485 // Schema 2 to 3: convert DRC exclusions from legacy pipe-delimited strings to ProtoJSON
1486 std::optional<nlohmann::json> opt = Get<nlohmann::json>( "drc_exclusions" );
1487
1488 if( !opt )
1489 return true;
1490
1491 nlohmann::json migrated = nlohmann::json::array();
1492
1493 for( const nlohmann::json& entry : *opt )
1494 {
1495 if( entry.is_object() )
1496 {
1497 migrated.push_back( entry );
1498 }
1499 else if( entry.is_array() && entry.size() > 0 )
1500 {
1501 wxString markerData = entry[0].get<wxString>();
1502 wxString comment = entry.size() > 1 ? entry[1].get<wxString>() : wxString();
1503
1504 DRC_EXCLUSION ex = DRC_EXCLUSION::FromLegacyStrings( markerData, comment );
1505
1506 if( !ex.GetSortKey().empty() )
1507 migrated.push_back( ex );
1508 }
1509 else if( entry.is_string() )
1510 {
1511 DRC_EXCLUSION ex = DRC_EXCLUSION::FromLegacyStrings( entry.get<wxString>(), wxString() );
1512
1513 if( !ex.GetSortKey().empty() )
1514 migrated.push_back( ex );
1515 }
1516 }
1517
1518 Set( "drc_exclusions", migrated );
1519
1520 return true;
1521}
1522
1523
1524bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
1525{
1526 bool ret = NESTED_SETTINGS::LoadFromFile( aDirectory );
1527
1528 // A number of things won't have been translated by the PROJECT_FILE migration because of
1529 // descoped objects required to decode this data. So, it will be in the legacy.pcbnew
1530 // section and needs to be pulled out here
1531
1532 PROJECT_FILE* project = dynamic_cast<PROJECT_FILE*>( GetParent() );
1533
1534 if( !project )
1535 return ret;
1536
1537 bool migrated = false;
1538
1539 auto drcName =
1540 []( int aCode ) -> std::string
1541 {
1542 return std::string( DRC_ITEM::Create( aCode )->GetSettingsKey().ToUTF8() );
1543 };
1544
1545 const std::string rs = "rule_severities.";
1546 const std::string no_courtyard_key = "legacy_no_courtyard_defined";
1547 const std::string courtyard_overlap_key = "legacy_courtyards_overlap";
1548
1549 try
1550 {
1551 nlohmann::json& severities =
1552 project->Internals()->at( "/board/design_settings/rule_severities"_json_pointer );
1553
1554 if( severities.contains( no_courtyard_key ) )
1555 {
1556 if( severities[no_courtyard_key].get<bool>() )
1557 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "error" );
1558 else
1559 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "ignore" );
1560
1561 severities.erase( no_courtyard_key );
1562 migrated = true;
1563 }
1564
1565 if( severities.contains( courtyard_overlap_key ) )
1566 {
1567 if( severities[courtyard_overlap_key].get<bool>() )
1568 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "error" );
1569 else
1570 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "ignore" );
1571
1572 severities.erase( courtyard_overlap_key );
1573 migrated = true;
1574 }
1575 }
1576 catch( ... )
1577 {
1578 }
1579
1580 if( Contains( "legacy" ) )
1581 {
1582 // This defaults to false for new boards, but version 5.1.x and prior kept the fillets
1583 // so we do the same for legacy boards.
1585
1586 project->At( "legacy" ).erase( "pcbnew" );
1587 }
1588
1589 // Now that we have everything, we need to load again
1590 if( migrated )
1591 Load();
1592
1593 return ret;
1594}
1595
1596
1598{
1599 auto it = m_DRCSeverities.find( aDRCErrorCode );
1600
1601 // If not found, return the default severity for unrecognized error codes.
1602 // As constructed, the default severity for unrecognized error codes is RPT_SEVERITY_ERROR.
1603 wxCHECK_MSG( it != m_DRCSeverities.end(), RPT_SEVERITY_ERROR,
1604 wxString::Format( wxT( "DRC error code %d not found" ), aDRCErrorCode ) );
1605
1606 return it->second;
1607}
1608
1609
1610bool BOARD_DESIGN_SETTINGS::Ignore( int aDRCErrorCode ) const
1611{
1612 return GetSeverity( aDRCErrorCode ) == RPT_SEVERITY_IGNORE;
1613}
1614
1615
1616std::vector<BOARD_DESIGN_SETTINGS::VALIDATION_ERROR>
1617BOARD_DESIGN_SETTINGS::ValidateDesignRules( std::optional<EDA_UNITS> aUnits ) const
1618{
1619 std::vector<VALIDATION_ERROR> errors;
1620 EDA_UNITS units = aUnits.value_or( EDA_UNITS::MM );
1621
1622 auto addRangeError =
1623 [&]( const wxString& aField, int aValue, int aMin, int aMax )
1624 {
1625 if( aValue < aMin || aValue > aMax )
1626 {
1627 wxString minValue = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units,
1628 aMin, true );
1629 wxString maxValue = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units,
1630 aMax, true );
1631
1632 errors.push_back( {
1633 aField,
1634 wxString::Format( _( "Value must be between %s and %s." ),
1635 minValue, maxValue )
1636 } );
1637 }
1638 };
1639
1640 auto addRatioRangeError =
1641 [&]( const wxString& aField, double aValue, double aMin, double aMax )
1642 {
1643 if( !std::isfinite( aValue ) || aValue < aMin || aValue > aMax )
1644 {
1645 errors.push_back( {
1646 aField,
1647 wxString::Format( _( "Value must be between %.3f and %.3f." ),
1648 aMin, aMax )
1649 } );
1650 }
1651 };
1652
1653 addRangeError( wxS( "min_clearance" ), m_MinClearance,
1654 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1655 addRangeError( wxS( "min_connection" ), m_MinConn,
1656 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ) );
1657 addRangeError( wxS( "min_track_width" ), m_TrackMinWidth,
1658 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1659 addRangeError( wxS( "min_via_annular_width" ), m_ViasMinAnnularWidth,
1660 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1661 addRangeError( wxS( "min_via_diameter" ), m_ViasMinSize,
1662 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1663 addRangeError( wxS( "min_through_hole_diameter" ), m_MinThroughDrill,
1664 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1665 addRangeError( wxS( "min_microvia_diameter" ), m_MicroViasMinSize,
1666 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ) );
1667 addRangeError( wxS( "min_microvia_drill" ), m_MicroViasMinDrill,
1668 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ) );
1669 addRangeError( wxS( "min_hole_to_hole" ), m_HoleToHoleMin,
1670 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ) );
1671 addRangeError( wxS( "min_hole_clearance" ), m_HoleClearance,
1672 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ) );
1673 addRangeError( wxS( "min_silk_clearance" ), m_SilkClearance,
1674 pcbIUScale.mmToIU( -10.0 ), pcbIUScale.mmToIU( 100.0 ) );
1675 addRangeError( wxS( "min_groove_width" ), m_MinGrooveWidth,
1676 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1677 addRangeError( wxS( "min_text_height" ), m_MinSilkTextHeight,
1678 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ) );
1679 addRangeError( wxS( "min_text_thickness" ), m_MinSilkTextThickness,
1680 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1681 addRangeError( wxS( "min_copper_edge_clearance" ), m_CopperEdgeClearance,
1682 pcbIUScale.mmToIU( -0.01 ), pcbIUScale.mmToIU( 25.0 ) );
1683
1685 {
1686 errors.push_back( {
1687 wxS( "min_resolved_spokes" ),
1688 _( "Value must be between 0 and 99." )
1689 } );
1690 }
1691
1692 addRangeError( wxS( "max_error" ), m_MaxError,
1695
1696 addRangeError( wxS( "solder_mask_expansion" ), m_SolderMaskExpansion,
1697 pcbIUScale.mmToIU( -25.0 ), pcbIUScale.mmToIU( 25.0 ) );
1698 addRangeError( wxS( "solder_mask_min_width" ), m_SolderMaskMinWidth,
1699 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ) );
1700 addRangeError( wxS( "solder_mask_to_copper_clearance" ), m_SolderMaskToCopperClearance,
1701 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ) );
1702 addRangeError( wxS( "solder_paste_margin" ), m_SolderPasteMargin,
1703 pcbIUScale.mmToIU( -25.0 ), pcbIUScale.mmToIU( 25.0 ) );
1704 addRatioRangeError( wxS( "solder_paste_margin_ratio" ), m_SolderPasteMarginRatio,
1705 -1.0, 1.0 );
1706
1707 TEARDROP_PARAMETERS_LIST& teardropParamsList =
1709
1710 for( size_t ii = 0; ii < teardropParamsList.GetParametersCount(); ++ii )
1711 {
1712 const TEARDROP_PARAMETERS* params = teardropParamsList.GetParameters( static_cast<TARGET_TD>( ii ) );
1713 std::string target = GetTeardropTargetCanonicalName( static_cast<TARGET_TD>( ii ) );
1714
1715 if( params->m_TdMaxLen < 0 )
1716 {
1717 errors.push_back( {
1718 wxString::Format( wxS( "teardrop_parameters[%s].max_length" ), target ),
1719 _( "Value must be greater than or equal to 0." )
1720 } );
1721 }
1722
1723 if( params->m_TdMaxWidth < 0 )
1724 {
1725 errors.push_back( {
1726 wxString::Format( wxS( "teardrop_parameters[%s].max_width" ), target ),
1727 _( "Value must be greater than or equal to 0." )
1728 } );
1729 }
1730
1731 addRatioRangeError( wxString::Format( wxS( "teardrop_parameters[%s].best_length_ratio" ), target ),
1732 params->m_BestLengthRatio, 0.0, 1.0 );
1733 addRatioRangeError( wxString::Format( wxS( "teardrop_parameters[%s].best_width_ratio" ), target ),
1734 params->m_BestWidthRatio, 0.0, 1.0 );
1735 addRatioRangeError( wxString::Format( wxS( "teardrop_parameters[%s].width_to_size_filter_ratio" ),
1736 target ),
1737 params->m_WidthtoSizeFilterRatio, 0.0, 1.0 );
1738 }
1739
1740 for( size_t ii = 1; ii < m_DiffPairDimensionsList.size(); ++ii )
1741 {
1742 const DIFF_PAIR_DIMENSION& diffPair = m_DiffPairDimensionsList[ii];
1743
1744 if( diffPair.m_Width > 0 && diffPair.m_Gap <= 0 )
1745 {
1746 errors.push_back( {
1747 wxString::Format( wxS( "diff_pair_dimensions_list[%zu].gap" ), ii ),
1748 _( "No differential pair gap defined." )
1749 } );
1750 }
1751 }
1752
1753 for( size_t ii = 1; ii < m_ViasDimensionsList.size(); ++ii )
1754 {
1755 const VIA_DIMENSION& viaDim = m_ViasDimensionsList[ii];
1756
1757 std::optional<int> viaDiameter;
1758 std::optional<int> viaDrill;
1759
1760 if( viaDim.m_Diameter > 0 )
1761 viaDiameter = viaDim.m_Diameter;
1762
1763 if( viaDim.m_Drill > 0 )
1764 viaDrill = viaDim.m_Drill;
1765
1766 if( std::optional<PCB_VIA::VIA_PARAMETER_ERROR> error =
1767 PCB_VIA::ValidateViaParameters( viaDiameter, viaDrill ) )
1768 {
1769 errors.push_back( {
1770 wxString::Format( wxS( "via_dimensions_list[%zu]" ), ii ),
1771 error->m_Message
1772 } );
1773 }
1774 }
1775
1776 return errors;
1777}
1778
1779
1780std::vector<BOARD_DESIGN_SETTINGS::VALIDATION_ERROR>
1781BOARD_DESIGN_SETTINGS::GetDesignRuleWarnings( std::optional<EDA_UNITS> aUnits ) const
1782{
1783 std::vector<VALIDATION_ERROR> warnings;
1784 EDA_UNITS units = aUnits.value_or( EDA_UNITS::MM );
1785
1786 auto str =
1787 [&]( int aValue )
1788 {
1789 return EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, aValue, true );
1790 };
1791
1792 // Microvias are excluded because their default drill plus annulus already exceeds their default diameter
1793 int impliedViaMin = m_MinThroughDrill + 2 * m_ViasMinAnnularWidth;
1794
1795 if( m_ViasMinSize < impliedViaMin )
1796 {
1797 warnings.push_back( {
1798 wxS( "min_via_diameter" ),
1799 wxString::Format( _( "Minimum via diameter (%s) is smaller than the minimum drill size (%s) "
1800 "plus twice the minimum annular width (%s), so it has no effect. "
1801 "The effective minimum via diameter is %s." ),
1802 str( m_ViasMinSize ), str( m_MinThroughDrill ),
1803 str( m_ViasMinAnnularWidth ), str( impliedViaMin ) )
1804 } );
1805 }
1806
1807 return warnings;
1808}
1809
1810
1812{
1813 int biggest = std::max( m_MinClearance, m_HoleClearance );
1814 DRC_CONSTRAINT constraint;
1815
1816 biggest = std::max( biggest, m_HoleToHoleMin );
1817 biggest = std::max( biggest, m_CopperEdgeClearance );
1818
1819 if( m_DRCEngine )
1820 {
1821 m_DRCEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, constraint );
1822 biggest = std::max( biggest, constraint.Value().Min() );
1823
1824 m_DRCEngine->QueryWorstConstraint( PHYSICAL_CLEARANCE_CONSTRAINT, constraint );
1825 biggest = std::max( biggest, constraint.Value().Min() );
1826
1827 m_DRCEngine->QueryWorstConstraint( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, constraint );
1828 biggest = std::max( biggest, constraint.Value().Min() );
1829
1830 m_DRCEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, constraint );
1831 biggest = std::max( biggest, constraint.Value().Min() );
1832
1833 m_DRCEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, constraint );
1834 biggest = std::max( biggest, constraint.Value().Min() );
1835
1836 m_DRCEngine->QueryWorstConstraint( HOLE_TO_HOLE_CONSTRAINT, constraint );
1837 biggest = std::max( biggest, constraint.Value().Min() );
1838 }
1839
1840 // Clip to avoid integer overflows in subsequent calculations
1841 return std::min( biggest, MAXIMUM_CLEARANCE );
1842}
1843
1844
1846{
1847 int clearance = m_NetSettings->GetDefaultNetclass()->GetClearance();
1848
1849 for( const auto& [name, netclass] : m_NetSettings->GetNetclasses() )
1850 {
1851 if( netclass->HasClearance() )
1852 clearance = std::min( clearance, netclass->GetClearance() );
1853 }
1854
1855 return clearance;
1856}
1857
1858
1859// Compute the next index when cycling a predefined-size list whose index 0 is the synthetic
1860// "use netclass" placeholder. Roll-over skips that placeholder when real sizes exist so the
1861// cycle stays monotonic.
1862static int nextPredefinedIndex( int aIndex, bool aForward, int aListSize )
1863{
1864 // Nothing to cycle when the list holds only the netclass placeholder (or is empty).
1865 if( aListSize <= 1 )
1866 return 0;
1867
1868 constexpr int lowestRealIndex = 1;
1869 int next = aIndex + ( aForward ? 1 : -1 );
1870
1871 if( next >= aListSize )
1872 next = lowestRealIndex;
1873 else if( next < lowestRealIndex )
1874 next = aListSize - 1;
1875
1876 return next;
1877}
1878
1879
1881{
1883 ? 0
1884 : std::clamp( aIndex, 0, (int) m_ViasDimensionsList.size() - 1 );
1885 m_useCustomTrackVia = false;
1886}
1887
1888
1889int BOARD_DESIGN_SETTINGS::GetNextViaSizeIndex( int aIndex, bool aForward ) const
1890{
1891 return nextPredefinedIndex( aIndex, aForward, (int) m_ViasDimensionsList.size() );
1892}
1893
1894
1896{
1898 return m_customViaSize.m_Diameter;
1900 return m_NetSettings->GetDefaultNetclass()->GetViaDiameter();
1901 else
1902 return m_ViasDimensionsList[ m_viaSizeIndex ].m_Diameter;
1903}
1904
1905
1907{
1908 int drill;
1909
1911 drill = m_customViaSize.m_Drill;
1913 drill = m_NetSettings->GetDefaultNetclass()->GetViaDrill();
1914 else
1915 drill = m_ViasDimensionsList[ m_viaSizeIndex ].m_Drill;
1916
1917 return drill > 0 ? drill : -1;
1918}
1919
1920
1922{
1924 ? 0
1925 : std::clamp( aIndex, 0, (int) m_TrackWidthList.size() - 1 );
1926 m_useCustomTrackVia = false;
1927}
1928
1929
1930int BOARD_DESIGN_SETTINGS::GetNextTrackWidthIndex( int aIndex, bool aForward ) const
1931{
1932 return nextPredefinedIndex( aIndex, aForward, (int) m_TrackWidthList.size() );
1933}
1934
1935
1937{
1939 return m_customTrackWidth;
1941 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1942 else
1944}
1945
1946
1948{
1950 ? 0
1951 : std::clamp( aIndex, 0, (int) m_DiffPairDimensionsList.size() - 1 );
1952 m_useCustomDiffPair = false;
1953}
1954
1955
1956int BOARD_DESIGN_SETTINGS::GetNextDiffPairIndex( int aIndex, bool aForward ) const
1957{
1958 return nextPredefinedIndex( aIndex, aForward, (int) m_DiffPairDimensionsList.size() );
1959}
1960
1961
1963{
1965 {
1966 return m_customDiffPair.m_Width;
1967 }
1969 {
1970 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairWidth() )
1971 return m_NetSettings->GetDefaultNetclass()->GetDiffPairWidth();
1972 else
1973 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1974 }
1975 else
1976 {
1978 }
1979}
1980
1981
1983{
1985 {
1986 return m_customDiffPair.m_Gap;
1987 }
1989 {
1990 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairGap() )
1991 return m_NetSettings->GetDefaultNetclass()->GetDiffPairGap();
1992 else
1993 return m_NetSettings->GetDefaultNetclass()->GetClearance();
1994 }
1995 else
1996 {
1998 }
1999}
2000
2001
2003{
2005 {
2006 return m_customDiffPair.m_ViaGap;
2007 }
2009 {
2010 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairViaGap() )
2011 return m_NetSettings->GetDefaultNetclass()->GetDiffPairViaGap();
2012 else
2013 return GetCurrentDiffPairGap();
2014 }
2015 else
2016 {
2018 }
2019}
2020
2021
2023{
2024 m_copperLayerCount = aNewLayerCount;
2025
2026 // Update only enabled copper layers mask
2027 m_enabledLayers.ClearCopperLayers();
2028
2029 if( aNewLayerCount > 0 )
2030 m_enabledLayers |= LSET::AllCuMask( aNewLayerCount );
2031}
2032
2033
2035{
2036 m_userDefinedLayerCount = aNewLayerCount;
2037
2038 m_enabledLayers.ClearUserDefinedLayers();
2039
2040 if( aNewLayerCount > 0 )
2041 m_enabledLayers |= LSET::UserDefinedLayersMask( aNewLayerCount );
2042}
2043
2044
2046{
2047 m_enabledLayers = aMask;
2048
2049 // Ensures mandatory back and front layers are always enabled regardless of board file
2050 // configuration.
2051 m_enabledLayers.set( B_Cu ).set( F_Cu )
2052 .set( B_CrtYd ).set( F_CrtYd )
2053 .set( Edge_Cuts )
2054 .set( Margin );
2055
2056 // update layer counts to ensure their consistency with m_EnabledLayers
2057 LSET copperLayers = aMask;
2058 copperLayers.ClearNonCopperLayers();
2059
2060 LSET userLayers = aMask & LSET::UserDefinedLayersMask();
2061
2062 m_copperLayerCount = (int) copperLayers.count();
2063 m_userDefinedLayerCount = (int) userLayers.count();
2064}
2065
2066
2067// Return the layer class index { silk, copper, edges & courtyards, fab, others } of the
2068// given layer.
2070{
2071 if( aLayer == F_SilkS || aLayer == B_SilkS )
2072 return LAYER_CLASS_SILK;
2073 else if( IsCopperLayer( aLayer ) )
2074 return LAYER_CLASS_COPPER;
2075 else if( aLayer == Edge_Cuts )
2076 return LAYER_CLASS_EDGES;
2077 else if( aLayer == F_CrtYd || aLayer == B_CrtYd )
2078 return LAYER_CLASS_COURTYARD;
2079 else if( aLayer == F_Fab || aLayer == B_Fab )
2080 return LAYER_CLASS_FAB;
2081 else
2082 return LAYER_CLASS_OTHERS;
2083}
2084
2085
2087{
2088 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
2089}
2090
2091
2093{
2094 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
2095}
2096
2097
2099{
2100 return m_LineThickness[ GetLayerClass( aLayer ) ];
2101}
2102
2103
2105{
2106 return m_TextSize[ GetLayerClass( aLayer ) ];
2107}
2108
2109
2111{
2112 return m_TextThickness[ GetLayerClass( aLayer ) ];
2113}
2114
2115
2117{
2118 return m_TextItalic[ GetLayerClass( aLayer ) ];
2119}
2120
2121
2123{
2124 return m_TextUpright[ GetLayerClass( aLayer ) ];
2125}
const char * name
constexpr int ARC_HIGH_DEF
Definition base_units.h:144
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
const int bdsSchemaVersion
static int nextPredefinedIndex(int aIndex, bool aForward, int aListSize)
@ LAYER_CLASS_OTHERS
@ LAYER_CLASS_FAB
@ LAYER_CLASS_COURTYARD
@ LAYER_CLASS_SILK
@ LAYER_CLASS_COPPER
@ LAYER_CLASS_EDGES
#define DEFAULT_MICROVIASMINDRILL
#define DEFAULT_SOLDERPASTE_CLEARANCE
#define DEFAULT_SOLDERPASTE_RATIO
#define DEFAULT_CUSTOMDPAIRWIDTH
#define DEFAULT_DP_MEANDER_SPACING
#define DEFAULT_VIASMINSIZE
#define DEFAULT_TEXT_WIDTH
#define DEFAULT_COPPER_TEXT_WIDTH
#define DEFAULT_CUSTOMDPAIRGAP
#define DEFAULT_MINCLEARANCE
#define MAXIMUM_ERROR_SIZE_MM
#define DEFAULT_HOLECLEARANCE
#define DEFAULT_SOLDERMASK_EXPANSION
#define DEFAULT_SOLDERMASK_MIN_WIDTH
#define MINIMUM_ERROR_SIZE_MM
#define DEFAULT_DIMENSION_EXTENSION_OFFSET
#define DEFAULT_COPPEREDGECLEARANCE
#define DEFAULT_DIMENSION_ARROW_LENGTH
#define DEFAULT_TRACKMINWIDTH
#define DEFAULT_MINTHROUGHDRILL
#define DEFAULT_SILK_TEXT_SIZE
#define MAXIMUM_CLEARANCE
#define DEFAULT_HOLETOHOLEMIN
#define MAX_MICROVIA_STACK_PITCH_MM
#define DEFAULT_MINCONNECTION
#define DEFAULT_COPPER_LINE_WIDTH
#define DEFAULT_SILK_LINE_WIDTH
#define DEFAULT_SILKCLEARANCE
#define DEFAULT_MICROVIASMINSIZE
#define DEFAULT_SILK_TEXT_WIDTH
#define DEFAULT_MINGROOVEWIDTH
#define DEFAULT_EDGE_WIDTH
#define DEFAULT_CUSTOMTRACKWIDTH
#define DEFAULT_CUSTOMDPAIRVIAGAP
#define DEFAULT_COPPER_TEXT_SIZE
#define DEFAULT_SOLDERMASK_TO_COPPER_CLEARANCE
#define DEFAULT_LINE_WIDTH
#define DEFAULT_MEANDER_SPACING
#define DEFAULT_COURTYARD_WIDTH
#define DEFAULT_BOARD_THICKNESS_MM
#define DEFAULT_MINRESOLVEDSPOKES
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
BASE_SET & set(size_t pos)
Definition base_set.h:126
DIM_PRECISION m_DimensionPrecision
Number of digits after the decimal.
std::vector< TEXT_ITEM_INFO > m_DefaultFPTextItems
std::vector< VALIDATION_ERROR > GetDesignRuleWarnings(std::optional< EDA_UNITS > aUnits=std::nullopt) const
Find design rule values that are legal but have no effect because other rules imply a stricter limit.
int GetHolePlatingThickness() const
Pad & via drills are finish size.
VIATYPE m_CurrentViaType
(VIA_BLIND_BURIED, VIA_THROUGH, VIA_MICROVIA)
void SetEnabledLayers(const LSET &aMask)
Change the bit-mask of enabled layers to aMask.
std::shared_ptr< NET_SETTINGS > m_NetSettings
bool Ignore(int aDRCErrorCode) const
Return true if the DRC error code's severity is RPT_SEVERITY_ERROR.
bool operator==(const BOARD_DESIGN_SETTINGS &aOther) const
DIM_UNITS_FORMAT m_DimensionUnitsFormat
void initFromOther(const BOARD_DESIGN_SETTINGS &aOther)
bool GetTextUpright(PCB_LAYER_ID aLayer) const
std::map< int, SEVERITY > m_DRCSeverities
VECTOR2I m_gridOrigin
origin for grid offsets
int GetTextThickness(PCB_LAYER_ID aLayer) const
Return the default text thickness from the layer class for the given layer.
VECTOR2I m_auxOrigin
origin for plot exports
bool m_TextUpright[LAYER_CLASS_COUNT]
BOARD_DESIGN_SETTINGS(JSON_SETTINGS *aParent, const std::string &aPath)
bool GetTextItalic(PCB_LAYER_ID aLayer) const
int GetNextDiffPairIndex(int aIndex, bool aForward) const
Compute the next diff pair dimensions list index when cycling predefined sizes, skipping the index-0 ...
wxString m_currentNetClassName
Current net class name used to display netclass info.
void SetViaSizeIndex(int aIndex)
Set the current via size list index to aIndex.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
std::map< std::string, wxString > m_UserLayerNames
SEVERITY GetSeverity(int aDRCErrorCode) const
Return the severity of a given DRC error code.
int GetNextTrackWidthIndex(int aIndex, bool aForward) const
Compute the next track width list index when cycling predefined sizes, skipping the index-0 netclass ...
TEARDROP_PARAMETERS_LIST m_TeardropParamsList
The parameters of teardrops for the different teardrop targets (via/pad, track end).
void SetUserDefinedLayerCount(int aNewLayerCount)
Set the number of user defined layers to aNewLayerCount.
int GetDRCEpsilon() const
Return an epsilon which accounts for rounding errors, etc.
int GetLayerClass(PCB_LAYER_ID aLayer) const
PNS::MEANDER_SETTINGS m_DiffPairMeanderSettings
int m_boardThickness
Board thickness for 3D viewer.
int m_copperLayerCount
Number of copper layers for this design.
int m_userDefinedLayerCount
Number of user defined layers for this design.
bool LoadFromFile(const wxString &aDirectory="") override
Loads the backing file from disk and then calls Load()
PNS::MEANDER_SETTINGS m_SingleTrackMeanderSettings
void SetTrackWidthIndex(int aIndex)
Set the current track width list index to aIndex.
int m_TextThickness[LAYER_CLASS_COUNT]
ZONE_SETTINGS m_defaultZoneSettings
The default settings that will be used for new zones.
int GetNextViaSizeIndex(int aIndex, bool aForward) const
Compute the next via size list index when cycling predefined sizes, skipping the index-0 netclass pla...
std::vector< int > m_TrackWidthList
DIFF_PAIR_DIMENSION m_customDiffPair
std::vector< VALIDATION_ERROR > ValidateDesignRules(std::optional< EDA_UNITS > aUnits=std::nullopt) const
Validate design settings values and return per-field errors.
int m_LineThickness[LAYER_CLASS_COUNT]
VECTOR2I GetTextSize(PCB_LAYER_ID aLayer) const
Return the default text size from the layer class for the given layer.
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
bool m_UseHeightForLengthCalcs
Enable inclusion of stackup height in track length measurements and length tuning.
VECTOR2I m_TextSize[LAYER_CLASS_COUNT]
PNS::MEANDER_SETTINGS m_SkewMeanderSettings
LSET m_enabledLayers
Bit-mask for layer enabling.
bool m_TextItalic[LAYER_CLASS_COUNT]
std::vector< VIA_STACK_PRESET > m_ViaStackPresets
void SetCopperLayerCount(int aNewLayerCount)
Set the copper layer count to aNewLayerCount.
DIM_TEXT_POSITION m_DimensionTextPosition
BOARD_STACKUP m_stackup
The description of layers stackup, for board fabrication only physical layers are in layers stackup.
std::vector< VIA_DIMENSION > m_ViasDimensionsList
BOARD_DESIGN_SETTINGS & operator=(const BOARD_DESIGN_SETTINGS &aOther)
std::set< DRC_EXCLUSION, DRC_EXCLUSION_COMPARE > m_DrcExclusions
MINOPTMAX< int > & Value()
Definition drc_rule.h:130
Container for an DRC exclusion, which is a PCB_MARKER plus an optional comment.
static DRC_EXCLUSION FromLegacyStrings(const wxString &aMarkerData, const wxString &aComment)
std::string GetSortKey() const
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition drc_item.h:172
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition drc_item.cpp:492
void Set(const std::string &aPath, ValueType aVal)
Stores a value into the JSON document Will throw an exception if ValueType isn't something that the l...
bool Contains(const std::string &aPath) const
virtual void Load()
Updates the parameters of this object based on the current JSON document contents.
std::optional< ValueType > Get(const std::string &aPath) const
Fetches a value from within the JSON document.
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
void registerMigration(int aOldSchemaVersion, int aNewSchemaVersion, std::function< bool(void)> aMigrator)
Registers a migration from one schema version to another.
nlohmann::json & At(const std::string &aPath)
Wrappers for the underlying JSON API so that most consumers don't need json.hpp All of these function...
JSON_SETTINGS(const wxString &aFilename, SETTINGS_LOC aLocation, int aSchemaVersion)
bool m_resetParamsIfMissing
Whether or not to set parameters to their default value if missing from JSON on Load()
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:604
LSET & ClearNonCopperLayers()
Clear the non-copper layers in this set.
Definition lset.cpp:949
static int NameToLayer(wxString &aName)
Return the layer number from a layer name.
Definition lset.cpp:113
static LSET UserDefinedLayersMask(int aUserDefinedLayerCount=MAX_USER_DEFINED_LAYERS)
Return a mask with the requested number of user defined layers.
Definition lset.cpp:700
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition lset.cpp:184
T Min() const
Definition minoptmax.h:29
std::string m_path
The path (in pointer format) of where to store this document in the parent.
JSON_SETTINGS * GetParent()
JSON_SETTINGS * m_parent
A pointer to the parent object to load and store from.
NESTED_SETTINGS(const std::string &aName, int aSchemaVersion, JSON_SETTINGS *aParent, const std::string &aPath, bool aLoadFromFile=true)
bool LoadFromFile(const wxString &aDirectory="") override
Loads the JSON document from the parent and then calls Load()
Stores an enum as an integer.
Definition parameters.h:232
Like a normal param, but with custom getter and setter functions.
Definition parameters.h:299
Represents a parameter that has a scaling factor between the value in the file and the value used int...
Definition parameters.h:410
static std::optional< VIA_PARAMETER_ERROR > ValidateViaParameters(std::optional< int > aDiameter, std::optional< int > aPrimaryDrill, std::optional< PCB_LAYER_ID > aPrimaryStartLayer=std::nullopt, std::optional< PCB_LAYER_ID > aPrimaryEndLayer=std::nullopt, std::optional< int > aSecondaryDrill=std::nullopt, std::optional< PCB_LAYER_ID > aSecondaryStartLayer=std::nullopt, std::optional< PCB_LAYER_ID > aSecondaryEndLayer=std::nullopt, std::optional< int > aTertiaryDrill=std::nullopt, std::optional< PCB_LAYER_ID > aTertiaryStartLayer=std::nullopt, std::optional< PCB_LAYER_ID > aTertiaryEndLayer=std::nullopt, int aCopperLayerCount=0)
Dimensions for the meandering algorithm.
Definition pns_meander.h:70
int m_minAmplitude
Minimum meandering amplitude.
int m_cornerRadiusPercentage
Rounding percentage (0 - 100).
bool m_singleSided
Place meanders on one side.
MEANDER_STYLE m_cornerStyle
Type of corners for the meandered line.
int m_maxAmplitude
Maximum meandering amplitude.
int m_spacing
Meandering period/spacing (see dialog picture for explanation).
The backing store for a PROJECT, in JSON format.
A holder for a rule check item, DRC in Pcbnew or ERC in Eeschema.
Definition rc_item.h:138
TEARDROP_PARAMETERS_LIST is a helper class to handle the list of TEARDROP_PARAMETERS needed to build ...
TEARDROP_PARAMETERS * GetParameters(TARGET_TD aTdType)
TEARDROP_PARAMETARS is a helper class to handle parameters needed to build teardrops for a board thes...
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_Enabled
Flag to enable teardrops.
bool m_CurvedEdges
True if the teardrop should be curved.
#define DEFAULT_TEXT_SIZE
The default text size in mils. (can be changed in preference menu)
@ EDGE_CLEARANCE_CONSTRAINT
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
@ CLEARANCE_CONSTRAINT
@ HOLE_CLEARANCE_CONSTRAINT
@ PHYSICAL_CLEARANCE_CONSTRAINT
@ HOLE_TO_HOLE_CONSTRAINT
@ DRCE_FOOTPRINT_SCALED_WITH_PADS
Definition drc_item.h:100
@ DRCE_TUNING_PROFILE_IMPLICIT_RULES
Definition drc_item.h:131
@ DRCE_SILK_EDGE_CLEARANCE
Definition drc_item.h:113
@ DRCE_FOOTPRINT_FILTERS
Definition drc_item.h:93
@ DRCE_SILK_MASK_CLEARANCE
Definition drc_item.h:111
@ DRCE_PADSTACK
Definition drc_item.h:71
@ DRCE_MIRRORED_TEXT_ON_FRONT_LAYER
Definition drc_item.h:127
@ DRCE_LIB_FOOTPRINT_ISSUES
Definition drc_item.h:96
@ DRCE_MICROVIA_CROSSES_CORE
Definition drc_item.h:78
@ DRCE_OVERLAPPING_FOOTPRINTS
Definition drc_item.h:79
@ DRCE_SCHEMATIC_FIELDS_PARITY
Definition drc_item.h:137
@ DRCE_MISSING_COURTYARD
Definition drc_item.h:80
@ DRCE_MICROVIA_STACK_NOT_FILLED
Definition drc_item.h:75
@ DRCE_TRACK_NOT_CENTERED_ON_VIA
Definition drc_item.h:135
@ DRCE_COPPER_OUTSIDE_BOARD
Definition drc_item.h:142
@ DRCE_ISOLATED_COPPER
Definition drc_item.h:57
@ DRCE_MISSING_TUNING_PROFILE
Definition drc_item.h:130
@ DRCE_DRILLED_HOLES_TOO_CLOSE
Definition drc_item.h:61
@ DRCE_COPPER_SLIVER
Definition drc_item.h:107
@ DRCE_PTH_IN_COURTYARD
Definition drc_item.h:83
@ DRCE_FIRST
Definition drc_item.h:47
@ DRCE_DANGLING_VIA
Definition drc_item.h:59
@ DRCE_FOOTPRINT_TYPE_MISMATCH
Definition drc_item.h:95
@ DRCE_DUPLICATE_FOOTPRINT
Definition drc_item.h:89
@ DRCE_DANGLING_TRACK
Definition drc_item.h:60
@ DRCE_TEXT_HEIGHT
Definition drc_item.h:115
@ DRCE_DRILLED_HOLES_COLOCATED
Definition drc_item.h:62
@ DRCE_EXTRA_FOOTPRINT
Definition drc_item.h:90
@ DRCE_SILK_CLEARANCE
Definition drc_item.h:114
@ DRCE_LAST
Definition drc_item.h:144
@ DRCE_LIB_FOOTPRINT_MISMATCH
Definition drc_item.h:97
@ DRCE_NET_CONFLICT
Definition drc_item.h:91
@ DRCE_MISSING_FOOTPRINT
Definition drc_item.h:88
@ DRCE_UNMIRRORED_TEXT_ON_BACK_LAYER
Definition drc_item.h:128
@ DRCE_TEXT_THICKNESS
Definition drc_item.h:116
@ DRCE_NPTH_IN_COURTYARD
Definition drc_item.h:84
@ DRCE_CONNECTION_WIDTH
Definition drc_item.h:68
@ DRCE_SCHEMATIC_PARITY
Definition drc_item.h:92
#define _(s)
@ DEGREES_T
Definition eda_angle.h:30
#define TEXT_MIN_SIZE_MM
Minimum text size (1 micron).
Definition eda_text.h:61
#define TEXT_MAX_SIZE_MM
Maximum text size in mm (~10 inches)
Definition eda_text.h:62
EDA_UNITS
Definition eda_units.h:44
template KICOMMON_API std::optional< nlohmann::json > JSON_SETTINGS::Get< nlohmann::json >(const std::string &aPath) const
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:741
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ F_CrtYd
Definition layer_ids.h:112
@ Edge_Cuts
Definition layer_ids.h:108
@ B_Cu
Definition layer_ids.h:61
@ F_Fab
Definition layer_ids.h:115
@ Margin
Definition layer_ids.h:109
@ F_SilkS
Definition layer_ids.h:96
@ B_CrtYd
Definition layer_ids.h:111
@ In1_Cu
Definition layer_ids.h:62
@ B_SilkS
Definition layer_ids.h:97
@ PCB_LAYER_ID_COUNT
Definition layer_ids.h:167
@ F_Cu
Definition layer_ids.h:60
@ B_Fab
Definition layer_ids.h:114
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:750
KICOMMON_API wxString StringFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Return the string from aValue according to aUnits (inch, mm ...) for display.
@ MEANDER_STYLE_ROUND
Definition pns_meander.h:54
@ MEANDER_STYLE_CHAMFER
Definition pns_meander.h:55
@ OUTSIDE
Text appears outside the dimension line (default)
@ INLINE
Text appears in line with the dimension line.
CITER next(CITER it)
Definition ptree.cpp:120
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_IGNORE
static BOM_FMT_PRESET CSV()
Container to handle a stock of specific differential pairs each with unique track width,...
BOM_FMT_PRESET m_BomFmtSettings
List of stored BOM format presets.
BOM_PRESET m_BomSettings
List of stored BOM presets.
std::vector< BOM_PRESET > m_BomPresets
std::vector< BOM_FMT_PRESET > m_BomFmtPresets
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
A named microvia stack definition, chosen while routing instead of entering the values each time.
std::string GetTeardropTargetCanonicalName(TARGET_TD aTdType)
TARGET_TD GetTeardropTargetTypeFromCanonicalName(const std::string &aTargetName)
int clearance
SEVERITY SeverityFromString(const wxString &aSeverity)
Definition ui_common.cpp:58
wxString SeverityToString(const SEVERITY &aSeverity)
Definition ui_common.cpp:69
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
ISLAND_REMOVAL_MODE
Whether or not to remove isolated islands from a zone.
#define ZONE_THERMAL_RELIEF_GAP_MM
Definition zones.h:28
ZONE_CONNECTION
How pads are covered by copper in zone.
Definition zones.h:43
@ THERMAL
Use thermal relief for pads.
Definition zones.h:46
#define ZONE_BORDER_HATCH_DIST_MM
Definition zones.h:34
#define ZONE_BORDER_HATCH_MINDIST_MM
Definition zones.h:35
#define ZONE_THERMAL_RELIEF_COPPER_WIDTH_MM
Definition zones.h:29
#define ZONE_CLEARANCE_MM
Definition zones.h:32
#define ZONE_THICKNESS_MIN_VALUE_MM
Definition zones.h:31
#define ZONE_THICKNESS_MM
Definition zones.h:30
#define ZONE_BORDER_HATCH_MAXDIST_MM
Definition zones.h:36