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 <pcb_dimension.h>
21#include <pcb_track.h>
22#include <algorithm>
23#include <cmath>
24#include <layer_ids.h>
25#include <lset.h>
26#include <kiface_base.h>
27#include <pad.h>
30#include <drc/drc_item.h>
31#include <drc/drc_engine.h>
33#include <settings/parameters.h>
35#include <advanced_config.h>
36
37const int bdsSchemaVersion = 2;
38
39
40BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
41 NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aParent, aPath )
42{
43 // We want to leave alone parameters that aren't found in the project JSON as they may be
44 // initialized by the board file parser before NESTED_SETTINGS::LoadFromFile is called.
46
47 // Create a default NET_SETTINGS so that things don't break horribly if there's no project
48 // loaded. This also is used during file load for legacy boards that have netclasses stored
49 // in the file. After load, this information will be moved to the project and the pointer
50 // updated.
51 m_NetSettings = std::make_shared<NET_SETTINGS>( nullptr, "" );
52
53 m_HasStackup = false; // no stackup defined by default
54
55 m_Pad_Master = std::make_unique<PAD>( nullptr );
57
58 LSET all_set = LSET().set();
59 m_enabledLayers = all_set; // All layers enabled at first.
60 // SetCopperLayerCount() will adjust this.
61
62 // Default design is a double layer board with 4 user defined layers
65
67
68 // if true, when creating a new track starting on an existing track, use this track width
71
72 // First is always the reference designator
73 m_DefaultFPTextItems.emplace_back( wxT( "REF**" ), true, F_SilkS );
74 // Second is always the value
75 m_DefaultFPTextItems.emplace_back( wxT( "" ), true, F_Fab );
76 // Any following ones are freebies
77 m_DefaultFPTextItems.emplace_back( wxT( "${REFERENCE}" ), true, F_Fab );
78
85
92
93 // Edges & Courtyards; text properties aren't used but better to have them holding
94 // reasonable values than not.
97 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
101
104 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
108
111 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
113 m_TextItalic[ LAYER_CLASS_FAB ] = false;
115
118 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
122
123 m_StyleFPFields = false;
124 m_StyleFPText = false;
125 m_StyleFPShapes = false;
126 m_StyleFPDimensions = false;
127 m_StyleFPBarcodes = false;
128
137
138 m_useCustomTrackVia = false;
140 m_customViaSize.m_Diameter = pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE );
142
143 m_useCustomDiffPair = false;
147
164
165 for( int errorCode = DRCE_FIRST; errorCode <= DRCE_LAST; ++errorCode )
166 m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
167
170
174
177
180
183
191
197
199
202
204
207
210
212
216
217 // Global mask margins:
221
222 // Solder paste margin absolute value
224 // Solder paste margin as a ratio of pad size
225 // The final margin is the sum of these 2 values
226 // Usually < 0 because the mask is smaller than pad
228
230 m_TentViasFront = true;
231 m_TentViasBack = true;
232
233 m_CoverViasFront = false;
234 m_CoverViasBack = false;
235
236 m_PlugViasFront = false;
237 m_PlugViasBack = false;
238
239 m_CapVias = false;
240
241 m_FillVias = false;
242
243 // Layer thickness for 3D viewer
245
246 // Default spacing for meanders
250
251 m_viaSizeIndex = 0;
253 m_diffPairIndex = 0;
254
255 // Parameters stored in JSON in the project file
256
257 // NOTE: Previously, BOARD_DESIGN_SETTINGS stored the basic board layer information (layer
258 // names and enable/disable state) in the project file even though this information is also
259 // stored in the board file. This was implemented for importing these settings from another
260 // project. Going forward, the import feature will just import from other board files (since
261 // we could have multi-board projects in the future anyway) so this functionality is dropped.
262
263
264 m_params.emplace_back( new PARAM<bool>( "rules.use_height_for_length_calcs",
265 &m_UseHeightForLengthCalcs, true ) );
266
267 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_clearance",
269 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
270
271 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_connection",
273 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
274
275 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_track_width",
277 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
278
279 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_annular_width",
281 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
282
283 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_diameter",
285 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
286
287 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_through_hole_diameter",
289 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
290
291 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_diameter",
293 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), pcbIUScale.MM_PER_IU ) );
294
295 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_drill",
297 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), pcbIUScale.MM_PER_IU ) );
298
299 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_to_hole",
301 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), pcbIUScale.MM_PER_IU ) );
302
303 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_clearance",
305 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
306
307 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_silk_clearance",
309 pcbIUScale.mmToIU( -10.0 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
310
311 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_groove_width",
313 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
314
315 // While the maximum *effective* value is 4, we've had users interpret this as the count on
316 // all layers, and enter something like 10. They'll figure it out soon enough *unless* we
317 // enforce a max of 4 (and therefore reset it back to the default of 2), at which point it
318 // just looks buggy.
319 m_params.emplace_back( new PARAM<int>( "rules.min_resolved_spokes",
321
322 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_height",
324 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
325
326 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_thickness",
328 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
329
330 // Note: a clearance of -0.01 is a flag indicating we should use the legacy (pre-6.0) method
331 // based on the edge cut thicknesses.
332 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_copper_edge_clearance",
334 pcbIUScale.mmToIU( -0.01 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
335
336 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
337 [&]() -> nlohmann::json
338 {
339 nlohmann::json ret = {};
340
341 for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
342 {
343 wxString name = item.GetSettingsKey();
344 int code = item.GetErrorCode();
345
346 if( name.IsEmpty() || m_DRCSeverities.count( code ) == 0 )
347 continue;
348
349 ret[std::string( name.ToUTF8() )] = SeverityToString( m_DRCSeverities[code] );
350 }
351
352 return ret;
353 },
354 [&]( const nlohmann::json& aJson )
355 {
356 if( !aJson.is_object() )
357 return;
358
359 // Load V8 'hole_near_hole' token first (if present). Any current 'hole_to_hole' token
360 // found will then overwrite it.
361 // We can't use the migration architecture because we forgot to bump the version number
362 // when the change was made. But this is a one-off as any future deprecations should
363 // bump the version number and use registerMigration().
364 if( aJson.contains( "hole_near_hole" ) )
366
367 for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
368 {
369 wxString name = item.GetSettingsKey();
370 std::string key( name.ToUTF8() );
371
372 if( aJson.contains( key ) )
373 m_DRCSeverities[item.GetErrorCode()] = SeverityFromString( aJson[key] );
374 }
375 }, {} ) );
376
377 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "drc_exclusions",
378 [&]() -> nlohmann::json
379 {
380 nlohmann::json js = nlohmann::json::array();
381
382 for( const wxString& entry : m_DrcExclusions )
383 js.push_back( { entry, m_DrcExclusionComments[ entry ] } );
384
385 return js;
386 },
387 [&]( const nlohmann::json& aObj )
388 {
389 m_DrcExclusions.clear();
390
391 if( !aObj.is_array() )
392 return;
393
394 for( const nlohmann::json& entry : aObj )
395 {
396 if( entry.is_array() )
397 {
398 wxString serialized = entry[0].get<wxString>();
399 m_DrcExclusions.insert( serialized );
400 m_DrcExclusionComments[ serialized ] = entry[1].get<wxString>();
401 }
402 else if( entry.is_string() )
403 {
404 m_DrcExclusions.insert( entry.get<wxString>() );
405 }
406 }
407 },
408 {} ) );
409
410 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "track_widths",
411 [&]() -> nlohmann::json
412 {
413 nlohmann::json js = nlohmann::json::array();
414
415 for( const int& width : m_TrackWidthList )
416 js.push_back( pcbIUScale.IUTomm( width ) );
417
418 return js;
419 },
420 [&]( const nlohmann::json& aJson )
421 {
422 if( !aJson.is_array() )
423 return;
424
425 m_TrackWidthList.clear();
426
427 for( const nlohmann::json& entry : aJson )
428 {
429 if( entry.empty() )
430 continue;
431
432 m_TrackWidthList.emplace_back( pcbIUScale.mmToIU( entry.get<double>() ) );
433 }
434 },
435 {} ) );
436
437 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "via_dimensions",
438 [&]() -> nlohmann::json
439 {
440 nlohmann::json js = nlohmann::json::array();
441
442 for( const auto& via : m_ViasDimensionsList )
443 {
444 nlohmann::json entry = {};
445
446 entry["diameter"] = pcbIUScale.IUTomm( via.m_Diameter );
447 entry["drill"] = pcbIUScale.IUTomm( via.m_Drill );
448
449 js.push_back( entry );
450 }
451
452 return js;
453 },
454 [&]( const nlohmann::json& aObj )
455 {
456 if( !aObj.is_array() )
457 return;
458
459 m_ViasDimensionsList.clear();
460
461 for( const nlohmann::json& entry : aObj )
462 {
463 if( entry.empty() || !entry.is_object() )
464 continue;
465
466 if( !entry.contains( "diameter" ) || !entry.contains( "drill" ) )
467 continue;
468
469 int diameter = pcbIUScale.mmToIU( entry["diameter"].get<double>() );
470 int drill = pcbIUScale.mmToIU( entry["drill"].get<double>() );
471
472 m_ViasDimensionsList.emplace_back( VIA_DIMENSION( diameter, drill ) );
473 }
474 },
475 {} ) );
476
477 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "diff_pair_dimensions",
478 [&]() -> nlohmann::json
479 {
480 nlohmann::json js = nlohmann::json::array();
481
482 for( const auto& pair : m_DiffPairDimensionsList )
483 {
484 nlohmann::json entry = {};
485
486 entry["width"] = pcbIUScale.IUTomm( pair.m_Width );
487 entry["gap"] = pcbIUScale.IUTomm( pair.m_Gap );
488 entry["via_gap"] = pcbIUScale.IUTomm( pair.m_ViaGap );
489
490 js.push_back( entry );
491 }
492
493 return js;
494 },
495 [&]( const nlohmann::json& aObj )
496 {
497 if( !aObj.is_array() )
498 return;
499
501
502 for( const nlohmann::json& entry : aObj )
503 {
504 if( entry.empty() || !entry.is_object() )
505 continue;
506
507 if( !entry.contains( "width" )
508 || !entry.contains( "gap" )
509 || !entry.contains( "via_gap" ) )
510 {
511 continue;
512 }
513
514 int width = pcbIUScale.mmToIU( entry["width"].get<double>() );
515 int gap = pcbIUScale.mmToIU( entry["gap"].get<double>() );
516 int via_gap = pcbIUScale.mmToIU( entry["via_gap"].get<double>() );
517
518 m_DiffPairDimensionsList.emplace_back( DIFF_PAIR_DIMENSION( width, gap, via_gap ) );
519 }
520 },
521 {} ) );
522
523 // Handle options for teardrops (targets and some others):
524 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_options",
525 [&]() -> nlohmann::json
526 {
527 nlohmann::json js = nlohmann::json::array();
528 nlohmann::json entry = {};
529
530 entry["td_onvia"] = m_TeardropParamsList.m_TargetVias;
531 entry["td_onpthpad"] = m_TeardropParamsList.m_TargetPTHPads;
532 entry["td_onsmdpad"] = m_TeardropParamsList.m_TargetSMDPads;
533 entry["td_ontrackend"] = m_TeardropParamsList.m_TargetTrack2Track;
534 entry["td_onroundshapesonly"] = m_TeardropParamsList.m_UseRoundShapesOnly;
535
536 js.push_back( entry );
537
538 return js;
539 },
540 [&]( const nlohmann::json& aObj )
541 {
542 if( !aObj.is_array() )
543 return;
544
545 for( const nlohmann::json& entry : aObj )
546 {
547 if( entry.empty() || !entry.is_object() )
548 continue;
549
550 if( entry.contains( "td_onvia" ) )
551 m_TeardropParamsList.m_TargetVias = entry["td_onvia"].get<bool>();
552
553 if( entry.contains( "td_onpthpad" ) )
554 m_TeardropParamsList.m_TargetPTHPads = entry["td_onpthpad"].get<bool>();
555
556 if( entry.contains( "td_onsmdpad" ) )
557 m_TeardropParamsList.m_TargetSMDPads = entry["td_onsmdpad"].get<bool>();
558
559 if( entry.contains( "td_ontrackend" ) )
560 m_TeardropParamsList.m_TargetTrack2Track = entry["td_ontrackend"].get<bool>();
561
562 if( entry.contains( "td_onroundshapesonly" ) )
563 m_TeardropParamsList.m_UseRoundShapesOnly = entry["td_onroundshapesonly"].get<bool>();
564
565 // Legacy settings
566 for( int ii = 0; ii < 3; ++ii )
567 {
568 TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)ii );
569
570 if( entry.contains( "td_allow_use_two_tracks" ) )
571 td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
572
573 if( entry.contains( "td_curve_segcount" ) )
574 {
575 if( entry["td_curve_segcount"].get<int>() > 0 )
576 td_prm->m_CurvedEdges = true;
577 }
578
579 if( entry.contains( "td_on_pad_in_zone" ) )
580 td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
581 }
582 }
583 },
584 {} ) );
585
586 // Handle parameters (sizes, shape) for each type of teardrop:
587 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_parameters",
588 [&]() -> nlohmann::json
589 {
590 nlohmann::json js = nlohmann::json::array();
591
592 for( size_t ii = 0; ii < m_TeardropParamsList.GetParametersCount(); ii++ )
593 {
594 nlohmann::json entry = {};
595 TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)ii );
596
597 entry["td_target_name"] = GetTeardropTargetCanonicalName( (TARGET_TD)ii );
598 entry["td_maxlen"] = pcbIUScale.IUTomm( td_prm->m_TdMaxLen );
599 entry["td_maxheight"] = pcbIUScale.IUTomm( td_prm->m_TdMaxWidth );
600 entry["td_length_ratio"] = td_prm->m_BestLengthRatio;
601 entry["td_height_ratio"] = td_prm->m_BestWidthRatio;
602 entry["td_curve_segcount"] = td_prm->m_CurvedEdges ? 1 : 0;
603 entry["td_width_to_size_filter_ratio"] = td_prm->m_WidthtoSizeFilterRatio;
604 entry["td_allow_use_two_tracks"] = td_prm->m_AllowUseTwoTracks;
605 entry["td_on_pad_in_zone"] = td_prm->m_TdOnPadsInZones;
606
607 js.push_back( entry );
608 }
609
610 return js;
611 },
612 [&]( const nlohmann::json& aObj )
613 {
614 if( !aObj.is_array() )
615 return;
616
617 for( const nlohmann::json& entry : aObj )
618 {
619 if( entry.empty() || !entry.is_object() )
620 continue;
621
622 if( !entry.contains( "td_target_name" ) )
623 continue;
624
625 int idx = GetTeardropTargetTypeFromCanonicalName( entry["td_target_name"].get<std::string>() );
626
627 if( idx >= 0 && idx < 3 )
628 {
629 TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)idx );
630
631 if( entry.contains( "td_maxlen" ) )
632 td_prm->m_TdMaxLen = pcbIUScale.mmToIU( entry["td_maxlen"].get<double>() );
633
634 if( entry.contains( "td_maxheight" ) )
635 td_prm->m_TdMaxWidth = pcbIUScale.mmToIU( entry["td_maxheight"].get<double>() );
636
637 if( entry.contains( "td_length_ratio" ) )
638 td_prm->m_BestLengthRatio = entry["td_length_ratio"].get<double>();
639
640 if( entry.contains( "td_height_ratio" ) )
641 td_prm->m_BestWidthRatio = entry["td_height_ratio"].get<double>();
642
643 if( entry.contains( "td_curve_segcount" ) )
644 {
645 if( entry["td_curve_segcount"].get<int>() > 0 )
646 td_prm->m_CurvedEdges = true;
647 }
648
649 if( entry.contains( "td_width_to_size_filter_ratio" ) )
650 td_prm->m_WidthtoSizeFilterRatio = entry["td_width_to_size_filter_ratio"].get<double>();
651
652 if( entry.contains( "td_allow_use_two_tracks" ) )
653 td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
654
655 if( entry.contains( "td_on_pad_in_zone" ) )
656 td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
657 }
658 }
659 },
660 {} ) );
661
662 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "tuning_pattern_settings",
663 [&]() -> nlohmann::json
664 {
665 nlohmann::json js = {};
666
667 auto make_settings =
668 []( const PNS::MEANDER_SETTINGS& aSettings )
669 {
670 nlohmann::json entry = {};
671
672 entry["min_amplitude"] = pcbIUScale.IUTomm( aSettings.m_minAmplitude );
673 entry["max_amplitude"] = pcbIUScale.IUTomm( aSettings.m_maxAmplitude );
674 entry["spacing"] = pcbIUScale.IUTomm( aSettings.m_spacing );
675 entry["corner_style"] = aSettings.m_cornerStyle == PNS::MEANDER_STYLE_CHAMFER ? 0 : 1;
676 entry["corner_radius_percentage"] = aSettings.m_cornerRadiusPercentage;
677 entry["single_sided"] = aSettings.m_singleSided;
678
679 return entry;
680 };
681
682 js["single_track_defaults"] = make_settings( m_SingleTrackMeanderSettings );
683 js["diff_pair_defaults"] = make_settings( m_DiffPairMeanderSettings );
684 js["diff_pair_skew_defaults"] = make_settings( m_SkewMeanderSettings );
685
686 return js;
687 },
688 [&]( const nlohmann::json& aObj )
689 {
690 auto read_settings =
691 []( const nlohmann::json& entry ) -> PNS::MEANDER_SETTINGS
692 {
693 PNS::MEANDER_SETTINGS settings;
694
695 if( entry.contains( "min_amplitude" ) )
696 settings.m_minAmplitude = pcbIUScale.mmToIU( entry["min_amplitude"].get<double>() );
697
698 if( entry.contains( "max_amplitude" ) )
699 settings.m_maxAmplitude = pcbIUScale.mmToIU( entry["max_amplitude"].get<double>() );
700
701 if( entry.contains( "spacing" ) )
702 settings.m_spacing = pcbIUScale.mmToIU( entry["spacing"].get<double>() );
703
704 if( entry.contains( "corner_style" ) )
705 {
706 settings.m_cornerStyle = entry["corner_style"] == 0 ? PNS::MEANDER_STYLE_CHAMFER
708 }
709
710 if( entry.contains( "corner_radius_percentage" ) )
711 settings.m_cornerRadiusPercentage = entry["corner_radius_percentage"].get<int>();
712
713 if( entry.contains( "single_sided" ) )
714 settings.m_singleSided = entry["single_sided"].get<bool>();
715
716 return settings;
717 };
718
719 if( aObj.contains( "single_track_defaults" ) )
720 m_SingleTrackMeanderSettings = read_settings( aObj["single_track_defaults"] );
721
722 if( aObj.contains( "diff_pair_defaults" ) )
723 m_DiffPairMeanderSettings = read_settings( aObj["diff_pair_defaults"] );
724
725 if( aObj.contains( "diff_pair_skew_defaults" ) )
726 m_SkewMeanderSettings = read_settings( aObj["diff_pair_skew_defaults"] );
727 },
728 {} ) );
729
730 int minTextSize = pcbIUScale.mmToIU( TEXT_MIN_SIZE_MM );
731 int maxTextSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
732 int minStroke = 1;
733 int maxStroke = pcbIUScale.mmToIU( 100 );
734
735 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_line_width",
737 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
738
739 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_v",
741 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
742
743 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_h",
745 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
746
747 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_thickness",
749 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
750
751 m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_italic",
752 &m_TextItalic[LAYER_CLASS_SILK], false ) );
753
754 m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_upright",
755 &m_TextUpright[ LAYER_CLASS_SILK ], true ) );
756
757 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_line_width",
759 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
760
761 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_v",
763 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
764
765 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_h",
767 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
768
769 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_thickness",
771 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
772
773 m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_italic",
774 &m_TextItalic[LAYER_CLASS_COPPER], false ) );
775
776 m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_upright",
778
779 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.board_outline_line_width",
781 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
782
783 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.courtyard_line_width",
785 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
786
787 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_line_width",
789 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
790
791 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_v",
793 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
794
795 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_h",
797 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
798
799 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_thickness",
801 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
802
803 m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_italic",
804 &m_TextItalic[LAYER_CLASS_FAB], false ) );
805
806 m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_upright",
807 &m_TextUpright[LAYER_CLASS_FAB], true ) );
808
809 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_line_width",
811 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
812
813 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_v",
815 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
816
817 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_h",
819 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
820
821 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_thickness",
823 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
824
825 m_params.emplace_back( new PARAM<bool>( "defaults.other_text_italic",
826 &m_TextItalic[LAYER_CLASS_OTHERS], false ) );
827
828 m_params.emplace_back( new PARAM<bool>( "defaults.other_text_upright",
830
831 m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_MODE>( "defaults.dimension_units",
834
835 m_params.emplace_back( new PARAM_ENUM<DIM_PRECISION>( "defaults.dimension_precision",
837
838 m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_FORMAT>( "defaults.dimensions.units_format",
841
842 m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.suppress_zeroes",
843 &m_DimensionSuppressZeroes, true ) );
844
845 // NOTE: excluding DIM_TEXT_POSITION::MANUAL from the valid range here
846 m_params.emplace_back( new PARAM_ENUM<DIM_TEXT_POSITION>( "defaults.dimensions.text_position",
849
850 m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.keep_text_aligned",
852
853 m_params.emplace_back( new PARAM<int>( "defaults.dimensions.arrow_length",
856
857 m_params.emplace_back( new PARAM<int>( "defaults.dimensions.extension_offset",
860
861 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_fields",
862 &m_StyleFPFields, false ) );
863 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_text",
864 &m_StyleFPText, false ) );
865 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_shapes",
866 &m_StyleFPShapes, false ) );
867 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_dimensions",
868 &m_StyleFPDimensions, false ) );
869 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_barcodes",
870 &m_StyleFPBarcodes, false ) );
871
872 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.zones.min_clearance",
873 &m_defaultZoneSettings.m_ZoneClearance, pcbIUScale.mmToIU( ZONE_CLEARANCE_MM ),
874 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
875
876 m_params.emplace_back( new PARAM_SCALED<int>(
877 "defaults.zones.min_thickness", &m_defaultZoneSettings.m_ZoneMinThickness,
879 pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
880
881 m_params.emplace_back( new PARAM_ENUM<ZONE_FILL_MODE>( "defaults.zones.fill_mode",
885
886 m_params.emplace_back(
887 new PARAM_SCALED<int>( "defaults.zones.hatch_thickness", &m_defaultZoneSettings.m_HatchThickness,
888 std::max( pcbIUScale.mmToIU( ZONE_THICKNESS_MM ) * 4, pcbIUScale.mmToIU( 1.0 ) ),
889 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
890
891 m_params.emplace_back(
892 new PARAM_SCALED<int>( "defaults.zones.hatch_gap", &m_defaultZoneSettings.m_HatchGap,
893 std::max( pcbIUScale.mmToIU( ZONE_THICKNESS_MM ) * 6, pcbIUScale.mmToIU( 1.5 ) ),
894 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
895
896 m_params.emplace_back( new PARAM_LAMBDA<double>(
897 "defaults.zones.hatch_orientation",
898 [&]() -> double
899 {
900 return m_defaultZoneSettings.m_HatchOrientation.AsDegrees();
901 },
902 [&]( double aVal )
903 {
904 m_defaultZoneSettings.m_HatchOrientation = EDA_ANGLE( aVal, DEGREES_T );
905 },
906 0.0 ) );
907
908 m_params.emplace_back( new PARAM<int>( "defaults.zones.hatch_smoothing_level",
909 &m_defaultZoneSettings.m_HatchSmoothingLevel, 0, 0, 2 ) );
910
911 m_params.emplace_back( new PARAM<double>( "defaults.zones.hatch_smoothing_value",
912 &m_defaultZoneSettings.m_HatchSmoothingValue, 0.1, 0.0, 1.0 ) );
913
915 "defaults.zones.border_display_style", &m_defaultZoneSettings.m_ZoneBorderDisplayStyle,
918
919 m_params.emplace_back( new PARAM_SCALED<int>(
920 "defaults.zones.border_hatch_pitch", &m_defaultZoneSettings.m_BorderHatchPitch,
922 pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MAXDIST_MM ), pcbIUScale.MM_PER_IU ) );
923
924 m_params.emplace_back(
925 new PARAM_SCALED<long>( "defaults.zones.thermal_relief_gap", &m_defaultZoneSettings.m_ThermalReliefGap,
926 pcbIUScale.mmToIU( ZONE_THERMAL_RELIEF_GAP_MM ), pcbIUScale.mmToIU( 0.0 ),
927 pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
928
929 m_params.emplace_back( new PARAM_SCALED<long>(
930 "defaults.zones.thermal_relief_spoke_width", &m_defaultZoneSettings.m_ThermalReliefSpokeWidth,
932 pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
933
934 m_params.emplace_back( new PARAM_LAMBDA<int>(
935 "defaults.zones.pad_connection",
936 [&]() -> int
937 {
938 return static_cast<int>( m_defaultZoneSettings.GetPadConnection() );
939 },
940 [&]( int aVal )
941 {
942 m_defaultZoneSettings.SetPadConnection( static_cast<ZONE_CONNECTION>( aVal ) );
943 },
944 static_cast<int>( ZONE_CONNECTION::THERMAL ) ) );
945
946 m_params.emplace_back( new PARAM_LAMBDA<int>(
947 "defaults.zones.corner_smoothing",
948 [&]() -> int
949 {
950 return m_defaultZoneSettings.GetCornerSmoothingType();
951 },
952 [&]( int aVal )
953 {
954 m_defaultZoneSettings.SetCornerSmoothingType( aVal );
955 },
957
958 m_params.emplace_back( new PARAM_LAMBDA<double>(
959 "defaults.zones.corner_radius",
960 [&]() -> double
961 {
962 return pcbIUScale.IUTomm( m_defaultZoneSettings.GetCornerRadius() );
963 },
964 [&]( double aVal )
965 {
966 m_defaultZoneSettings.SetCornerRadius( pcbIUScale.mmToIU( aVal ) );
967 },
968 0.0 ) );
969
970 m_params.emplace_back( new PARAM_LAMBDA<int>(
971 "defaults.zones.remove_islands",
972 [&]() -> int
973 {
974 return static_cast<int>( m_defaultZoneSettings.GetIslandRemovalMode() );
975 },
976 [&]( int aVal )
977 {
978 m_defaultZoneSettings.SetIslandRemovalMode( static_cast<ISLAND_REMOVAL_MODE>( aVal ) );
979 },
980 static_cast<int>( ISLAND_REMOVAL_MODE::ALWAYS ) ) );
981
982 m_params.emplace_back( new PARAM_LAMBDA<double>(
983 "defaults.zones.min_island_area",
984 [&]() -> double
985 {
986 const double iuPerMm2 = pcbIUScale.IU_PER_MM * pcbIUScale.IU_PER_MM;
987 return static_cast<double>( m_defaultZoneSettings.GetMinIslandArea() ) / iuPerMm2;
988 },
989 [&]( double aVal )
990 {
991 const double iuPerMm2 = pcbIUScale.IU_PER_MM * pcbIUScale.IU_PER_MM;
992 m_defaultZoneSettings.SetMinIslandArea( static_cast<long long int>( aVal * iuPerMm2 ) );
993 },
994 10.0 ) );
995
996 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "defaults.pads",
997 [&]() -> nlohmann::json
998 {
999 nlohmann::json ret =
1000 {
1001 { "width", pcbIUScale.IUTomm( m_Pad_Master->GetSize( PADSTACK::ALL_LAYERS ).x ) },
1002 { "height", pcbIUScale.IUTomm( m_Pad_Master->GetSize( PADSTACK::ALL_LAYERS ).y ) },
1003 { "drill", pcbIUScale.IUTomm( m_Pad_Master->GetDrillSize().x ) }
1004 };
1005
1006 return ret;
1007 },
1008 [&]( const nlohmann::json& aJson )
1009 {
1010 if( aJson.contains( "width" ) && aJson.contains( "height" )
1011 && aJson.contains( "drill" ) )
1012 {
1013 VECTOR2I sz;
1014 sz.x = pcbIUScale.mmToIU( aJson["width"].get<double>() );
1015 sz.y = pcbIUScale.mmToIU( aJson["height"].get<double>() );
1016
1017 m_Pad_Master->SetSize( PADSTACK::ALL_LAYERS, sz );
1018
1019 int drill = pcbIUScale.mmToIU( aJson["drill"].get<double>() );
1020
1021 m_Pad_Master->SetDrillSize( VECTOR2I( drill, drill ) );
1022 }
1023 }, {} ) );
1024
1025 m_params.emplace_back( new PARAM_SCALED<int>( "rules.max_error",
1027 pcbIUScale.mmToIU( 0.0001 ), pcbIUScale.mmToIU( 1.0 ), pcbIUScale.MM_PER_IU ) );
1028
1029 m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_mask_to_copper_clearance",
1031 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1032
1033 m_params.emplace_back( new PARAM<bool>( "zones_allow_external_fillets",
1034 &m_ZoneKeepExternalFillets, false ) );
1035
1037
1038 registerMigration( 1, 2,
1039 [&]() -> bool
1040 {
1041 // Schema 1 to 2: move mask and paste margin settings back to board.
1042 // The parameters are removed, so we just have to manually load them here and
1043 // they will get saved with the board
1044 if( std::optional<double> optval = Get<double>( "rules.solder_mask_clearance" ) )
1045 m_SolderMaskExpansion = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
1046
1047 if( std::optional<double> optval = Get<double>( "rules.solder_mask_min_width" ) )
1048 m_SolderMaskMinWidth = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
1049
1050 if( std::optional<double> optval = Get<double>( "rules.solder_paste_clearance" ) )
1051 m_SolderPasteMargin = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
1052
1053 if( std::optional<double> optval = Get<double>( "rules.solder_paste_margin_ratio" ) )
1054 m_SolderPasteMarginRatio = *optval;
1055
1056 try
1057 {
1058 At( "rules" ).erase( "solder_mask_clearance" );
1059 At( "rules" ).erase( "solder_mask_min_width" );
1060 At( "rules" ).erase( "solder_paste_clearance" );
1061 At( "rules" ).erase( "solder_paste_margin_ratio" );
1062 }
1063 catch( ... )
1064 {}
1065
1066 return true;
1067 } );
1068}
1069
1070
1072{
1073 if( m_parent )
1074 {
1075 m_parent->ReleaseNestedSettings( this );
1076 m_parent = nullptr;
1077 }
1078}
1079
1080
1082 NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aOther.m_parent,
1083 aOther.m_path ),
1084 m_Pad_Master( nullptr )
1085{
1086 initFromOther( aOther );
1087}
1088
1089
1091{
1092 initFromOther( aOther );
1093 return *this;
1094}
1095
1096
1098{
1099 // Copy of NESTED_SETTINGS around is not allowed, so let's just update the params.
1108 m_MinConn = aOther.m_MinConn;
1126 m_MaxError = aOther.m_MaxError;
1139 m_CapVias = aOther.m_CapVias;
1140 m_FillVias = aOther.m_FillVias;
1143
1144 std::copy( std::begin( aOther.m_LineThickness ), std::end( aOther.m_LineThickness ),
1145 std::begin( m_LineThickness ) );
1146
1147 std::copy( std::begin( aOther.m_TextSize ), std::end( aOther.m_TextSize ),
1148 std::begin( m_TextSize ) );
1149
1150 std::copy( std::begin( aOther.m_TextThickness ), std::end( aOther.m_TextThickness ),
1151 std::begin( m_TextThickness ) );
1152
1153 std::copy( std::begin( aOther.m_TextItalic ), std::end( aOther.m_TextItalic ),
1154 std::begin( m_TextItalic ) );
1155
1156 std::copy( std::begin( aOther.m_TextUpright ), std::end( aOther.m_TextUpright ),
1157 std::begin( m_TextUpright ) );
1158
1167
1168 m_auxOrigin = aOther.m_auxOrigin;
1169 m_gridOrigin = aOther.m_gridOrigin;
1170 m_HasStackup = aOther.m_HasStackup;
1172
1186 m_stackup = aOther.m_stackup;
1188 m_Pad_Master = std::make_unique<PAD>( *aOther.m_Pad_Master );
1190
1196}
1197
1198
1200{
1201 if( m_TrackWidthList != aOther.m_TrackWidthList ) return false;
1202 if( m_ViasDimensionsList != aOther.m_ViasDimensionsList ) return false;
1203 if( m_DiffPairDimensionsList != aOther.m_DiffPairDimensionsList ) return false;
1204 if( m_CurrentViaType != aOther.m_CurrentViaType ) return false;
1205 if( m_UseConnectedTrackWidth != aOther.m_UseConnectedTrackWidth ) return false;
1206 if( m_TempOverrideTrackWidth != aOther.m_TempOverrideTrackWidth ) return false;
1207 if( m_MinClearance != aOther.m_MinClearance ) return false;
1208 if( m_MinGrooveWidth != aOther.m_MinGrooveWidth ) return false;
1209 if( m_MinConn != aOther.m_MinConn ) return false;
1210 if( m_TrackMinWidth != aOther.m_TrackMinWidth ) return false;
1211 if( m_ViasMinAnnularWidth != aOther.m_ViasMinAnnularWidth ) return false;
1212 if( m_ViasMinSize != aOther.m_ViasMinSize ) return false;
1213 if( m_MinThroughDrill != aOther.m_MinThroughDrill ) return false;
1214 if( m_MicroViasMinSize != aOther.m_MicroViasMinSize ) return false;
1215 if( m_MicroViasMinDrill != aOther.m_MicroViasMinDrill ) return false;
1216 if( m_CopperEdgeClearance != aOther.m_CopperEdgeClearance ) return false;
1217 if( m_HoleClearance != aOther.m_HoleClearance ) return false;
1218 if( m_HoleToHoleMin != aOther.m_HoleToHoleMin ) return false;
1219 if( m_SilkClearance != aOther.m_SilkClearance ) return false;
1220 if( m_MinResolvedSpokes != aOther.m_MinResolvedSpokes ) return false;
1221 if( m_MinSilkTextHeight != aOther.m_MinSilkTextHeight ) return false;
1222 if( m_MinSilkTextThickness != aOther.m_MinSilkTextThickness ) return false;
1223 if( m_DRCSeverities != aOther.m_DRCSeverities ) return false;
1224 if( m_DrcExclusions != aOther.m_DrcExclusions ) return false;
1225 if( m_DrcExclusionComments != aOther.m_DrcExclusionComments ) return false;
1226 if( m_ZoneKeepExternalFillets != aOther.m_ZoneKeepExternalFillets ) return false;
1227 if( m_MaxError != aOther.m_MaxError ) return false;
1228 if( m_SolderMaskExpansion != aOther.m_SolderMaskExpansion ) return false;
1229 if( m_SolderMaskMinWidth != aOther.m_SolderMaskMinWidth ) return false;
1231 if( m_SolderPasteMargin != aOther.m_SolderPasteMargin ) return false;
1232 if( m_SolderPasteMarginRatio != aOther.m_SolderPasteMarginRatio ) return false;
1234 if( m_TentViasFront != aOther.m_TentViasFront ) return false;
1235 if( m_TentViasBack != aOther.m_TentViasBack ) return false;
1236 if( m_CoverViasFront != aOther.m_CoverViasFront ) return false;
1237 if( m_CoverViasBack != aOther.m_CoverViasBack ) return false;
1238 if( m_PlugViasFront != aOther.m_PlugViasFront ) return false;
1239 if( m_PlugViasBack != aOther.m_PlugViasBack ) return false;
1240 if( m_CapVias != aOther.m_CapVias ) return false;
1241 if( m_FillVias != aOther.m_FillVias ) return false;
1242 if( m_DefaultFPTextItems != aOther.m_DefaultFPTextItems ) return false;
1243 if( m_UserLayerNames != aOther.m_UserLayerNames ) return false;
1244
1245 if( !std::equal( std::begin( m_LineThickness ), std::end( m_LineThickness ),
1246 std::begin( aOther.m_LineThickness ) ) )
1247 return false;
1248
1249 if( !std::equal( std::begin( m_TextSize ), std::end( m_TextSize ),
1250 std::begin( aOther.m_TextSize ) ) )
1251 return false;
1252
1253 if( !std::equal( std::begin( m_TextThickness ), std::end( m_TextThickness ),
1254 std::begin( aOther.m_TextThickness ) ) )
1255 return false;
1256
1257 if( !std::equal( std::begin( m_TextItalic ), std::end( m_TextItalic ),
1258 std::begin( aOther.m_TextItalic ) ) )
1259 return false;
1260
1261 if( !std::equal( std::begin( m_TextUpright ), std::end( m_TextUpright ),
1262 std::begin( aOther.m_TextUpright ) ) )
1263 return false;
1264
1265 if( m_DimensionUnitsMode != aOther.m_DimensionUnitsMode ) return false;
1266 if( m_DimensionPrecision != aOther.m_DimensionPrecision ) return false;
1267 if( m_DimensionUnitsFormat != aOther.m_DimensionUnitsFormat ) return false;
1268 if( m_DimensionSuppressZeroes != aOther.m_DimensionSuppressZeroes ) return false;
1269 if( m_DimensionTextPosition != aOther.m_DimensionTextPosition ) return false;
1270 if( m_DimensionKeepTextAligned != aOther.m_DimensionKeepTextAligned ) return false;
1271 if( m_DimensionArrowLength != aOther.m_DimensionArrowLength ) return false;
1272 if( m_DimensionExtensionOffset != aOther.m_DimensionExtensionOffset ) return false;
1273 if( m_auxOrigin != aOther.m_auxOrigin ) return false;
1274 if( m_gridOrigin != aOther.m_gridOrigin ) return false;
1275 if( m_HasStackup != aOther.m_HasStackup ) return false;
1276 if( m_UseHeightForLengthCalcs != aOther.m_UseHeightForLengthCalcs ) return false;
1277 if( m_trackWidthIndex != aOther.m_trackWidthIndex ) return false;
1278 if( m_viaSizeIndex != aOther.m_viaSizeIndex ) return false;
1279 if( m_diffPairIndex != aOther.m_diffPairIndex ) return false;
1280 if( m_useCustomTrackVia != aOther.m_useCustomTrackVia ) return false;
1281 if( m_customTrackWidth != aOther.m_customTrackWidth ) return false;
1282 if( m_customViaSize != aOther.m_customViaSize ) return false;
1283 if( m_useCustomDiffPair != aOther.m_useCustomDiffPair ) return false;
1284 if( m_customDiffPair != aOther.m_customDiffPair ) return false;
1285 if( m_copperLayerCount != aOther.m_copperLayerCount ) return false;
1286 if( m_userDefinedLayerCount != aOther.m_userDefinedLayerCount ) return false;
1287 if( m_enabledLayers != aOther.m_enabledLayers ) return false;
1288 if( m_boardThickness != aOther.m_boardThickness ) return false;
1289 if( m_currentNetClassName != aOther.m_currentNetClassName ) return false;
1290 if( m_stackup != aOther.m_stackup ) return false;
1291 if( *m_NetSettings != *aOther.m_NetSettings ) return false;
1292 if( *m_Pad_Master != *aOther.m_Pad_Master ) return false;
1293 if( m_defaultZoneSettings != aOther.m_defaultZoneSettings ) return false;
1294
1295 if( m_StyleFPFields != aOther.m_StyleFPFields ) return false;
1296 if( m_StyleFPText != aOther.m_StyleFPText ) return false;
1297 if( m_StyleFPShapes != aOther.m_StyleFPShapes ) return false;
1298 if( m_StyleFPDimensions != aOther.m_StyleFPDimensions ) return false;
1299 if( m_StyleFPBarcodes != aOther.m_StyleFPBarcodes ) return false;
1300
1301 return true;
1302}
1303
1304
1306{
1324 std::string units_ptr( "defaults.dimension_units" );
1325 std::string precision_ptr( "defaults.dimension_precision" );
1326
1327 if( !( Contains( units_ptr )
1328 && Contains( precision_ptr )
1329 && At( units_ptr ).is_number_integer()
1330 && At( precision_ptr ).is_number_integer() ) )
1331 {
1332 // if either is missing or invalid, migration doesn't make sense
1333 return true;
1334 }
1335
1336 int units = *Get<int>( units_ptr );
1337 int precision = *Get<int>( precision_ptr );
1338
1339 // The enum maps directly to precision if the units is mils
1340 int extraDigits = 0;
1341
1342 switch( units )
1343 {
1344 case 0: extraDigits = 3; break;
1345 case 2: extraDigits = 2; break;
1346 default: break;
1347 }
1348
1349 precision += extraDigits;
1350
1351 Set( precision_ptr, precision );
1352
1353 return true;
1354}
1355
1356
1357bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
1358{
1359 bool ret = NESTED_SETTINGS::LoadFromFile( aDirectory );
1360
1361 // A number of things won't have been translated by the PROJECT_FILE migration because of
1362 // descoped objects required to decode this data. So, it will be in the legacy.pcbnew
1363 // section and needs to be pulled out here
1364
1365 PROJECT_FILE* project = dynamic_cast<PROJECT_FILE*>( GetParent() );
1366
1367 if( !project )
1368 return ret;
1369
1370 bool migrated = false;
1371
1372 auto drcName =
1373 []( int aCode ) -> std::string
1374 {
1375 return std::string( DRC_ITEM::Create( aCode )->GetSettingsKey().ToUTF8() );
1376 };
1377
1378 const std::string rs = "rule_severities.";
1379 const std::string no_courtyard_key = "legacy_no_courtyard_defined";
1380 const std::string courtyard_overlap_key = "legacy_courtyards_overlap";
1381
1382 try
1383 {
1384 nlohmann::json& severities =
1385 project->Internals()->at( "/board/design_settings/rule_severities"_json_pointer );
1386
1387 if( severities.contains( no_courtyard_key ) )
1388 {
1389 if( severities[no_courtyard_key].get<bool>() )
1390 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "error" );
1391 else
1392 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "ignore" );
1393
1394 severities.erase( no_courtyard_key );
1395 migrated = true;
1396 }
1397
1398 if( severities.contains( courtyard_overlap_key ) )
1399 {
1400 if( severities[courtyard_overlap_key].get<bool>() )
1401 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "error" );
1402 else
1403 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "ignore" );
1404
1405 severities.erase( courtyard_overlap_key );
1406 migrated = true;
1407 }
1408 }
1409 catch( ... )
1410 {
1411 }
1412
1413 if( Contains( "legacy" ) )
1414 {
1415 // This defaults to false for new boards, but version 5.1.x and prior kept the fillets
1416 // so we do the same for legacy boards.
1418
1419 project->At( "legacy" ).erase( "pcbnew" );
1420 }
1421
1422 // Now that we have everything, we need to load again
1423 if( migrated )
1424 Load();
1425
1426 return ret;
1427}
1428
1429
1431{
1432 return m_DRCSeverities[ aDRCErrorCode ];
1433}
1434
1435
1436bool BOARD_DESIGN_SETTINGS::Ignore( int aDRCErrorCode )
1437{
1438 return m_DRCSeverities[ aDRCErrorCode ] == RPT_SEVERITY_IGNORE;
1439}
1440
1441
1442std::vector<BOARD_DESIGN_SETTINGS::VALIDATION_ERROR>
1443BOARD_DESIGN_SETTINGS::ValidateDesignRules( std::optional<EDA_UNITS> aUnits ) const
1444{
1445 std::vector<VALIDATION_ERROR> errors;
1446 EDA_UNITS units = aUnits.value_or( EDA_UNITS::MM );
1447
1448 auto addRangeError =
1449 [&]( const wxString& aField, int aValue, int aMin, int aMax )
1450 {
1451 if( aValue < aMin || aValue > aMax )
1452 {
1453 wxString minValue = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units,
1454 aMin, true );
1455 wxString maxValue = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units,
1456 aMax, true );
1457
1458 errors.push_back( {
1459 aField,
1460 wxString::Format( _( "Value must be between %s and %s." ),
1461 minValue, maxValue )
1462 } );
1463 }
1464 };
1465
1466 auto addRatioRangeError =
1467 [&]( const wxString& aField, double aValue, double aMin, double aMax )
1468 {
1469 if( !std::isfinite( aValue ) || aValue < aMin || aValue > aMax )
1470 {
1471 errors.push_back( {
1472 aField,
1473 wxString::Format( _( "Value must be between %.3f and %.3f." ),
1474 aMin, aMax )
1475 } );
1476 }
1477 };
1478
1479 addRangeError( wxS( "min_clearance" ), m_MinClearance,
1480 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1481 addRangeError( wxS( "min_connection" ), m_MinConn,
1482 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ) );
1483 addRangeError( wxS( "min_track_width" ), m_TrackMinWidth,
1484 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1485 addRangeError( wxS( "min_via_annular_width" ), m_ViasMinAnnularWidth,
1486 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1487 addRangeError( wxS( "min_via_diameter" ), m_ViasMinSize,
1488 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1489 addRangeError( wxS( "min_through_hole_diameter" ), m_MinThroughDrill,
1490 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1491 addRangeError( wxS( "min_microvia_diameter" ), m_MicroViasMinSize,
1492 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ) );
1493 addRangeError( wxS( "min_microvia_drill" ), m_MicroViasMinDrill,
1494 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ) );
1495 addRangeError( wxS( "min_hole_to_hole" ), m_HoleToHoleMin,
1496 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ) );
1497 addRangeError( wxS( "min_hole_clearance" ), m_HoleClearance,
1498 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ) );
1499 addRangeError( wxS( "min_silk_clearance" ), m_SilkClearance,
1500 pcbIUScale.mmToIU( -10.0 ), pcbIUScale.mmToIU( 100.0 ) );
1501 addRangeError( wxS( "min_groove_width" ), m_MinGrooveWidth,
1502 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1503 addRangeError( wxS( "min_text_height" ), m_MinSilkTextHeight,
1504 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ) );
1505 addRangeError( wxS( "min_text_thickness" ), m_MinSilkTextThickness,
1506 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1507 addRangeError( wxS( "min_copper_edge_clearance" ), m_CopperEdgeClearance,
1508 pcbIUScale.mmToIU( -0.01 ), pcbIUScale.mmToIU( 25.0 ) );
1509
1511 {
1512 errors.push_back( {
1513 wxS( "min_resolved_spokes" ),
1514 _( "Value must be between 0 and 99." )
1515 } );
1516 }
1517
1518 addRangeError( wxS( "max_error" ), m_MaxError,
1521
1522 addRangeError( wxS( "solder_mask_expansion" ), m_SolderMaskExpansion,
1523 pcbIUScale.mmToIU( -25.0 ), pcbIUScale.mmToIU( 25.0 ) );
1524 addRangeError( wxS( "solder_mask_min_width" ), m_SolderMaskMinWidth,
1525 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ) );
1526 addRangeError( wxS( "solder_mask_to_copper_clearance" ), m_SolderMaskToCopperClearance,
1527 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ) );
1528 addRangeError( wxS( "solder_paste_margin" ), m_SolderPasteMargin,
1529 pcbIUScale.mmToIU( -25.0 ), pcbIUScale.mmToIU( 25.0 ) );
1530 addRatioRangeError( wxS( "solder_paste_margin_ratio" ), m_SolderPasteMarginRatio,
1531 -1.0, 1.0 );
1532
1533 TEARDROP_PARAMETERS_LIST& teardropParamsList =
1535
1536 for( size_t ii = 0; ii < teardropParamsList.GetParametersCount(); ++ii )
1537 {
1538 const TEARDROP_PARAMETERS* params = teardropParamsList.GetParameters( static_cast<TARGET_TD>( ii ) );
1539 std::string target = GetTeardropTargetCanonicalName( static_cast<TARGET_TD>( ii ) );
1540
1541 if( params->m_TdMaxLen < 0 )
1542 {
1543 errors.push_back( {
1544 wxString::Format( wxS( "teardrop_parameters[%s].max_length" ), target ),
1545 _( "Value must be greater than or equal to 0." )
1546 } );
1547 }
1548
1549 if( params->m_TdMaxWidth < 0 )
1550 {
1551 errors.push_back( {
1552 wxString::Format( wxS( "teardrop_parameters[%s].max_width" ), target ),
1553 _( "Value must be greater than or equal to 0." )
1554 } );
1555 }
1556
1557 addRatioRangeError( wxString::Format( wxS( "teardrop_parameters[%s].best_length_ratio" ), target ),
1558 params->m_BestLengthRatio, 0.0, 1.0 );
1559 addRatioRangeError( wxString::Format( wxS( "teardrop_parameters[%s].best_width_ratio" ), target ),
1560 params->m_BestWidthRatio, 0.0, 1.0 );
1561 addRatioRangeError( wxString::Format( wxS( "teardrop_parameters[%s].width_to_size_filter_ratio" ),
1562 target ),
1563 params->m_WidthtoSizeFilterRatio, 0.0, 1.0 );
1564 }
1565
1566 for( size_t ii = 1; ii < m_DiffPairDimensionsList.size(); ++ii )
1567 {
1568 const DIFF_PAIR_DIMENSION& diffPair = m_DiffPairDimensionsList[ii];
1569
1570 if( diffPair.m_Width > 0 && diffPair.m_Gap <= 0 )
1571 {
1572 errors.push_back( {
1573 wxString::Format( wxS( "diff_pair_dimensions_list[%zu].gap" ), ii ),
1574 _( "No differential pair gap defined." )
1575 } );
1576 }
1577 }
1578
1579 for( size_t ii = 1; ii < m_ViasDimensionsList.size(); ++ii )
1580 {
1581 const VIA_DIMENSION& viaDim = m_ViasDimensionsList[ii];
1582
1583 std::optional<int> viaDiameter;
1584 std::optional<int> viaDrill;
1585
1586 if( viaDim.m_Diameter > 0 )
1587 viaDiameter = viaDim.m_Diameter;
1588
1589 if( viaDim.m_Drill > 0 )
1590 viaDrill = viaDim.m_Drill;
1591
1592 if( std::optional<PCB_VIA::VIA_PARAMETER_ERROR> error =
1593 PCB_VIA::ValidateViaParameters( viaDiameter, viaDrill ) )
1594 {
1595 errors.push_back( {
1596 wxString::Format( wxS( "via_dimensions_list[%zu]" ), ii ),
1597 error->m_Message
1598 } );
1599 }
1600 }
1601
1602 return errors;
1603}
1604
1605
1607{
1608 int biggest = std::max( m_MinClearance, m_HoleClearance );
1609 DRC_CONSTRAINT constraint;
1610
1611 biggest = std::max( biggest, m_HoleToHoleMin );
1612 biggest = std::max( biggest, m_CopperEdgeClearance );
1613
1614 if( m_DRCEngine )
1615 {
1616 m_DRCEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, constraint );
1617 biggest = std::max( biggest, constraint.Value().Min() );
1618
1619 m_DRCEngine->QueryWorstConstraint( PHYSICAL_CLEARANCE_CONSTRAINT, constraint );
1620 biggest = std::max( biggest, constraint.Value().Min() );
1621
1622 m_DRCEngine->QueryWorstConstraint( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, constraint );
1623 biggest = std::max( biggest, constraint.Value().Min() );
1624
1625 m_DRCEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, constraint );
1626 biggest = std::max( biggest, constraint.Value().Min() );
1627
1628 m_DRCEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, constraint );
1629 biggest = std::max( biggest, constraint.Value().Min() );
1630
1631 m_DRCEngine->QueryWorstConstraint( HOLE_TO_HOLE_CONSTRAINT, constraint );
1632 biggest = std::max( biggest, constraint.Value().Min() );
1633 }
1634
1635 // Clip to avoid integer overflows in subsequent calculations
1636 return std::min( biggest, MAXIMUM_CLEARANCE );
1637}
1638
1639
1641{
1642 int clearance = m_NetSettings->GetDefaultNetclass()->GetClearance();
1643
1644 for( const auto& [name, netclass] : m_NetSettings->GetNetclasses() )
1645 clearance = std::min( clearance, netclass->GetClearance() );
1646
1647 return clearance;
1648}
1649
1650
1651// Compute the next index when cycling a predefined-size list whose index 0 is the synthetic
1652// "use netclass" placeholder. Roll-over skips that placeholder when real sizes exist so the
1653// cycle stays monotonic.
1654static int nextPredefinedIndex( int aIndex, bool aForward, int aListSize )
1655{
1656 // Nothing to cycle when the list holds only the netclass placeholder (or is empty).
1657 if( aListSize <= 1 )
1658 return 0;
1659
1660 constexpr int lowestRealIndex = 1;
1661 int next = aIndex + ( aForward ? 1 : -1 );
1662
1663 if( next >= aListSize )
1664 next = lowestRealIndex;
1665 else if( next < lowestRealIndex )
1666 next = aListSize - 1;
1667
1668 return next;
1669}
1670
1671
1673{
1675 ? 0
1676 : std::clamp( aIndex, 0, (int) m_ViasDimensionsList.size() - 1 );
1677 m_useCustomTrackVia = false;
1678}
1679
1680
1681int BOARD_DESIGN_SETTINGS::GetNextViaSizeIndex( int aIndex, bool aForward ) const
1682{
1683 return nextPredefinedIndex( aIndex, aForward, (int) m_ViasDimensionsList.size() );
1684}
1685
1686
1688{
1690 return m_customViaSize.m_Diameter;
1692 return m_NetSettings->GetDefaultNetclass()->GetViaDiameter();
1693 else
1694 return m_ViasDimensionsList[ m_viaSizeIndex ].m_Diameter;
1695}
1696
1697
1699{
1700 int drill;
1701
1703 drill = m_customViaSize.m_Drill;
1705 drill = m_NetSettings->GetDefaultNetclass()->GetViaDrill();
1706 else
1707 drill = m_ViasDimensionsList[ m_viaSizeIndex ].m_Drill;
1708
1709 return drill > 0 ? drill : -1;
1710}
1711
1712
1714{
1716 ? 0
1717 : std::clamp( aIndex, 0, (int) m_TrackWidthList.size() - 1 );
1718 m_useCustomTrackVia = false;
1719}
1720
1721
1722int BOARD_DESIGN_SETTINGS::GetNextTrackWidthIndex( int aIndex, bool aForward ) const
1723{
1724 return nextPredefinedIndex( aIndex, aForward, (int) m_TrackWidthList.size() );
1725}
1726
1727
1729{
1731 return m_customTrackWidth;
1733 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1734 else
1736}
1737
1738
1740{
1742 ? 0
1743 : std::clamp( aIndex, 0, (int) m_DiffPairDimensionsList.size() - 1 );
1744 m_useCustomDiffPair = false;
1745}
1746
1747
1748int BOARD_DESIGN_SETTINGS::GetNextDiffPairIndex( int aIndex, bool aForward ) const
1749{
1750 return nextPredefinedIndex( aIndex, aForward, (int) m_DiffPairDimensionsList.size() );
1751}
1752
1753
1755{
1757 {
1758 return m_customDiffPair.m_Width;
1759 }
1761 {
1762 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairWidth() )
1763 return m_NetSettings->GetDefaultNetclass()->GetDiffPairWidth();
1764 else
1765 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1766 }
1767 else
1768 {
1770 }
1771}
1772
1773
1775{
1777 {
1778 return m_customDiffPair.m_Gap;
1779 }
1781 {
1782 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairGap() )
1783 return m_NetSettings->GetDefaultNetclass()->GetDiffPairGap();
1784 else
1785 return m_NetSettings->GetDefaultNetclass()->GetClearance();
1786 }
1787 else
1788 {
1790 }
1791}
1792
1793
1795{
1797 {
1798 return m_customDiffPair.m_ViaGap;
1799 }
1801 {
1802 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairViaGap() )
1803 return m_NetSettings->GetDefaultNetclass()->GetDiffPairViaGap();
1804 else
1805 return GetCurrentDiffPairGap();
1806 }
1807 else
1808 {
1810 }
1811}
1812
1813
1815{
1816 m_copperLayerCount = aNewLayerCount;
1817
1818 // Update only enabled copper layers mask
1819 m_enabledLayers.ClearCopperLayers();
1820
1821 if( aNewLayerCount > 0 )
1822 m_enabledLayers |= LSET::AllCuMask( aNewLayerCount );
1823}
1824
1825
1827{
1828 m_userDefinedLayerCount = aNewLayerCount;
1829
1830 m_enabledLayers.ClearUserDefinedLayers();
1831
1832 if( aNewLayerCount > 0 )
1833 m_enabledLayers |= LSET::UserDefinedLayersMask( aNewLayerCount );
1834}
1835
1836
1838{
1839 m_enabledLayers = aMask;
1840
1841 // Ensures mandatory back and front layers are always enabled regardless of board file
1842 // configuration.
1843 m_enabledLayers.set( B_Cu ).set( F_Cu )
1844 .set( B_CrtYd ).set( F_CrtYd )
1845 .set( Edge_Cuts )
1846 .set( Margin );
1847
1848 // update layer counts to ensure their consistency with m_EnabledLayers
1849 LSET copperLayers = aMask;
1850 copperLayers.ClearNonCopperLayers();
1851
1852 LSET userLayers = aMask & LSET::UserDefinedLayersMask();
1853
1854 m_copperLayerCount = (int) copperLayers.count();
1855 m_userDefinedLayerCount = (int) userLayers.count();
1856}
1857
1858
1859// Return the layer class index { silk, copper, edges & courtyards, fab, others } of the
1860// given layer.
1862{
1863 if( aLayer == F_SilkS || aLayer == B_SilkS )
1864 return LAYER_CLASS_SILK;
1865 else if( IsCopperLayer( aLayer ) )
1866 return LAYER_CLASS_COPPER;
1867 else if( aLayer == Edge_Cuts )
1868 return LAYER_CLASS_EDGES;
1869 else if( aLayer == F_CrtYd || aLayer == B_CrtYd )
1870 return LAYER_CLASS_COURTYARD;
1871 else if( aLayer == F_Fab || aLayer == B_Fab )
1872 return LAYER_CLASS_FAB;
1873 else
1874 return LAYER_CLASS_OTHERS;
1875}
1876
1877
1879{
1880 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
1881}
1882
1883
1885{
1886 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
1887}
1888
1889
1891{
1892 return m_LineThickness[ GetLayerClass( aLayer ) ];
1893}
1894
1895
1897{
1898 return m_TextSize[ GetLayerClass( aLayer ) ];
1899}
1900
1901
1903{
1904 return m_TextThickness[ GetLayerClass( aLayer ) ];
1905}
1906
1907
1909{
1910 return m_TextItalic[ GetLayerClass( aLayer ) ];
1911}
1912
1913
1915{
1916 return m_TextUpright[ GetLayerClass( aLayer ) ];
1917}
1918
1920{
1921 m_Pad_Master->SetSizeX( pcbIUScale.mmToIU( DEFAULT_PAD_WIDTH_MM ) );
1922 m_Pad_Master->SetSizeY( pcbIUScale.mmToIU( DEFAULT_PAD_HEIGTH_MM ) );
1923 m_Pad_Master->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
1924 m_Pad_Master->SetDrillSize( VECTOR2I( pcbIUScale.mmToIU( DEFAULT_PAD_DRILL_DIAMETER_MM ), 0 ) );
1926
1927 constexpr double RR_RADIUS = DEFAULT_PAD_HEIGTH_MM * DEFAULT_PAD_RR_RADIUS_RATIO;
1928 m_Pad_Master->SetRoundRectCornerRadius( PADSTACK::ALL_LAYERS, pcbIUScale.mmToIU( RR_RADIUS ) );
1929
1930 if( m_Pad_Master->GetFrontShape() == PAD_SHAPE::CIRCLE )
1931 m_Pad_Master->SetThermalSpokeAngle( ANGLE_45 );
1932 else
1933 m_Pad_Master->SetThermalSpokeAngle( ANGLE_90 );
1934}
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 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:116
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
std::map< wxString, wxString > m_DrcExclusionComments
DIM_UNITS_FORMAT m_DimensionUnitsFormat
void initFromOther(const BOARD_DESIGN_SETTINGS &aOther)
bool GetTextUpright(PCB_LAYER_ID aLayer) const
std::map< int, SEVERITY > m_DRCSeverities
VECTOR2I m_gridOrigin
origin for grid offsets
int GetTextThickness(PCB_LAYER_ID aLayer) const
Return the default text thickness from the layer class for the given layer.
VECTOR2I m_auxOrigin
origin for plot exports
bool m_TextUpright[LAYER_CLASS_COUNT]
BOARD_DESIGN_SETTINGS(JSON_SETTINGS *aParent, const std::string &aPath)
bool GetTextItalic(PCB_LAYER_ID aLayer) const
int GetNextDiffPairIndex(int aIndex, bool aForward) const
Compute the next diff pair dimensions list index when cycling predefined sizes, skipping the index-0 ...
wxString m_currentNetClassName
Current net class name used to display netclass info.
void SetViaSizeIndex(int aIndex)
Set the current via size list index to aIndex.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
std::set< wxString > m_DrcExclusions
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]
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)
MINOPTMAX< int > & Value()
Definition drc_rule.h:197
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition drc_item.h:142
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition drc_item.cpp:417
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:946
static LSET UserDefinedLayersMask(int aUserDefinedLayerCount=MAX_USER_DEFINED_LAYERS)
Return a mask with the requested number of user defined layers.
Definition lset.cpp:700
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()
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:177
Stores an enum as an integer.
Definition parameters.h:230
Like a normal param, but with custom getter and setter functions.
Definition parameters.h:297
Represents a parameter that has a scaling factor between the value in the file and the value used int...
Definition parameters.h:394
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:80
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_CurvedEdges
True if the teardrop should be curved.
@ DRCE_FOOTPRINT_SCALED_WITH_PADS
Definition drc_item.h:83
@ DRCE_TUNING_PROFILE_IMPLICIT_RULES
Definition drc_item.h:113
@ DRCE_SILK_EDGE_CLEARANCE
Definition drc_item.h:96
@ DRCE_FOOTPRINT_FILTERS
Definition drc_item.h:76
@ DRCE_SILK_MASK_CLEARANCE
Definition drc_item.h:94
@ DRCE_PADSTACK
Definition drc_item.h:59
@ DRCE_MIRRORED_TEXT_ON_FRONT_LAYER
Definition drc_item.h:109
@ DRCE_LIB_FOOTPRINT_ISSUES
Definition drc_item.h:79
@ DRCE_OVERLAPPING_FOOTPRINTS
Definition drc_item.h:62
@ DRCE_SCHEMATIC_FIELDS_PARITY
Definition drc_item.h:119
@ DRCE_MISSING_COURTYARD
Definition drc_item.h:63
@ DRCE_TRACK_NOT_CENTERED_ON_VIA
Definition drc_item.h:117
@ DRCE_ISOLATED_COPPER
Definition drc_item.h:45
@ DRCE_MISSING_TUNING_PROFILE
Definition drc_item.h:112
@ DRCE_DRILLED_HOLES_TOO_CLOSE
Definition drc_item.h:49
@ DRCE_COPPER_SLIVER
Definition drc_item.h:90
@ DRCE_PTH_IN_COURTYARD
Definition drc_item.h:66
@ DRCE_FIRST
Definition drc_item.h:35
@ DRCE_DANGLING_VIA
Definition drc_item.h:47
@ DRCE_FOOTPRINT_TYPE_MISMATCH
Definition drc_item.h:78
@ DRCE_NONMIRRORED_TEXT_ON_BACK_LAYER
Definition drc_item.h:110
@ DRCE_DUPLICATE_FOOTPRINT
Definition drc_item.h:72
@ DRCE_DANGLING_TRACK
Definition drc_item.h:48
@ DRCE_TEXT_HEIGHT
Definition drc_item.h:98
@ DRCE_DRILLED_HOLES_COLOCATED
Definition drc_item.h:50
@ DRCE_EXTRA_FOOTPRINT
Definition drc_item.h:73
@ DRCE_SILK_CLEARANCE
Definition drc_item.h:97
@ DRCE_LAST
Definition drc_item.h:121
@ DRCE_LIB_FOOTPRINT_MISMATCH
Definition drc_item.h:80
@ DRCE_NET_CONFLICT
Definition drc_item.h:74
@ DRCE_MISSING_FOOTPRINT
Definition drc_item.h:71
@ DRCE_TEXT_THICKNESS
Definition drc_item.h:99
@ DRCE_NPTH_IN_COURTYARD
Definition drc_item.h:67
@ DRCE_CONNECTION_WIDTH
Definition drc_item.h:56
@ DRCE_SCHEMATIC_PARITY
Definition drc_item.h:75
@ 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:413
@ DEGREES_T
Definition eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_45
Definition eda_angle.h:412
#define TEXT_MIN_SIZE_MM
Minimum text size (1 micron).
Definition eda_text.h:56
#define TEXT_MAX_SIZE_MM
Maximum text size in mm (~10 inches)
Definition eda_text.h:57
EDA_UNITS
Definition eda_units.h:44
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:675
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
@ B_SilkS
Definition layer_ids.h:97
@ F_Cu
Definition layer_ids.h:60
@ B_Fab
Definition layer_ids.h:114
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:57
@ 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
Container to handle a stock of specific differential pairs each with unique track width,...
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
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