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
20#include <magic_enum.hpp>
21#include <pcb_dimension.h>
22#include <pcb_track.h>
23#include <algorithm>
24#include <cmath>
25#include <layer_ids.h>
26#include <lset.h>
27#include <kiface_base.h>
28#include <pad.h>
31#include <drc/drc_item.h>
32#include <drc/drc_engine.h>
34#include <settings/parameters.h>
36#include <advanced_config.h>
37
38const int bdsSchemaVersion = 3;
39
40
41BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
42 NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aParent, aPath )
43{
44 // We want to leave alone parameters that aren't found in the project JSON as they may be
45 // initialized by the board file parser before NESTED_SETTINGS::LoadFromFile is called.
47
48 // Create a default NET_SETTINGS so that things don't break horribly if there's no project
49 // loaded. This also is used during file load for legacy boards that have netclasses stored
50 // in the file. After load, this information will be moved to the project and the pointer
51 // updated.
52 m_NetSettings = std::make_shared<NET_SETTINGS>( nullptr, "" );
53
54 m_HasStackup = false; // no stackup defined by default
55
56 m_Pad_Master = std::make_unique<PAD>( nullptr );
58
59 LSET all_set = LSET().set();
60 m_enabledLayers = all_set; // All layers enabled at first.
61 // SetCopperLayerCount() will adjust this.
62
63 // Default design is a double layer board with 4 user defined layers
66
68
69 // if true, when creating a new track starting on an existing track, use this track width
72
73 // First is always the reference designator
74 m_DefaultFPTextItems.emplace_back( wxT( "REF**" ), true, F_SilkS );
75 // Second is always the value
76 m_DefaultFPTextItems.emplace_back( wxT( "" ), true, F_Fab );
77 // Any following ones are freebies
78 m_DefaultFPTextItems.emplace_back( wxT( "${REFERENCE}" ), true, F_Fab );
79
86
93
94 // Edges & Courtyards; text properties aren't used but better to have them holding
95 // reasonable values than not.
98 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
102
105 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
109
112 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
114 m_TextItalic[ LAYER_CLASS_FAB ] = false;
116
119 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
123
124 m_StyleFPFields = false;
125 m_StyleFPText = false;
126 m_StyleFPShapes = false;
127 m_StyleFPDimensions = false;
128 m_StyleFPBarcodes = false;
129
138
139 m_useCustomTrackVia = false;
141 m_customViaSize.m_Diameter = pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE );
143
144 m_useCustomDiffPair = false;
148
165
166 for( int errorCode = DRCE_FIRST; errorCode <= DRCE_LAST; ++errorCode )
167 m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
168
171
175
178
181
184
187
195
201
203
206
208
211
214
216
220
221 m_BomExportFileName = wxS( "${PROJECTNAME}.csv" );
222 m_BomSettings = BOM_PRESET::DefaultEditing();
224
225 // Global mask margins:
229
230 // Solder paste margin absolute value
232 // Solder paste margin as a ratio of pad size
233 // The final margin is the sum of these 2 values
234 // Usually < 0 because the mask is smaller than pad
236
238 m_TentViasFront = true;
239 m_TentViasBack = true;
240
241 m_CoverViasFront = false;
242 m_CoverViasBack = false;
243
244 m_PlugViasFront = false;
245 m_PlugViasBack = false;
246
247 m_CapVias = false;
248
249 m_FillVias = false;
250
251 // Layer thickness for 3D viewer
253
254 // Default spacing for meanders
258
259 m_viaSizeIndex = 0;
260 m_viaStackIndex = 0;
262 m_diffPairIndex = 0;
263
264 // Parameters stored in JSON in the project file
265
266 // NOTE: Previously, BOARD_DESIGN_SETTINGS stored the basic board layer information (layer
267 // names and enable/disable state) in the project file even though this information is also
268 // stored in the board file. This was implemented for importing these settings from another
269 // project. Going forward, the import feature will just import from other board files (since
270 // we could have multi-board projects in the future anyway) so this functionality is dropped.
271
272 m_params.emplace_back( new PARAM<wxString>( "bom_export_filename",
273 &m_BomExportFileName, "${PROJECTNAME}.csv" ) );
274
275 m_params.emplace_back( new PARAM<BOM_PRESET>( "bom_settings",
276 &m_BomSettings, BOM_PRESET::DefaultEditing() ) );
277 m_params.emplace_back( new PARAM_LIST<BOM_PRESET>( "bom_presets",
278 &m_BomPresets, {} ) );
279
280 m_params.emplace_back( new PARAM<BOM_FMT_PRESET>( "bom_fmt_settings",
282 m_params.emplace_back( new PARAM_LIST<BOM_FMT_PRESET>( "bom_fmt_presets",
283 &m_BomFmtPresets, {} ) );
284
285 m_params.emplace_back( new PARAM<bool>( "rules.use_height_for_length_calcs",
286 &m_UseHeightForLengthCalcs, true ) );
287
288 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_clearance",
290 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
291
292 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_connection",
294 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
295
296 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_track_width",
298 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
299
300 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_annular_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_diameter",
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_through_hole_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_microvia_diameter",
314 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), pcbIUScale.MM_PER_IU ) );
315
316 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_drill",
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_hole_to_hole",
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_clearance",
326 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
327
328 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_silk_clearance",
330 pcbIUScale.mmToIU( -10.0 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
331
332 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_groove_width",
334 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
335
336 // While the maximum *effective* value is 4, we've had users interpret this as the count on
337 // all layers, and enter something like 10. They'll figure it out soon enough *unless* we
338 // enforce a max of 4 (and therefore reset it back to the default of 2), at which point it
339 // just looks buggy.
340 m_params.emplace_back( new PARAM<int>( "rules.min_resolved_spokes",
342
343 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_height",
345 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
346
347 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_thickness",
349 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
350
351 // Note: a clearance of -0.01 is a flag indicating we should use the legacy (pre-6.0) method
352 // based on the edge cut thicknesses.
353 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_copper_edge_clearance",
355 pcbIUScale.mmToIU( -0.01 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
356
357 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
358 [&]() -> nlohmann::json
359 {
360 nlohmann::json ret = {};
361
362 for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
363 {
364 wxString name = item.GetSettingsKey();
365 int code = item.GetErrorCode();
366
367 if( name.IsEmpty() || m_DRCSeverities.count( code ) == 0 )
368 continue;
369
370 ret[std::string( name.ToUTF8() )] = SeverityToString( m_DRCSeverities[code] );
371 }
372
373 return ret;
374 },
375 [&]( const nlohmann::json& aJson )
376 {
377 if( !aJson.is_object() )
378 return;
379
380 // Load V8 'hole_near_hole' token first (if present). Any current 'hole_to_hole' token
381 // found will then overwrite it.
382 // We can't use the migration architecture because we forgot to bump the version number
383 // when the change was made. But this is a one-off as any future deprecations should
384 // bump the version number and use registerMigration().
385 if( aJson.contains( "hole_near_hole" ) )
387
388 for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
389 {
390 wxString name = item.GetSettingsKey();
391 std::string key( name.ToUTF8() );
392
393 if( aJson.contains( key ) )
394 m_DRCSeverities[item.GetErrorCode()] = SeverityFromString( aJson[key] );
395 }
396 }, {} ) );
397
398 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "drc_exclusions",
399 [&]() -> nlohmann::json
400 {
401 nlohmann::json js = nlohmann::json::array();
402
403 for( const DRC_EXCLUSION& exclusion : m_DrcExclusions )
404 js.push_back( exclusion );
405
406 return js;
407 },
408 [&]( const nlohmann::json& aObj )
409 {
410 m_DrcExclusions.clear();
411
412 if( !aObj.is_array() )
413 return;
414
415 for( const nlohmann::json& entry : aObj )
416 {
417 if( entry.is_object() )
418 {
419 DRC_EXCLUSION exclusion = entry.get<DRC_EXCLUSION>();
420
421 if( !exclusion.GetSortKey().empty() )
422 m_DrcExclusions.insert( exclusion );
423 }
424 }
425 },
426 {} ) );
427
428 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "track_widths",
429 [&]() -> nlohmann::json
430 {
431 nlohmann::json js = nlohmann::json::array();
432
433 for( const int& width : m_TrackWidthList )
434 js.push_back( pcbIUScale.IUTomm( width ) );
435
436 return js;
437 },
438 [&]( const nlohmann::json& aJson )
439 {
440 if( !aJson.is_array() )
441 return;
442
443 m_TrackWidthList.clear();
444
445 for( const nlohmann::json& entry : aJson )
446 {
447 if( entry.empty() )
448 continue;
449
450 m_TrackWidthList.emplace_back( pcbIUScale.mmToIU( entry.get<double>() ) );
451 }
452 },
453 {} ) );
454
455 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "via_dimensions",
456 [&]() -> nlohmann::json
457 {
458 nlohmann::json js = nlohmann::json::array();
459
460 for( const auto& via : m_ViasDimensionsList )
461 {
462 nlohmann::json entry = {};
463
464 entry["diameter"] = pcbIUScale.IUTomm( via.m_Diameter );
465 entry["drill"] = pcbIUScale.IUTomm( via.m_Drill );
466
467 js.push_back( entry );
468 }
469
470 return js;
471 },
472 [&]( const nlohmann::json& aObj )
473 {
474 if( !aObj.is_array() )
475 return;
476
477 m_ViasDimensionsList.clear();
478
479 for( const nlohmann::json& entry : aObj )
480 {
481 if( entry.empty() || !entry.is_object() )
482 continue;
483
484 if( !entry.contains( "diameter" ) || !entry.contains( "drill" ) )
485 continue;
486
487 int diameter = pcbIUScale.mmToIU( entry["diameter"].get<double>() );
488 int drill = pcbIUScale.mmToIU( entry["drill"].get<double>() );
489
490 m_ViasDimensionsList.emplace_back( VIA_DIMENSION( diameter, drill ) );
491 }
492 },
493 {} ) );
494
495 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
496 "via_stack_presets",
497 [&]() -> nlohmann::json
498 {
499 nlohmann::json js = nlohmann::json::array();
500
501 for( const VIA_STACK_PRESET& preset : m_ViaStackPresets )
502 {
503 nlohmann::json entry = {};
504
505 entry["name"] = preset.m_Name.ToUTF8();
506 entry["start_layer"] = LSET::Name( preset.m_StartLayer );
507 entry["end_layer"] = LSET::Name( preset.m_EndLayer );
508 entry["staggered"] = preset.m_Staggered;
509 entry["via_size"] = pcbIUScale.IUTomm( preset.m_ViaSize );
510 entry["via_drill"] = pcbIUScale.IUTomm( preset.m_ViaDrill );
511 entry["use_netclass"] = preset.m_UseNetclass;
512 entry["filled"] = preset.m_Filled;
513 entry["capped"] = preset.m_Capped;
514 entry["pitch"] = pcbIUScale.IUTomm( preset.m_Pitch );
515
516 js.push_back( entry );
517 }
518
519 return js;
520 },
521 [&]( const nlohmann::json& aObj )
522 {
523 if( !aObj.is_array() )
524 return;
525
526 m_ViaStackPresets.clear();
527
528 // An odd or non-copper layer from a hand-edited file would make every
529 // LAYER_RANGE built from the preset throw or never terminate.
530 auto copperLayer = []( const nlohmann::json& aEntry, const char* aKey,
531 PCB_LAYER_ID aFallback ) -> PCB_LAYER_ID
532 {
533 if( !aEntry.contains( aKey ) || !aEntry[aKey].is_string() )
534 return aFallback;
535
536 wxString name = wxString::FromUTF8( aEntry[aKey].get<std::string>() );
537 int layer = LSET::NameToLayer( name );
538
539 if( layer >= 0 && layer < PCB_LAYER_ID_COUNT && !( layer & 1 ) && IsCopperLayer( layer ) )
540 return ToLAYER_ID( layer );
541
542 return aFallback;
543 };
544
545 auto boolOr = []( const nlohmann::json& aEntry, const char* aKey, bool aFallback )
546 {
547 return aEntry.contains( aKey ) && aEntry[aKey].is_boolean() ? aEntry[aKey].get<bool>() : aFallback;
548 };
549
550 auto mmOr = []( const nlohmann::json& aEntry, const char* aKey )
551 {
552 return aEntry.contains( aKey ) && aEntry[aKey].is_number()
553 ? pcbIUScale.mmToIU( aEntry[aKey].get<double>() )
554 : 0;
555 };
556
557 // Bound in mm, before the conversion to IU, because an absurd hand-edited
558 // value overflows int on the way in and lands past the limit as a negative
559 auto boundedMmOr = []( const nlohmann::json& aEntry, const char* aKey, double aMaxMM )
560 {
561 if( !aEntry.contains( aKey ) || !aEntry[aKey].is_number() )
562 return 0;
563
564 return pcbIUScale.mmToIU( std::clamp( aEntry[aKey].get<double>(), 0.0, aMaxMM ) );
565 };
566
567 for( const nlohmann::json& entry : aObj )
568 {
569 if( entry.empty() || !entry.is_object() || !entry.contains( "name" ) || !entry["name"].is_string() )
570 {
571 continue;
572 }
573
574 VIA_STACK_PRESET preset;
575
576 preset.m_Name = wxString::FromUTF8( entry["name"].get<std::string>() );
577 preset.m_StartLayer = copperLayer( entry, "start_layer", F_Cu );
578 preset.m_EndLayer = copperLayer( entry, "end_layer", In1_Cu );
579 preset.m_Staggered = boolOr( entry, "staggered", false );
580 preset.m_ViaSize = mmOr( entry, "via_size" );
581 preset.m_ViaDrill = mmOr( entry, "via_drill" );
582 preset.m_UseNetclass = boolOr( entry, "use_netclass", false );
583 preset.m_Filled = boolOr( entry, "filled", true );
584 preset.m_Capped = boolOr( entry, "capped", false );
585 preset.m_Pitch = boundedMmOr( entry, "pitch", MAX_MICROVIA_STACK_PITCH_MM );
586
587 // Presets are referenced by name, so a duplicate would be ambiguous.
588 auto sameName = [&]( const VIA_STACK_PRESET& aOther )
589 {
590 return aOther.m_Name.CmpNoCase( preset.m_Name ) == 0;
591 };
592
593 if( std::none_of( m_ViaStackPresets.begin(), m_ViaStackPresets.end(), sameName ) )
594 m_ViaStackPresets.push_back( preset );
595 }
596 },
597 {} ) );
598
599 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "diff_pair_dimensions",
600 [&]() -> nlohmann::json
601 {
602 nlohmann::json js = nlohmann::json::array();
603
604 for( const auto& pair : m_DiffPairDimensionsList )
605 {
606 nlohmann::json entry = {};
607
608 entry["width"] = pcbIUScale.IUTomm( pair.m_Width );
609 entry["gap"] = pcbIUScale.IUTomm( pair.m_Gap );
610 entry["via_gap"] = pcbIUScale.IUTomm( pair.m_ViaGap );
611
612 js.push_back( entry );
613 }
614
615 return js;
616 },
617 [&]( const nlohmann::json& aObj )
618 {
619 if( !aObj.is_array() )
620 return;
621
623
624 for( const nlohmann::json& entry : aObj )
625 {
626 if( entry.empty() || !entry.is_object() )
627 continue;
628
629 if( !entry.contains( "width" )
630 || !entry.contains( "gap" )
631 || !entry.contains( "via_gap" ) )
632 {
633 continue;
634 }
635
636 int width = pcbIUScale.mmToIU( entry["width"].get<double>() );
637 int gap = pcbIUScale.mmToIU( entry["gap"].get<double>() );
638 int via_gap = pcbIUScale.mmToIU( entry["via_gap"].get<double>() );
639
640 m_DiffPairDimensionsList.emplace_back( DIFF_PAIR_DIMENSION( width, gap, via_gap ) );
641 }
642 },
643 {} ) );
644
645 // Handle options for teardrops (targets and some others):
646 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_options",
647 [&]() -> nlohmann::json
648 {
649 nlohmann::json js = nlohmann::json::array();
650 nlohmann::json entry = {};
651
652 entry["td_onvia"] = m_TeardropParamsList.m_TargetVias;
653 entry["td_onpthpad"] = m_TeardropParamsList.m_TargetPTHPads;
654 entry["td_onsmdpad"] = m_TeardropParamsList.m_TargetSMDPads;
655 entry["td_ontrackend"] = m_TeardropParamsList.m_TargetTrack2Track;
656 entry["td_onroundshapesonly"] = m_TeardropParamsList.m_UseRoundShapesOnly;
657
658 js.push_back( entry );
659
660 return js;
661 },
662 [&]( const nlohmann::json& aObj )
663 {
664 if( !aObj.is_array() )
665 return;
666
667 for( const nlohmann::json& entry : aObj )
668 {
669 if( entry.empty() || !entry.is_object() )
670 continue;
671
672 if( entry.contains( "td_onvia" ) )
673 m_TeardropParamsList.m_TargetVias = entry["td_onvia"].get<bool>();
674
675 if( entry.contains( "td_onpthpad" ) )
676 m_TeardropParamsList.m_TargetPTHPads = entry["td_onpthpad"].get<bool>();
677
678 if( entry.contains( "td_onsmdpad" ) )
679 m_TeardropParamsList.m_TargetSMDPads = entry["td_onsmdpad"].get<bool>();
680
681 if( entry.contains( "td_ontrackend" ) )
682 m_TeardropParamsList.m_TargetTrack2Track = entry["td_ontrackend"].get<bool>();
683
684 if( entry.contains( "td_onroundshapesonly" ) )
685 m_TeardropParamsList.m_UseRoundShapesOnly = entry["td_onroundshapesonly"].get<bool>();
686
687 // Legacy settings
688 for( int ii = 0; ii < 3; ++ii )
689 {
690 TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)ii );
691
692 if( entry.contains( "td_allow_use_two_tracks" ) )
693 td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
694
695 if( entry.contains( "td_curve_segcount" ) )
696 {
697 if( entry["td_curve_segcount"].get<int>() > 0 )
698 td_prm->m_CurvedEdges = true;
699 }
700
701 if( entry.contains( "td_on_pad_in_zone" ) )
702 td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
703 }
704 }
705 },
706 {} ) );
707
708 // Handle parameters (sizes, shape) for each type of teardrop:
709 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_parameters",
710 [&]() -> nlohmann::json
711 {
712 nlohmann::json js = nlohmann::json::array();
713
714 for( size_t ii = 0; ii < m_TeardropParamsList.GetParametersCount(); ii++ )
715 {
716 nlohmann::json entry = {};
717 TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)ii );
718
719 entry["td_target_name"] = GetTeardropTargetCanonicalName( (TARGET_TD)ii );
720 entry["td_enabled"] = td_prm->m_Enabled;
721 entry["td_maxlen"] = pcbIUScale.IUTomm( td_prm->m_TdMaxLen );
722 entry["td_maxheight"] = pcbIUScale.IUTomm( td_prm->m_TdMaxWidth );
723 entry["td_length_ratio"] = td_prm->m_BestLengthRatio;
724 entry["td_height_ratio"] = td_prm->m_BestWidthRatio;
725 entry["td_curve_segcount"] = td_prm->m_CurvedEdges ? 1 : 0;
726 entry["td_width_to_size_filter_ratio"] = td_prm->m_WidthtoSizeFilterRatio;
727 entry["td_allow_use_two_tracks"] = td_prm->m_AllowUseTwoTracks;
728 entry["td_on_pad_in_zone"] = td_prm->m_TdOnPadsInZones;
729
730 js.push_back( entry );
731 }
732
733 return js;
734 },
735 [&]( const nlohmann::json& aObj )
736 {
737 if( !aObj.is_array() )
738 return;
739
740 for( const nlohmann::json& entry : aObj )
741 {
742 if( entry.empty() || !entry.is_object() )
743 continue;
744
745 if( !entry.contains( "td_target_name" ) )
746 continue;
747
748 int idx = GetTeardropTargetTypeFromCanonicalName( entry["td_target_name"].get<std::string>() );
749
750 if( idx >= 0 && idx < 3 )
751 {
752 TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)idx );
753
754 // Pads and vias carry their enable in the board file; this one has
755 // nowhere else to live.
756 if( entry.contains( "td_enabled" ) )
757 td_prm->m_Enabled = entry["td_enabled"].get<bool>();
758
759 if( entry.contains( "td_maxlen" ) )
760 td_prm->m_TdMaxLen = pcbIUScale.mmToIU( entry["td_maxlen"].get<double>() );
761
762 if( entry.contains( "td_maxheight" ) )
763 td_prm->m_TdMaxWidth = pcbIUScale.mmToIU( entry["td_maxheight"].get<double>() );
764
765 if( entry.contains( "td_length_ratio" ) )
766 td_prm->m_BestLengthRatio = entry["td_length_ratio"].get<double>();
767
768 if( entry.contains( "td_height_ratio" ) )
769 td_prm->m_BestWidthRatio = entry["td_height_ratio"].get<double>();
770
771 if( entry.contains( "td_curve_segcount" ) )
772 {
773 if( entry["td_curve_segcount"].get<int>() > 0 )
774 td_prm->m_CurvedEdges = true;
775 }
776
777 if( entry.contains( "td_width_to_size_filter_ratio" ) )
778 td_prm->m_WidthtoSizeFilterRatio = entry["td_width_to_size_filter_ratio"].get<double>();
779
780 if( entry.contains( "td_allow_use_two_tracks" ) )
781 td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
782
783 if( entry.contains( "td_on_pad_in_zone" ) )
784 td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
785 }
786 }
787 },
788 {} ) );
789
790 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "tuning_pattern_settings",
791 [&]() -> nlohmann::json
792 {
793 nlohmann::json js = {};
794
795 auto make_settings =
796 []( const PNS::MEANDER_SETTINGS& aSettings )
797 {
798 nlohmann::json entry = {};
799
800 entry["min_amplitude"] = pcbIUScale.IUTomm( aSettings.m_minAmplitude );
801 entry["max_amplitude"] = pcbIUScale.IUTomm( aSettings.m_maxAmplitude );
802 entry["spacing"] = pcbIUScale.IUTomm( aSettings.m_spacing );
803 entry["corner_style"] = aSettings.m_cornerStyle == PNS::MEANDER_STYLE_CHAMFER ? 0 : 1;
804 entry["corner_radius_percentage"] = aSettings.m_cornerRadiusPercentage;
805 entry["single_sided"] = aSettings.m_singleSided;
806
807 return entry;
808 };
809
810 js["single_track_defaults"] = make_settings( m_SingleTrackMeanderSettings );
811 js["diff_pair_defaults"] = make_settings( m_DiffPairMeanderSettings );
812 js["diff_pair_skew_defaults"] = make_settings( m_SkewMeanderSettings );
813
814 return js;
815 },
816 [&]( const nlohmann::json& aObj )
817 {
818 auto read_settings =
819 []( const nlohmann::json& entry ) -> PNS::MEANDER_SETTINGS
820 {
821 PNS::MEANDER_SETTINGS settings;
822
823 if( entry.contains( "min_amplitude" ) )
824 settings.m_minAmplitude = pcbIUScale.mmToIU( entry["min_amplitude"].get<double>() );
825
826 if( entry.contains( "max_amplitude" ) )
827 settings.m_maxAmplitude = pcbIUScale.mmToIU( entry["max_amplitude"].get<double>() );
828
829 if( entry.contains( "spacing" ) )
830 settings.m_spacing = pcbIUScale.mmToIU( entry["spacing"].get<double>() );
831
832 if( entry.contains( "corner_style" ) )
833 {
834 settings.m_cornerStyle = entry["corner_style"] == 0 ? PNS::MEANDER_STYLE_CHAMFER
836 }
837
838 if( entry.contains( "corner_radius_percentage" ) )
839 settings.m_cornerRadiusPercentage = entry["corner_radius_percentage"].get<int>();
840
841 if( entry.contains( "single_sided" ) )
842 settings.m_singleSided = entry["single_sided"].get<bool>();
843
844 return settings;
845 };
846
847 if( aObj.contains( "single_track_defaults" ) )
848 m_SingleTrackMeanderSettings = read_settings( aObj["single_track_defaults"] );
849
850 if( aObj.contains( "diff_pair_defaults" ) )
851 m_DiffPairMeanderSettings = read_settings( aObj["diff_pair_defaults"] );
852
853 if( aObj.contains( "diff_pair_skew_defaults" ) )
854 m_SkewMeanderSettings = read_settings( aObj["diff_pair_skew_defaults"] );
855 },
856 {} ) );
857
858 int minTextSize = pcbIUScale.mmToIU( TEXT_MIN_SIZE_MM );
859 int maxTextSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
860 int minStroke = 1;
861 int maxStroke = pcbIUScale.mmToIU( 100 );
862
863 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_line_width",
865 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
866
867 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_v",
869 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
870
871 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_h",
873 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
874
875 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_thickness",
877 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
878
879 m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_italic",
880 &m_TextItalic[LAYER_CLASS_SILK], false ) );
881
882 m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_upright",
883 &m_TextUpright[ LAYER_CLASS_SILK ], true ) );
884
885 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_line_width",
887 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
888
889 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_v",
891 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
892
893 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_h",
895 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
896
897 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_thickness",
899 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
900
901 m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_italic",
902 &m_TextItalic[LAYER_CLASS_COPPER], false ) );
903
904 m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_upright",
906
907 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.board_outline_line_width",
909 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
910
911 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.courtyard_line_width",
913 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
914
915 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_line_width",
917 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
918
919 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_v",
921 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
922
923 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_h",
925 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
926
927 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_thickness",
929 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
930
931 m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_italic",
932 &m_TextItalic[LAYER_CLASS_FAB], false ) );
933
934 m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_upright",
935 &m_TextUpright[LAYER_CLASS_FAB], true ) );
936
937 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_line_width",
939 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
940
941 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_v",
943 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
944
945 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_h",
947 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
948
949 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_thickness",
951 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
952
953 m_params.emplace_back( new PARAM<bool>( "defaults.other_text_italic",
954 &m_TextItalic[LAYER_CLASS_OTHERS], false ) );
955
956 m_params.emplace_back( new PARAM<bool>( "defaults.other_text_upright",
958
959 m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_MODE>( "defaults.dimension_units",
962
963 m_params.emplace_back( new PARAM_ENUM<DIM_PRECISION>( "defaults.dimension_precision",
965
966 m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_FORMAT>( "defaults.dimensions.units_format",
969
970 m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.suppress_zeroes",
971 &m_DimensionSuppressZeroes, true ) );
972
973 // NOTE: excluding DIM_TEXT_POSITION::MANUAL from the valid range here
974 m_params.emplace_back( new PARAM_ENUM<DIM_TEXT_POSITION>( "defaults.dimensions.text_position",
977
978 m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.keep_text_aligned",
980
981 m_params.emplace_back( new PARAM<int>( "defaults.dimensions.arrow_length",
984
985 m_params.emplace_back( new PARAM<int>( "defaults.dimensions.extension_offset",
988
989 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_fields",
990 &m_StyleFPFields, false ) );
991 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_text",
992 &m_StyleFPText, false ) );
993 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_shapes",
994 &m_StyleFPShapes, false ) );
995 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_dimensions",
996 &m_StyleFPDimensions, false ) );
997 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_barcodes",
998 &m_StyleFPBarcodes, false ) );
999
1000 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.zones.min_clearance",
1001 &m_defaultZoneSettings.m_ZoneClearance, pcbIUScale.mmToIU( ZONE_CLEARANCE_MM ),
1002 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1003
1004 m_params.emplace_back( new PARAM_SCALED<int>(
1005 "defaults.zones.min_thickness", &m_defaultZoneSettings.m_ZoneMinThickness,
1007 pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1008
1009 m_params.emplace_back( new PARAM_ENUM<ZONE_FILL_MODE>( "defaults.zones.fill_mode",
1013
1014 m_params.emplace_back(
1015 new PARAM_SCALED<int>( "defaults.zones.hatch_thickness", &m_defaultZoneSettings.m_HatchThickness,
1016 std::max( pcbIUScale.mmToIU( ZONE_THICKNESS_MM ) * 4, pcbIUScale.mmToIU( 1.0 ) ),
1017 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1018
1019 m_params.emplace_back(
1020 new PARAM_SCALED<int>( "defaults.zones.hatch_gap", &m_defaultZoneSettings.m_HatchGap,
1021 std::max( pcbIUScale.mmToIU( ZONE_THICKNESS_MM ) * 6, pcbIUScale.mmToIU( 1.5 ) ),
1022 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1023
1024 m_params.emplace_back( new PARAM_LAMBDA<double>(
1025 "defaults.zones.hatch_orientation",
1026 [&]() -> double
1027 {
1028 return m_defaultZoneSettings.m_HatchOrientation.AsDegrees();
1029 },
1030 [&]( double aVal )
1031 {
1032 m_defaultZoneSettings.m_HatchOrientation = EDA_ANGLE( aVal, DEGREES_T );
1033 },
1034 0.0 ) );
1035
1036 m_params.emplace_back( new PARAM<int>( "defaults.zones.hatch_smoothing_level",
1037 &m_defaultZoneSettings.m_HatchSmoothingLevel, 0, 0, 3 ) );
1038
1039 m_params.emplace_back( new PARAM<double>( "defaults.zones.hatch_smoothing_value",
1040 &m_defaultZoneSettings.m_HatchSmoothingValue, 0.1, 0.0, 1.0 ) );
1041
1043 "defaults.zones.border_display_style", &m_defaultZoneSettings.m_ZoneBorderDisplayStyle,
1046
1047 m_params.emplace_back( new PARAM_SCALED<int>(
1048 "defaults.zones.border_hatch_pitch", &m_defaultZoneSettings.m_BorderHatchPitch,
1050 pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MAXDIST_MM ), pcbIUScale.MM_PER_IU ) );
1051
1052 m_params.emplace_back(
1053 new PARAM_SCALED<long>( "defaults.zones.thermal_relief_gap", &m_defaultZoneSettings.m_ThermalReliefGap,
1054 pcbIUScale.mmToIU( ZONE_THERMAL_RELIEF_GAP_MM ), pcbIUScale.mmToIU( 0.0 ),
1055 pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1056
1057 m_params.emplace_back( new PARAM_SCALED<long>(
1058 "defaults.zones.thermal_relief_spoke_width", &m_defaultZoneSettings.m_ThermalReliefSpokeWidth,
1060 pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1061
1062 m_params.emplace_back( new PARAM_LAMBDA<int>(
1063 "defaults.zones.pad_connection",
1064 [&]() -> int
1065 {
1066 return static_cast<int>( m_defaultZoneSettings.GetPadConnection() );
1067 },
1068 [&]( int aVal )
1069 {
1070 m_defaultZoneSettings.SetPadConnection( static_cast<ZONE_CONNECTION>( aVal ) );
1071 },
1072 static_cast<int>( ZONE_CONNECTION::THERMAL ) ) );
1073
1074 m_params.emplace_back( new PARAM_LAMBDA<int>(
1075 "defaults.zones.corner_smoothing",
1076 [&]() -> int
1077 {
1078 return static_cast<int>( m_defaultZoneSettings.GetCornerSmoothingType() );
1079 },
1080 [&]( int aVal )
1081 {
1082 m_defaultZoneSettings.SetCornerSmoothingType(
1083 magic_enum::enum_cast<ZONE_SETTINGS::CORNER_SMOOTHING>( aVal ).value_or(
1085 },
1086 static_cast<int>( ZONE_SETTINGS::CORNER_SMOOTHING::NO_SMOOTHING ) ) );
1087
1088 m_params.emplace_back( new PARAM_LAMBDA<double>(
1089 "defaults.zones.corner_radius",
1090 [&]() -> double
1091 {
1092 return pcbIUScale.IUTomm( m_defaultZoneSettings.GetCornerRadius() );
1093 },
1094 [&]( double aVal )
1095 {
1096 m_defaultZoneSettings.SetCornerRadius( pcbIUScale.mmToIU( aVal ) );
1097 },
1098 0.0 ) );
1099
1100 m_params.emplace_back( new PARAM_LAMBDA<int>(
1101 "defaults.zones.remove_islands",
1102 [&]() -> int
1103 {
1104 return static_cast<int>( m_defaultZoneSettings.GetIslandRemovalMode() );
1105 },
1106 [&]( int aVal )
1107 {
1108 m_defaultZoneSettings.SetIslandRemovalMode( static_cast<ISLAND_REMOVAL_MODE>( aVal ) );
1109 },
1110 static_cast<int>( ISLAND_REMOVAL_MODE::ALWAYS ) ) );
1111
1112 m_params.emplace_back( new PARAM_LAMBDA<double>(
1113 "defaults.zones.min_island_area",
1114 [&]() -> double
1115 {
1116 const double iuPerMm2 = pcbIUScale.IU_PER_MM * pcbIUScale.IU_PER_MM;
1117 return static_cast<double>( m_defaultZoneSettings.GetMinIslandArea() ) / iuPerMm2;
1118 },
1119 [&]( double aVal )
1120 {
1121 const double iuPerMm2 = pcbIUScale.IU_PER_MM * pcbIUScale.IU_PER_MM;
1122 m_defaultZoneSettings.SetMinIslandArea( static_cast<long long int>( aVal * iuPerMm2 ) );
1123 },
1124 10.0 ) );
1125
1126 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "defaults.pads",
1127 [&]() -> nlohmann::json
1128 {
1129 nlohmann::json ret =
1130 {
1131 { "width", pcbIUScale.IUTomm( m_Pad_Master->GetSize( PADSTACK::ALL_LAYERS ).x ) },
1132 { "height", pcbIUScale.IUTomm( m_Pad_Master->GetSize( PADSTACK::ALL_LAYERS ).y ) },
1133 { "drill", pcbIUScale.IUTomm( m_Pad_Master->GetDrillSize().x ) }
1134 };
1135
1136 return ret;
1137 },
1138 [&]( const nlohmann::json& aJson )
1139 {
1140 if( aJson.contains( "width" ) && aJson.contains( "height" ) && aJson.contains( "drill" ) )
1141 {
1142 VECTOR2I sz;
1143 sz.x = pcbIUScale.mmToIU( aJson["width"].get<double>() );
1144 sz.y = pcbIUScale.mmToIU( aJson["height"].get<double>() );
1145
1146 m_Pad_Master->SetPadstackMode( PADSTACK::MODE::NORMAL );
1147 m_Pad_Master->SetSize( PADSTACK::ALL_LAYERS, sz );
1148
1149 int drill = pcbIUScale.mmToIU( aJson["drill"].get<double>() );
1150
1151 m_Pad_Master->SetDrillSize( VECTOR2I( drill, drill ) );
1152 }
1153 }, {} ) );
1154
1155 m_params.emplace_back( new PARAM_SCALED<int>( "rules.max_error",
1157 pcbIUScale.mmToIU( 0.0001 ), pcbIUScale.mmToIU( 1.0 ), pcbIUScale.MM_PER_IU ) );
1158
1159 m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_mask_to_copper_clearance",
1161 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1162
1163 m_params.emplace_back( new PARAM<bool>( "zones_allow_external_fillets",
1164 &m_ZoneKeepExternalFillets, false ) );
1165
1166
1168
1169 registerMigration( 1, 2,
1170 [&]() -> bool
1171 {
1172 // Schema 1 to 2: move mask and paste margin settings back to board.
1173 // The parameters are removed, so we just have to manually load them here and
1174 // they will get saved with the board
1175 if( std::optional<double> optval = Get<double>( "rules.solder_mask_clearance" ) )
1176 m_SolderMaskExpansion = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
1177
1178 if( std::optional<double> optval = Get<double>( "rules.solder_mask_min_width" ) )
1179 m_SolderMaskMinWidth = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
1180
1181 if( std::optional<double> optval = Get<double>( "rules.solder_paste_clearance" ) )
1182 m_SolderPasteMargin = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
1183
1184 if( std::optional<double> optval = Get<double>( "rules.solder_paste_margin_ratio" ) )
1185 m_SolderPasteMarginRatio = *optval;
1186
1187 try
1188 {
1189 At( "rules" ).erase( "solder_mask_clearance" );
1190 At( "rules" ).erase( "solder_mask_min_width" );
1191 At( "rules" ).erase( "solder_paste_clearance" );
1192 At( "rules" ).erase( "solder_paste_margin_ratio" );
1193 }
1194 catch( ... )
1195 {}
1196
1197 return true;
1198 } );
1199
1201}
1202
1203
1205{
1206 if( m_parent )
1207 {
1208 m_parent->ReleaseNestedSettings( this );
1209 m_parent = nullptr;
1210 }
1211}
1212
1213
1215 NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aOther.m_parent,
1216 aOther.m_path ),
1217 m_Pad_Master( nullptr )
1218{
1219 initFromOther( aOther );
1220}
1221
1222
1224{
1225 initFromOther( aOther );
1226 return *this;
1227}
1228
1229
1231{
1232 // Copy of NESTED_SETTINGS around is not allowed, so let's just update the params.
1242 m_MinConn = aOther.m_MinConn;
1259 m_MaxError = aOther.m_MaxError;
1272 m_CapVias = aOther.m_CapVias;
1273 m_FillVias = aOther.m_FillVias;
1276
1277 std::copy( std::begin( aOther.m_LineThickness ), std::end( aOther.m_LineThickness ),
1278 std::begin( m_LineThickness ) );
1279
1280 std::copy( std::begin( aOther.m_TextSize ), std::end( aOther.m_TextSize ),
1281 std::begin( m_TextSize ) );
1282
1283 std::copy( std::begin( aOther.m_TextThickness ), std::end( aOther.m_TextThickness ),
1284 std::begin( m_TextThickness ) );
1285
1286 std::copy( std::begin( aOther.m_TextItalic ), std::end( aOther.m_TextItalic ),
1287 std::begin( m_TextItalic ) );
1288
1289 std::copy( std::begin( aOther.m_TextUpright ), std::end( aOther.m_TextUpright ),
1290 std::begin( m_TextUpright ) );
1291
1300
1301 m_auxOrigin = aOther.m_auxOrigin;
1302 m_gridOrigin = aOther.m_gridOrigin;
1303 m_HasStackup = aOther.m_HasStackup;
1307 m_BomPresets = aOther.m_BomPresets;
1310
1325 m_stackup = aOther.m_stackup;
1327 m_Pad_Master = std::make_unique<PAD>( *aOther.m_Pad_Master );
1329
1335}
1336
1337
1339{
1340 if( m_TrackWidthList != aOther.m_TrackWidthList ) return false;
1341 if( m_ViasDimensionsList != aOther.m_ViasDimensionsList ) return false;
1342 if( m_ViaStackPresets != aOther.m_ViaStackPresets )
1343 return false;
1344 if( m_DiffPairDimensionsList != aOther.m_DiffPairDimensionsList ) return false;
1345 if( m_CurrentViaType != aOther.m_CurrentViaType ) return false;
1346 if( m_UseConnectedTrackWidth != aOther.m_UseConnectedTrackWidth ) return false;
1347 if( m_TempOverrideTrackWidth != aOther.m_TempOverrideTrackWidth ) return false;
1348 if( m_MinClearance != aOther.m_MinClearance ) return false;
1349 if( m_MinGrooveWidth != aOther.m_MinGrooveWidth ) return false;
1350 if( m_MinConn != aOther.m_MinConn ) return false;
1351 if( m_TrackMinWidth != aOther.m_TrackMinWidth ) return false;
1352 if( m_ViasMinAnnularWidth != aOther.m_ViasMinAnnularWidth ) return false;
1353 if( m_ViasMinSize != aOther.m_ViasMinSize ) return false;
1354 if( m_MinThroughDrill != aOther.m_MinThroughDrill ) return false;
1356 return false;
1357 if( m_MicroViasMinDrill != aOther.m_MicroViasMinDrill ) return false;
1358 if( m_CopperEdgeClearance != aOther.m_CopperEdgeClearance ) return false;
1359 if( m_HoleClearance != aOther.m_HoleClearance ) return false;
1360 if( m_HoleToHoleMin != aOther.m_HoleToHoleMin ) return false;
1361 if( m_SilkClearance != aOther.m_SilkClearance ) return false;
1362 if( m_MinResolvedSpokes != aOther.m_MinResolvedSpokes ) return false;
1363 if( m_MinSilkTextHeight != aOther.m_MinSilkTextHeight ) return false;
1364 if( m_MinSilkTextThickness != aOther.m_MinSilkTextThickness ) return false;
1365 if( m_DRCSeverities != aOther.m_DRCSeverities ) return false;
1366 if( m_DrcExclusions != aOther.m_DrcExclusions ) return false;
1367 if( m_ZoneKeepExternalFillets != aOther.m_ZoneKeepExternalFillets ) return false;
1368 if( m_MaxError != aOther.m_MaxError ) return false;
1369 if( m_SolderMaskExpansion != aOther.m_SolderMaskExpansion ) return false;
1370 if( m_SolderMaskMinWidth != aOther.m_SolderMaskMinWidth ) return false;
1372 if( m_SolderPasteMargin != aOther.m_SolderPasteMargin ) return false;
1373 if( m_SolderPasteMarginRatio != aOther.m_SolderPasteMarginRatio ) return false;
1375 if( m_TentViasFront != aOther.m_TentViasFront ) return false;
1376 if( m_TentViasBack != aOther.m_TentViasBack ) return false;
1377 if( m_CoverViasFront != aOther.m_CoverViasFront ) return false;
1378 if( m_CoverViasBack != aOther.m_CoverViasBack ) return false;
1379 if( m_PlugViasFront != aOther.m_PlugViasFront ) return false;
1380 if( m_PlugViasBack != aOther.m_PlugViasBack ) return false;
1381 if( m_CapVias != aOther.m_CapVias ) return false;
1382 if( m_FillVias != aOther.m_FillVias ) return false;
1383 if( m_DefaultFPTextItems != aOther.m_DefaultFPTextItems ) return false;
1384 if( m_UserLayerNames != aOther.m_UserLayerNames ) return false;
1385
1386 if( !std::equal( std::begin( m_LineThickness ), std::end( m_LineThickness ),
1387 std::begin( aOther.m_LineThickness ) ) )
1388 return false;
1389
1390 if( !std::equal( std::begin( m_TextSize ), std::end( m_TextSize ),
1391 std::begin( aOther.m_TextSize ) ) )
1392 return false;
1393
1394 if( !std::equal( std::begin( m_TextThickness ), std::end( m_TextThickness ),
1395 std::begin( aOther.m_TextThickness ) ) )
1396 return false;
1397
1398 if( !std::equal( std::begin( m_TextItalic ), std::end( m_TextItalic ),
1399 std::begin( aOther.m_TextItalic ) ) )
1400 return false;
1401
1402 if( !std::equal( std::begin( m_TextUpright ), std::end( m_TextUpright ),
1403 std::begin( aOther.m_TextUpright ) ) )
1404 return false;
1405
1406 if( m_DimensionUnitsMode != aOther.m_DimensionUnitsMode ) return false;
1407 if( m_DimensionPrecision != aOther.m_DimensionPrecision ) return false;
1408 if( m_DimensionUnitsFormat != aOther.m_DimensionUnitsFormat ) return false;
1409 if( m_DimensionSuppressZeroes != aOther.m_DimensionSuppressZeroes ) return false;
1410 if( m_DimensionTextPosition != aOther.m_DimensionTextPosition ) return false;
1411 if( m_DimensionKeepTextAligned != aOther.m_DimensionKeepTextAligned ) return false;
1412 if( m_DimensionArrowLength != aOther.m_DimensionArrowLength ) return false;
1413 if( m_DimensionExtensionOffset != aOther.m_DimensionExtensionOffset ) return false;
1414 if( m_auxOrigin != aOther.m_auxOrigin ) return false;
1415 if( m_gridOrigin != aOther.m_gridOrigin ) return false;
1416 if( m_HasStackup != aOther.m_HasStackup ) return false;
1417 if( m_UseHeightForLengthCalcs != aOther.m_UseHeightForLengthCalcs ) return false;
1418 if( m_BomExportFileName != aOther.m_BomExportFileName ) return false;
1419 if( m_BomSettings != aOther.m_BomSettings ) return false;
1420 if( m_BomPresets != aOther.m_BomPresets ) return false;
1421 if( m_BomFmtSettings != aOther.m_BomFmtSettings ) return false;
1422 if( m_BomFmtPresets != aOther.m_BomFmtPresets ) return false;
1423 if( m_trackWidthIndex != aOther.m_trackWidthIndex ) return false;
1424 if( m_viaSizeIndex != aOther.m_viaSizeIndex ) return false;
1425 if( m_viaStackIndex != aOther.m_viaStackIndex )
1426 return false;
1427 if( m_diffPairIndex != aOther.m_diffPairIndex ) return false;
1428 if( m_useCustomTrackVia != aOther.m_useCustomTrackVia ) return false;
1429 if( m_customTrackWidth != aOther.m_customTrackWidth ) return false;
1430 if( m_customViaSize != aOther.m_customViaSize ) return false;
1431 if( m_useCustomDiffPair != aOther.m_useCustomDiffPair ) return false;
1432 if( m_customDiffPair != aOther.m_customDiffPair ) return false;
1433 if( m_copperLayerCount != aOther.m_copperLayerCount ) return false;
1434 if( m_userDefinedLayerCount != aOther.m_userDefinedLayerCount ) return false;
1435 if( m_enabledLayers != aOther.m_enabledLayers ) return false;
1436 if( m_boardThickness != aOther.m_boardThickness ) return false;
1437 if( m_currentNetClassName != aOther.m_currentNetClassName ) return false;
1438 if( m_stackup != aOther.m_stackup ) return false;
1439 if( *m_NetSettings != *aOther.m_NetSettings ) return false;
1440 if( *m_Pad_Master != *aOther.m_Pad_Master ) return false;
1441 if( m_defaultZoneSettings != aOther.m_defaultZoneSettings ) return false;
1442
1443 if( m_StyleFPFields != aOther.m_StyleFPFields ) return false;
1444 if( m_StyleFPText != aOther.m_StyleFPText ) return false;
1445 if( m_StyleFPShapes != aOther.m_StyleFPShapes ) return false;
1446 if( m_StyleFPDimensions != aOther.m_StyleFPDimensions ) return false;
1447 if( m_StyleFPBarcodes != aOther.m_StyleFPBarcodes ) return false;
1448
1449 return true;
1450}
1451
1452
1454{
1472 std::string units_ptr( "defaults.dimension_units" );
1473 std::string precision_ptr( "defaults.dimension_precision" );
1474
1475 if( !( Contains( units_ptr )
1476 && Contains( precision_ptr )
1477 && At( units_ptr ).is_number_integer()
1478 && At( precision_ptr ).is_number_integer() ) )
1479 {
1480 // if either is missing or invalid, migration doesn't make sense
1481 return true;
1482 }
1483
1484 int units = *Get<int>( units_ptr );
1485 int precision = *Get<int>( precision_ptr );
1486
1487 // The enum maps directly to precision if the units is mils
1488 int extraDigits = 0;
1489
1490 switch( units )
1491 {
1492 case 0: extraDigits = 3; break;
1493 case 2: extraDigits = 2; break;
1494 default: break;
1495 }
1496
1497 precision += extraDigits;
1498
1499 Set( precision_ptr, precision );
1500
1501 return true;
1502}
1503
1504
1506{
1507 // Schema 2 to 3: convert DRC exclusions from legacy pipe-delimited strings to ProtoJSON
1508 std::optional<nlohmann::json> opt = Get<nlohmann::json>( "drc_exclusions" );
1509
1510 if( !opt )
1511 return true;
1512
1513 nlohmann::json migrated = nlohmann::json::array();
1514
1515 for( const nlohmann::json& entry : *opt )
1516 {
1517 if( entry.is_object() )
1518 {
1519 migrated.push_back( entry );
1520 }
1521 else if( entry.is_array() && entry.size() > 0 )
1522 {
1523 wxString markerData = entry[0].get<wxString>();
1524 wxString comment = entry.size() > 1 ? entry[1].get<wxString>() : wxString();
1525
1526 DRC_EXCLUSION ex = DRC_EXCLUSION::FromLegacyStrings( markerData, comment );
1527
1528 if( !ex.GetSortKey().empty() )
1529 migrated.push_back( ex );
1530 }
1531 else if( entry.is_string() )
1532 {
1533 DRC_EXCLUSION ex = DRC_EXCLUSION::FromLegacyStrings( entry.get<wxString>(), wxString() );
1534
1535 if( !ex.GetSortKey().empty() )
1536 migrated.push_back( ex );
1537 }
1538 }
1539
1540 Set( "drc_exclusions", migrated );
1541
1542 return true;
1543}
1544
1545
1546bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
1547{
1548 bool ret = NESTED_SETTINGS::LoadFromFile( aDirectory );
1549
1550 // A number of things won't have been translated by the PROJECT_FILE migration because of
1551 // descoped objects required to decode this data. So, it will be in the legacy.pcbnew
1552 // section and needs to be pulled out here
1553
1554 PROJECT_FILE* project = dynamic_cast<PROJECT_FILE*>( GetParent() );
1555
1556 if( !project )
1557 return ret;
1558
1559 bool migrated = false;
1560
1561 auto drcName =
1562 []( int aCode ) -> std::string
1563 {
1564 return std::string( DRC_ITEM::Create( aCode )->GetSettingsKey().ToUTF8() );
1565 };
1566
1567 const std::string rs = "rule_severities.";
1568 const std::string no_courtyard_key = "legacy_no_courtyard_defined";
1569 const std::string courtyard_overlap_key = "legacy_courtyards_overlap";
1570
1571 try
1572 {
1573 nlohmann::json& severities =
1574 project->Internals()->at( "/board/design_settings/rule_severities"_json_pointer );
1575
1576 if( severities.contains( no_courtyard_key ) )
1577 {
1578 if( severities[no_courtyard_key].get<bool>() )
1579 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "error" );
1580 else
1581 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "ignore" );
1582
1583 severities.erase( no_courtyard_key );
1584 migrated = true;
1585 }
1586
1587 if( severities.contains( courtyard_overlap_key ) )
1588 {
1589 if( severities[courtyard_overlap_key].get<bool>() )
1590 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "error" );
1591 else
1592 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "ignore" );
1593
1594 severities.erase( courtyard_overlap_key );
1595 migrated = true;
1596 }
1597 }
1598 catch( ... )
1599 {
1600 }
1601
1602 if( Contains( "legacy" ) )
1603 {
1604 // This defaults to false for new boards, but version 5.1.x and prior kept the fillets
1605 // so we do the same for legacy boards.
1607
1608 project->At( "legacy" ).erase( "pcbnew" );
1609 }
1610
1611 // Now that we have everything, we need to load again
1612 if( migrated )
1613 Load();
1614
1615 return ret;
1616}
1617
1618
1620{
1621 return m_DRCSeverities[ aDRCErrorCode ];
1622}
1623
1624
1625bool BOARD_DESIGN_SETTINGS::Ignore( int aDRCErrorCode )
1626{
1627 return m_DRCSeverities[ aDRCErrorCode ] == RPT_SEVERITY_IGNORE;
1628}
1629
1630
1631std::vector<BOARD_DESIGN_SETTINGS::VALIDATION_ERROR>
1632BOARD_DESIGN_SETTINGS::ValidateDesignRules( std::optional<EDA_UNITS> aUnits ) const
1633{
1634 std::vector<VALIDATION_ERROR> errors;
1635 EDA_UNITS units = aUnits.value_or( EDA_UNITS::MM );
1636
1637 auto addRangeError =
1638 [&]( const wxString& aField, int aValue, int aMin, int aMax )
1639 {
1640 if( aValue < aMin || aValue > aMax )
1641 {
1642 wxString minValue = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units,
1643 aMin, true );
1644 wxString maxValue = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units,
1645 aMax, true );
1646
1647 errors.push_back( {
1648 aField,
1649 wxString::Format( _( "Value must be between %s and %s." ),
1650 minValue, maxValue )
1651 } );
1652 }
1653 };
1654
1655 auto addRatioRangeError =
1656 [&]( const wxString& aField, double aValue, double aMin, double aMax )
1657 {
1658 if( !std::isfinite( aValue ) || aValue < aMin || aValue > aMax )
1659 {
1660 errors.push_back( {
1661 aField,
1662 wxString::Format( _( "Value must be between %.3f and %.3f." ),
1663 aMin, aMax )
1664 } );
1665 }
1666 };
1667
1668 addRangeError( wxS( "min_clearance" ), m_MinClearance,
1669 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1670 addRangeError( wxS( "min_connection" ), m_MinConn,
1671 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ) );
1672 addRangeError( wxS( "min_track_width" ), m_TrackMinWidth,
1673 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1674 addRangeError( wxS( "min_via_annular_width" ), m_ViasMinAnnularWidth,
1675 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1676 addRangeError( wxS( "min_via_diameter" ), m_ViasMinSize,
1677 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1678 addRangeError( wxS( "min_through_hole_diameter" ), m_MinThroughDrill,
1679 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1680 addRangeError( wxS( "min_microvia_diameter" ), m_MicroViasMinSize,
1681 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ) );
1682 addRangeError( wxS( "min_microvia_drill" ), m_MicroViasMinDrill,
1683 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ) );
1684 addRangeError( wxS( "min_hole_to_hole" ), m_HoleToHoleMin,
1685 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ) );
1686 addRangeError( wxS( "min_hole_clearance" ), m_HoleClearance,
1687 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ) );
1688 addRangeError( wxS( "min_silk_clearance" ), m_SilkClearance,
1689 pcbIUScale.mmToIU( -10.0 ), pcbIUScale.mmToIU( 100.0 ) );
1690 addRangeError( wxS( "min_groove_width" ), m_MinGrooveWidth,
1691 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1692 addRangeError( wxS( "min_text_height" ), m_MinSilkTextHeight,
1693 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ) );
1694 addRangeError( wxS( "min_text_thickness" ), m_MinSilkTextThickness,
1695 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1696 addRangeError( wxS( "min_copper_edge_clearance" ), m_CopperEdgeClearance,
1697 pcbIUScale.mmToIU( -0.01 ), pcbIUScale.mmToIU( 25.0 ) );
1698
1700 {
1701 errors.push_back( {
1702 wxS( "min_resolved_spokes" ),
1703 _( "Value must be between 0 and 99." )
1704 } );
1705 }
1706
1707 addRangeError( wxS( "max_error" ), m_MaxError,
1710
1711 addRangeError( wxS( "solder_mask_expansion" ), m_SolderMaskExpansion,
1712 pcbIUScale.mmToIU( -25.0 ), pcbIUScale.mmToIU( 25.0 ) );
1713 addRangeError( wxS( "solder_mask_min_width" ), m_SolderMaskMinWidth,
1714 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ) );
1715 addRangeError( wxS( "solder_mask_to_copper_clearance" ), m_SolderMaskToCopperClearance,
1716 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ) );
1717 addRangeError( wxS( "solder_paste_margin" ), m_SolderPasteMargin,
1718 pcbIUScale.mmToIU( -25.0 ), pcbIUScale.mmToIU( 25.0 ) );
1719 addRatioRangeError( wxS( "solder_paste_margin_ratio" ), m_SolderPasteMarginRatio,
1720 -1.0, 1.0 );
1721
1722 TEARDROP_PARAMETERS_LIST& teardropParamsList =
1724
1725 for( size_t ii = 0; ii < teardropParamsList.GetParametersCount(); ++ii )
1726 {
1727 const TEARDROP_PARAMETERS* params = teardropParamsList.GetParameters( static_cast<TARGET_TD>( ii ) );
1728 std::string target = GetTeardropTargetCanonicalName( static_cast<TARGET_TD>( ii ) );
1729
1730 if( params->m_TdMaxLen < 0 )
1731 {
1732 errors.push_back( {
1733 wxString::Format( wxS( "teardrop_parameters[%s].max_length" ), target ),
1734 _( "Value must be greater than or equal to 0." )
1735 } );
1736 }
1737
1738 if( params->m_TdMaxWidth < 0 )
1739 {
1740 errors.push_back( {
1741 wxString::Format( wxS( "teardrop_parameters[%s].max_width" ), target ),
1742 _( "Value must be greater than or equal to 0." )
1743 } );
1744 }
1745
1746 addRatioRangeError( wxString::Format( wxS( "teardrop_parameters[%s].best_length_ratio" ), target ),
1747 params->m_BestLengthRatio, 0.0, 1.0 );
1748 addRatioRangeError( wxString::Format( wxS( "teardrop_parameters[%s].best_width_ratio" ), target ),
1749 params->m_BestWidthRatio, 0.0, 1.0 );
1750 addRatioRangeError( wxString::Format( wxS( "teardrop_parameters[%s].width_to_size_filter_ratio" ),
1751 target ),
1752 params->m_WidthtoSizeFilterRatio, 0.0, 1.0 );
1753 }
1754
1755 for( size_t ii = 1; ii < m_DiffPairDimensionsList.size(); ++ii )
1756 {
1757 const DIFF_PAIR_DIMENSION& diffPair = m_DiffPairDimensionsList[ii];
1758
1759 if( diffPair.m_Width > 0 && diffPair.m_Gap <= 0 )
1760 {
1761 errors.push_back( {
1762 wxString::Format( wxS( "diff_pair_dimensions_list[%zu].gap" ), ii ),
1763 _( "No differential pair gap defined." )
1764 } );
1765 }
1766 }
1767
1768 for( size_t ii = 1; ii < m_ViasDimensionsList.size(); ++ii )
1769 {
1770 const VIA_DIMENSION& viaDim = m_ViasDimensionsList[ii];
1771
1772 std::optional<int> viaDiameter;
1773 std::optional<int> viaDrill;
1774
1775 if( viaDim.m_Diameter > 0 )
1776 viaDiameter = viaDim.m_Diameter;
1777
1778 if( viaDim.m_Drill > 0 )
1779 viaDrill = viaDim.m_Drill;
1780
1781 if( std::optional<PCB_VIA::VIA_PARAMETER_ERROR> error =
1782 PCB_VIA::ValidateViaParameters( viaDiameter, viaDrill ) )
1783 {
1784 errors.push_back( {
1785 wxString::Format( wxS( "via_dimensions_list[%zu]" ), ii ),
1786 error->m_Message
1787 } );
1788 }
1789 }
1790
1791 return errors;
1792}
1793
1794
1796{
1797 int biggest = std::max( m_MinClearance, m_HoleClearance );
1798 DRC_CONSTRAINT constraint;
1799
1800 biggest = std::max( biggest, m_HoleToHoleMin );
1801 biggest = std::max( biggest, m_CopperEdgeClearance );
1802
1803 if( m_DRCEngine )
1804 {
1805 m_DRCEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, constraint );
1806 biggest = std::max( biggest, constraint.Value().Min() );
1807
1808 m_DRCEngine->QueryWorstConstraint( PHYSICAL_CLEARANCE_CONSTRAINT, constraint );
1809 biggest = std::max( biggest, constraint.Value().Min() );
1810
1811 m_DRCEngine->QueryWorstConstraint( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, constraint );
1812 biggest = std::max( biggest, constraint.Value().Min() );
1813
1814 m_DRCEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, constraint );
1815 biggest = std::max( biggest, constraint.Value().Min() );
1816
1817 m_DRCEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, constraint );
1818 biggest = std::max( biggest, constraint.Value().Min() );
1819
1820 m_DRCEngine->QueryWorstConstraint( HOLE_TO_HOLE_CONSTRAINT, constraint );
1821 biggest = std::max( biggest, constraint.Value().Min() );
1822 }
1823
1824 // Clip to avoid integer overflows in subsequent calculations
1825 return std::min( biggest, MAXIMUM_CLEARANCE );
1826}
1827
1828
1830{
1831 int clearance = m_NetSettings->GetDefaultNetclass()->GetClearance();
1832
1833 for( const auto& [name, netclass] : m_NetSettings->GetNetclasses() )
1834 {
1835 if( netclass->HasClearance() )
1836 clearance = std::min( clearance, netclass->GetClearance() );
1837 }
1838
1839 return clearance;
1840}
1841
1842
1843// Compute the next index when cycling a predefined-size list whose index 0 is the synthetic
1844// "use netclass" placeholder. Roll-over skips that placeholder when real sizes exist so the
1845// cycle stays monotonic.
1846static int nextPredefinedIndex( int aIndex, bool aForward, int aListSize )
1847{
1848 // Nothing to cycle when the list holds only the netclass placeholder (or is empty).
1849 if( aListSize <= 1 )
1850 return 0;
1851
1852 constexpr int lowestRealIndex = 1;
1853 int next = aIndex + ( aForward ? 1 : -1 );
1854
1855 if( next >= aListSize )
1856 next = lowestRealIndex;
1857 else if( next < lowestRealIndex )
1858 next = aListSize - 1;
1859
1860 return next;
1861}
1862
1863
1865{
1867 ? 0
1868 : std::clamp( aIndex, 0, (int) m_ViasDimensionsList.size() - 1 );
1869 m_useCustomTrackVia = false;
1870}
1871
1872
1873int BOARD_DESIGN_SETTINGS::GetNextViaSizeIndex( int aIndex, bool aForward ) const
1874{
1875 return nextPredefinedIndex( aIndex, aForward, (int) m_ViasDimensionsList.size() );
1876}
1877
1878
1880{
1882 return m_customViaSize.m_Diameter;
1884 return m_NetSettings->GetDefaultNetclass()->GetViaDiameter();
1885 else
1886 return m_ViasDimensionsList[ m_viaSizeIndex ].m_Diameter;
1887}
1888
1889
1891{
1892 int drill;
1893
1895 drill = m_customViaSize.m_Drill;
1897 drill = m_NetSettings->GetDefaultNetclass()->GetViaDrill();
1898 else
1899 drill = m_ViasDimensionsList[ m_viaSizeIndex ].m_Drill;
1900
1901 return drill > 0 ? drill : -1;
1902}
1903
1904
1906{
1908 ? 0
1909 : std::clamp( aIndex, 0, (int) m_TrackWidthList.size() - 1 );
1910 m_useCustomTrackVia = false;
1911}
1912
1913
1914int BOARD_DESIGN_SETTINGS::GetNextTrackWidthIndex( int aIndex, bool aForward ) const
1915{
1916 return nextPredefinedIndex( aIndex, aForward, (int) m_TrackWidthList.size() );
1917}
1918
1919
1921{
1923 return m_customTrackWidth;
1925 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1926 else
1928}
1929
1930
1932{
1934 ? 0
1935 : std::clamp( aIndex, 0, (int) m_DiffPairDimensionsList.size() - 1 );
1936 m_useCustomDiffPair = false;
1937}
1938
1939
1940int BOARD_DESIGN_SETTINGS::GetNextDiffPairIndex( int aIndex, bool aForward ) const
1941{
1942 return nextPredefinedIndex( aIndex, aForward, (int) m_DiffPairDimensionsList.size() );
1943}
1944
1945
1947{
1949 {
1950 return m_customDiffPair.m_Width;
1951 }
1953 {
1954 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairWidth() )
1955 return m_NetSettings->GetDefaultNetclass()->GetDiffPairWidth();
1956 else
1957 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1958 }
1959 else
1960 {
1962 }
1963}
1964
1965
1967{
1969 {
1970 return m_customDiffPair.m_Gap;
1971 }
1973 {
1974 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairGap() )
1975 return m_NetSettings->GetDefaultNetclass()->GetDiffPairGap();
1976 else
1977 return m_NetSettings->GetDefaultNetclass()->GetClearance();
1978 }
1979 else
1980 {
1982 }
1983}
1984
1985
1987{
1989 {
1990 return m_customDiffPair.m_ViaGap;
1991 }
1993 {
1994 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairViaGap() )
1995 return m_NetSettings->GetDefaultNetclass()->GetDiffPairViaGap();
1996 else
1997 return GetCurrentDiffPairGap();
1998 }
1999 else
2000 {
2002 }
2003}
2004
2005
2007{
2008 m_copperLayerCount = aNewLayerCount;
2009
2010 // Update only enabled copper layers mask
2011 m_enabledLayers.ClearCopperLayers();
2012
2013 if( aNewLayerCount > 0 )
2014 m_enabledLayers |= LSET::AllCuMask( aNewLayerCount );
2015}
2016
2017
2019{
2020 m_userDefinedLayerCount = aNewLayerCount;
2021
2022 m_enabledLayers.ClearUserDefinedLayers();
2023
2024 if( aNewLayerCount > 0 )
2025 m_enabledLayers |= LSET::UserDefinedLayersMask( aNewLayerCount );
2026}
2027
2028
2030{
2031 m_enabledLayers = aMask;
2032
2033 // Ensures mandatory back and front layers are always enabled regardless of board file
2034 // configuration.
2035 m_enabledLayers.set( B_Cu ).set( F_Cu )
2036 .set( B_CrtYd ).set( F_CrtYd )
2037 .set( Edge_Cuts )
2038 .set( Margin );
2039
2040 // update layer counts to ensure their consistency with m_EnabledLayers
2041 LSET copperLayers = aMask;
2042 copperLayers.ClearNonCopperLayers();
2043
2044 LSET userLayers = aMask & LSET::UserDefinedLayersMask();
2045
2046 m_copperLayerCount = (int) copperLayers.count();
2047 m_userDefinedLayerCount = (int) userLayers.count();
2048}
2049
2050
2051// Return the layer class index { silk, copper, edges & courtyards, fab, others } of the
2052// given layer.
2054{
2055 if( aLayer == F_SilkS || aLayer == B_SilkS )
2056 return LAYER_CLASS_SILK;
2057 else if( IsCopperLayer( aLayer ) )
2058 return LAYER_CLASS_COPPER;
2059 else if( aLayer == Edge_Cuts )
2060 return LAYER_CLASS_EDGES;
2061 else if( aLayer == F_CrtYd || aLayer == B_CrtYd )
2062 return LAYER_CLASS_COURTYARD;
2063 else if( aLayer == F_Fab || aLayer == B_Fab )
2064 return LAYER_CLASS_FAB;
2065 else
2066 return LAYER_CLASS_OTHERS;
2067}
2068
2069
2071{
2072 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
2073}
2074
2075
2077{
2078 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
2079}
2080
2081
2083{
2084 return m_LineThickness[ GetLayerClass( aLayer ) ];
2085}
2086
2087
2089{
2090 return m_TextSize[ GetLayerClass( aLayer ) ];
2091}
2092
2093
2095{
2096 return m_TextThickness[ GetLayerClass( aLayer ) ];
2097}
2098
2099
2101{
2102 return m_TextItalic[ GetLayerClass( aLayer ) ];
2103}
2104
2105
2107{
2108 return m_TextUpright[ GetLayerClass( aLayer ) ];
2109}
2110
2112{
2113 m_Pad_Master->SetPadstackMode( PADSTACK::MODE::NORMAL );
2115 pcbIUScale.mmToIU( DEFAULT_PAD_HEIGTH_MM ) ) );
2116 m_Pad_Master->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
2117 m_Pad_Master->SetDrillSize( VECTOR2I( pcbIUScale.mmToIU( DEFAULT_PAD_DRILL_DIAMETER_MM ), 0 ) );
2119
2120 constexpr double RR_RADIUS = DEFAULT_PAD_HEIGTH_MM * DEFAULT_PAD_RR_RADIUS_RATIO;
2121 m_Pad_Master->SetRoundRectCornerRadius( PADSTACK::ALL_LAYERS, pcbIUScale.mmToIU( RR_RADIUS ) );
2122
2123 if( m_Pad_Master->GetFrontShape() == PAD_SHAPE::CIRCLE )
2124 m_Pad_Master->SetThermalSpokeAngle( ANGLE_45 );
2125 else
2126 m_Pad_Master->SetThermalSpokeAngle( ANGLE_90 );
2127}
const char * name
constexpr int ARC_HIGH_DEF
Definition base_units.h:137
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
const int bdsSchemaVersion
static int nextPredefinedIndex(int aIndex, bool aForward, int aListSize)
#define DEFAULT_MICROVIASMINDRILL
#define DEFAULT_SOLDERPASTE_CLEARANCE
#define DEFAULT_SOLDERPASTE_RATIO
#define DEFAULT_CUSTOMDPAIRWIDTH
#define DEFAULT_DP_MEANDER_SPACING
@ LAYER_CLASS_OTHERS
@ LAYER_CLASS_FAB
@ LAYER_CLASS_COURTYARD
@ LAYER_CLASS_SILK
@ LAYER_CLASS_COPPER
@ LAYER_CLASS_EDGES
#define DEFAULT_PAD_WIDTH_MM
#define DEFAULT_VIASMINSIZE
#define DEFAULT_PAD_DRILL_DIAMETER_MM
#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_PAD_HEIGTH_MM
#define DEFAULT_DIMENSION_ARROW_LENGTH
#define DEFAULT_TRACKMINWIDTH
#define DEFAULT_MINTHROUGHDRILL
#define DEFAULT_PAD_RR_RADIUS_RATIO
#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_TEXT_SIZE
#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
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 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
bool Ignore(int aDRCErrorCode)
Return true if the DRC error code's severity is SEVERITY_IGNORE.
std::map< std::string, wxString > m_UserLayerNames
std::unique_ptr< PAD > m_Pad_Master
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...
SEVERITY GetSeverity(int aDRCErrorCode)
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:201
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:159
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition drc_item.cpp:444
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:948
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()
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:170
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
Definition padstack.h:179
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
Maximum meandering amplitude.
int m_cornerRadiusPercentage
Place meanders on one side.
bool m_singleSided
Initial side when placing meanders at segment.
MEANDER_STYLE m_cornerStyle
Rounding percentage (0 - 100).
int m_maxAmplitude
Meandering period/spacing (see dialog picture for explanation).
int m_spacing
Amplitude/spacing adjustment step.
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:79
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.
@ DRCE_FOOTPRINT_SCALED_WITH_PADS
Definition drc_item.h:89
@ DRCE_TUNING_PROFILE_IMPLICIT_RULES
Definition drc_item.h:120
@ DRCE_SILK_EDGE_CLEARANCE
Definition drc_item.h:102
@ DRCE_FOOTPRINT_FILTERS
Definition drc_item.h:82
@ DRCE_SILK_MASK_CLEARANCE
Definition drc_item.h:100
@ DRCE_PADSTACK
Definition drc_item.h:60
@ DRCE_MIRRORED_TEXT_ON_FRONT_LAYER
Definition drc_item.h:116
@ DRCE_LIB_FOOTPRINT_ISSUES
Definition drc_item.h:85
@ DRCE_MICROVIA_CROSSES_CORE
Definition drc_item.h:67
@ DRCE_OVERLAPPING_FOOTPRINTS
Definition drc_item.h:68
@ DRCE_SCHEMATIC_FIELDS_PARITY
Definition drc_item.h:126
@ DRCE_MISSING_COURTYARD
Definition drc_item.h:69
@ DRCE_MICROVIA_STACK_NOT_FILLED
Definition drc_item.h:64
@ DRCE_TRACK_NOT_CENTERED_ON_VIA
Definition drc_item.h:124
@ DRCE_ISOLATED_COPPER
Definition drc_item.h:46
@ DRCE_MISSING_TUNING_PROFILE
Definition drc_item.h:119
@ DRCE_DRILLED_HOLES_TOO_CLOSE
Definition drc_item.h:50
@ DRCE_COPPER_SLIVER
Definition drc_item.h:96
@ DRCE_PTH_IN_COURTYARD
Definition drc_item.h:72
@ DRCE_FIRST
Definition drc_item.h:36
@ DRCE_DANGLING_VIA
Definition drc_item.h:48
@ DRCE_FOOTPRINT_TYPE_MISMATCH
Definition drc_item.h:84
@ DRCE_DUPLICATE_FOOTPRINT
Definition drc_item.h:78
@ DRCE_DANGLING_TRACK
Definition drc_item.h:49
@ DRCE_TEXT_HEIGHT
Definition drc_item.h:104
@ DRCE_DRILLED_HOLES_COLOCATED
Definition drc_item.h:51
@ DRCE_EXTRA_FOOTPRINT
Definition drc_item.h:79
@ DRCE_SILK_CLEARANCE
Definition drc_item.h:103
@ DRCE_LAST
Definition drc_item.h:131
@ DRCE_LIB_FOOTPRINT_MISMATCH
Definition drc_item.h:86
@ DRCE_NET_CONFLICT
Definition drc_item.h:80
@ DRCE_MISSING_FOOTPRINT
Definition drc_item.h:77
@ DRCE_UNMIRRORED_TEXT_ON_BACK_LAYER
Definition drc_item.h:117
@ DRCE_TEXT_THICKNESS
Definition drc_item.h:105
@ DRCE_NPTH_IN_COURTYARD
Definition drc_item.h:73
@ DRCE_CONNECTION_WIDTH
Definition drc_item.h:57
@ DRCE_SCHEMATIC_PARITY
Definition drc_item.h:81
@ EDGE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:55
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:83
@ CLEARANCE_CONSTRAINT
Definition drc_rule.h:51
@ HOLE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:53
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition drc_rule.h:82
@ HOLE_TO_HOLE_CONSTRAINT
Definition drc_rule.h:54
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:424
@ DEGREES_T
Definition eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_45
Definition eda_angle.h:423
#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:703
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
@ ROUNDRECT
Definition padstack.h:56
@ 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:56
wxString SeverityToString(const SEVERITY &aSeverity)
Definition ui_common.cpp:67
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
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