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