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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <pcb_dimension.h>
25#include <pcb_track.h>
26#include <layer_ids.h>
27#include <lset.h>
28#include <kiface_base.h>
29#include <pad.h>
31#include <drc/drc_item.h>
32#include <drc/drc_engine.h>
34#include <settings/parameters.h>
36#include <advanced_config.h>
37
38const int bdsSchemaVersion = 2;
39
40
41BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
42 NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aParent, aPath )
43{
44 // We want to leave alone parameters that aren't found in the project JSON as they may be
45 // initialized by the board file parser before NESTED_SETTINGS::LoadFromFile is called.
47
48 // Create a default NET_SETTINGS so that things don't break horribly if there's no project
49 // loaded. This also is used during file load for legacy boards that have netclasses stored
50 // in the file. After load, this information will be moved to the project and the pointer
51 // updated.
52 m_NetSettings = std::make_shared<NET_SETTINGS>( nullptr, "" );
53
54 m_HasStackup = false; // no stackup defined by default
55
56 m_Pad_Master = std::make_unique<PAD>( nullptr );
58
59 LSET all_set = LSET().set();
60 m_enabledLayers = all_set; // All layers enabled at first.
61 // SetCopperLayerCount() will adjust this.
62
63 // Default design is a double layer board with 4 user defined layers
66
67 m_CurrentViaType = VIATYPE::THROUGH;
68
69 // if true, when creating a new track starting on an existing track, use this track width
72
73 // First is always the reference designator
74 m_DefaultFPTextItems.emplace_back( wxT( "REF**" ), true, F_SilkS );
75 // Second is always the value
76 m_DefaultFPTextItems.emplace_back( wxT( "" ), true, F_Fab );
77 // Any following ones are freebies
78 m_DefaultFPTextItems.emplace_back( wxT( "${REFERENCE}" ), true, F_Fab );
79
86
93
94 // Edges & Courtyards; text properties aren't used but better to have them holding
95 // reasonable values than not.
102
109
114 m_TextItalic[ LAYER_CLASS_FAB ] = false;
116
123
124 m_StyleFPFields = false;
125 m_StyleFPText = false;
126 m_StyleFPShapes = false;
127
128 m_DimensionPrecision = DIM_PRECISION::X_XXXX;
129 m_DimensionUnitsMode = DIM_UNITS_MODE::AUTOMATIC;
130 m_DimensionUnitsFormat = DIM_UNITS_FORMAT::NO_SUFFIX;
132 m_DimensionTextPosition = DIM_TEXT_POSITION::OUTSIDE;
136
137 m_useCustomTrackVia = false;
141
142 m_useCustomDiffPair = false;
146
163
164 for( int errorCode = DRCE_FIRST; errorCode <= DRCE_LAST; ++errorCode )
165 m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
166
169
173
176
179
181
188
194
196
199
201
204
208
209 // Global mask margins:
213
214 // Solder paste margin absolute value
216 // Solder paste margin as a ratio of pad size
217 // The final margin is the sum of these 2 values
218 // Usually < 0 because the mask is smaller than pad
220
222 m_TentViasFront = true;
223 m_TentViasBack = true;
224
225 // Layer thickness for 3D viewer
227
228 // Default spacing for meanders
232
233 m_viaSizeIndex = 0;
235 m_diffPairIndex = 0;
236
237 // Parameters stored in JSON in the project file
238
239 // NOTE: Previously, BOARD_DESIGN_SETTINGS stored the basic board layer information (layer
240 // names and enable/disable state) in the project file even though this information is also
241 // stored in the board file. This was implemented for importing these settings from another
242 // project. Going forward, the import feature will just import from other board files (since
243 // we could have multi-board projects in the future anyway) so this functionality is dropped.
244
245
246 m_params.emplace_back( new PARAM<bool>( "rules.use_height_for_length_calcs",
247 &m_UseHeightForLengthCalcs, true ) );
248
249 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_clearance",
252
253 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_connection",
255 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
256
257 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_track_width",
260
261 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_annular_width",
264
265 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_diameter",
268
269 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_through_hole_diameter",
272
273 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_diameter",
276
277 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_drill",
280
281 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_to_hole",
284
285 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_clearance",
287 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
288
289 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_silk_clearance",
291 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
292
293 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_groove_width",
296
297 // While the maximum *effective* value is 4, we've had users interpret this as the count on
298 // all layers, and enter something like 10. They'll figure it out soon enough *unless* we
299 // enforce a max of 4 (and therefore reset it back to the default of 2), at which point it
300 // just looks buggy.
301 m_params.emplace_back( new PARAM<int>( "rules.min_resolved_spokes",
303
304 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_height",
306 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
307
308 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_thickness",
311
312 // Note: a clearance of -0.01 is a flag indicating we should use the legacy (pre-6.0) method
313 // based on the edge cut thicknesses.
314 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_copper_edge_clearance",
316 pcbIUScale.mmToIU( -0.01 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
317
318 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
319 [&]() -> nlohmann::json
320 {
321 nlohmann::json ret = {};
322
323 for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
324 {
325 wxString name = item.GetSettingsKey();
326 int code = item.GetErrorCode();
327
328 if( name.IsEmpty() || m_DRCSeverities.count( code ) == 0 )
329 continue;
330
331 ret[std::string( name.ToUTF8() )] = SeverityToString( m_DRCSeverities[code] );
332 }
333
334 return ret;
335 },
336 [&]( const nlohmann::json& aJson )
337 {
338 if( !aJson.is_object() )
339 return;
340
341 for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities( true ) )
342 {
343 wxString name = item.GetSettingsKey();
344 std::string key( name.ToUTF8() );
345
346 if( aJson.contains( key ) )
347 m_DRCSeverities[item.GetErrorCode()] = SeverityFromString( aJson[key] );
348 }
349 }, {} ) );
350
351 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "drc_exclusions",
352 [&]() -> nlohmann::json
353 {
354 nlohmann::json js = nlohmann::json::array();
355
356 for( const wxString& entry : m_DrcExclusions )
357 js.push_back( { entry, m_DrcExclusionComments[ entry ] } );
358
359 return js;
360 },
361 [&]( const nlohmann::json& aObj )
362 {
363 m_DrcExclusions.clear();
364
365 if( !aObj.is_array() )
366 return;
367
368 for( const nlohmann::json& entry : aObj )
369 {
370 if( entry.is_array() )
371 {
372 wxString serialized = entry[0].get<wxString>();
373 m_DrcExclusions.insert( serialized );
374 m_DrcExclusionComments[ serialized ] = entry[1].get<wxString>();
375 }
376 else if( entry.is_string() )
377 {
378 m_DrcExclusions.insert( entry.get<wxString>() );
379 }
380 }
381 },
382 {} ) );
383
384 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "track_widths",
385 [&]() -> nlohmann::json
386 {
387 nlohmann::json js = nlohmann::json::array();
388
389 for( const int& width : m_TrackWidthList )
390 js.push_back( pcbIUScale.IUTomm( width ) );
391
392 return js;
393 },
394 [&]( const nlohmann::json& aJson )
395 {
396 if( !aJson.is_array() )
397 return;
398
399 m_TrackWidthList.clear();
400
401 for( const nlohmann::json& entry : aJson )
402 {
403 if( entry.empty() )
404 continue;
405
406 m_TrackWidthList.emplace_back( pcbIUScale.mmToIU( entry.get<double>() ) );
407 }
408 },
409 {} ) );
410
411 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "via_dimensions",
412 [&]() -> nlohmann::json
413 {
414 nlohmann::json js = nlohmann::json::array();
415
416 for( const auto& via : m_ViasDimensionsList )
417 {
418 nlohmann::json entry = {};
419
420 entry["diameter"] = pcbIUScale.IUTomm( via.m_Diameter );
421 entry["drill"] = pcbIUScale.IUTomm( via.m_Drill );
422
423 js.push_back( entry );
424 }
425
426 return js;
427 },
428 [&]( const nlohmann::json& aObj )
429 {
430 if( !aObj.is_array() )
431 return;
432
433 m_ViasDimensionsList.clear();
434
435 for( const nlohmann::json& entry : aObj )
436 {
437 if( entry.empty() || !entry.is_object() )
438 continue;
439
440 if( !entry.contains( "diameter" ) || !entry.contains( "drill" ) )
441 continue;
442
443 int diameter = pcbIUScale.mmToIU( entry["diameter"].get<double>() );
444 int drill = pcbIUScale.mmToIU( entry["drill"].get<double>() );
445
446 m_ViasDimensionsList.emplace_back( VIA_DIMENSION( diameter, drill ) );
447 }
448 },
449 {} ) );
450
451 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "diff_pair_dimensions",
452 [&]() -> nlohmann::json
453 {
454 nlohmann::json js = nlohmann::json::array();
455
456 for( const auto& pair : m_DiffPairDimensionsList )
457 {
458 nlohmann::json entry = {};
459
460 entry["width"] = pcbIUScale.IUTomm( pair.m_Width );
461 entry["gap"] = pcbIUScale.IUTomm( pair.m_Gap );
462 entry["via_gap"] = pcbIUScale.IUTomm( pair.m_ViaGap );
463
464 js.push_back( entry );
465 }
466
467 return js;
468 },
469 [&]( const nlohmann::json& aObj )
470 {
471 if( !aObj.is_array() )
472 return;
473
475
476 for( const nlohmann::json& entry : aObj )
477 {
478 if( entry.empty() || !entry.is_object() )
479 continue;
480
481 if( !entry.contains( "width" )
482 || !entry.contains( "gap" )
483 || !entry.contains( "via_gap" ) )
484 {
485 continue;
486 }
487
488 int width = pcbIUScale.mmToIU( entry["width"].get<double>() );
489 int gap = pcbIUScale.mmToIU( entry["gap"].get<double>() );
490 int via_gap = pcbIUScale.mmToIU( entry["via_gap"].get<double>() );
491
492 m_DiffPairDimensionsList.emplace_back( DIFF_PAIR_DIMENSION( width, gap, via_gap ) );
493 }
494 },
495 {} ) );
496
497 // Handle options for teardrops (targets and some others):
498 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_options",
499 [&]() -> nlohmann::json
500 {
501 nlohmann::json js = nlohmann::json::array();
502 nlohmann::json entry = {};
503
504 entry["td_onvia"] = m_TeardropParamsList.m_TargetVias;
505 entry["td_onpthpad"] = m_TeardropParamsList.m_TargetPTHPads;
506 entry["td_onsmdpad"] = m_TeardropParamsList.m_TargetSMDPads;
507 entry["td_ontrackend"] = m_TeardropParamsList.m_TargetTrack2Track;
508 entry["td_onroundshapesonly"] = m_TeardropParamsList.m_UseRoundShapesOnly;
509
510 js.push_back( entry );
511
512 return js;
513 },
514 [&]( const nlohmann::json& aObj )
515 {
516 if( !aObj.is_array() )
517 return;
518
519 for( const nlohmann::json& entry : aObj )
520 {
521 if( entry.empty() || !entry.is_object() )
522 continue;
523
524 if( entry.contains( "td_onvia" ) )
525 m_TeardropParamsList.m_TargetVias = entry["td_onvia"].get<bool>();
526
527 if( entry.contains( "td_onpthpad" ) )
528 m_TeardropParamsList.m_TargetPTHPads = entry["td_onpthpad"].get<bool>();
529
530 if( entry.contains( "td_onsmdpad" ) )
531 m_TeardropParamsList.m_TargetSMDPads = entry["td_onsmdpad"].get<bool>();
532
533 if( entry.contains( "td_ontrackend" ) )
534 m_TeardropParamsList.m_TargetTrack2Track = entry["td_ontrackend"].get<bool>();
535
536 if( entry.contains( "td_onroundshapesonly" ) )
537 m_TeardropParamsList.m_UseRoundShapesOnly = entry["td_onroundshapesonly"].get<bool>();
538
539 // Legacy settings
540 for( int ii = 0; ii < 3; ++ii )
541 {
543
544 if( entry.contains( "td_allow_use_two_tracks" ) )
545 td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
546
547 if( entry.contains( "td_curve_segcount" ) )
548 {
549 if( entry["td_curve_segcount"].get<int>() > 0 )
550 td_prm->m_CurvedEdges = true;
551 }
552
553 if( entry.contains( "td_on_pad_in_zone" ) )
554 td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
555 }
556 }
557 },
558 {} ) );
559
560 // Handle parameters (sizes, shape) for each type of teardrop:
561 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_parameters",
562 [&]() -> nlohmann::json
563 {
564 nlohmann::json js = nlohmann::json::array();
565
566 for( size_t ii = 0; ii < m_TeardropParamsList.GetParametersCount(); ii++ )
567 {
568 nlohmann::json entry = {};
570
571 entry["td_target_name"] = GetTeardropTargetCanonicalName( (TARGET_TD)ii );
572 entry["td_maxlen"] = pcbIUScale.IUTomm( td_prm->m_TdMaxLen );
573 entry["td_maxheight"] = pcbIUScale.IUTomm( td_prm->m_TdMaxWidth );
574 entry["td_length_ratio"] = td_prm->m_BestLengthRatio;
575 entry["td_height_ratio"] = td_prm->m_BestWidthRatio;
576 entry["td_curve_segcount"] = td_prm->m_CurvedEdges ? 1 : 0;
577 entry["td_width_to_size_filter_ratio"] = td_prm->m_WidthtoSizeFilterRatio;
578 entry["td_allow_use_two_tracks"] = td_prm->m_AllowUseTwoTracks;
579 entry["td_on_pad_in_zone"] = td_prm->m_TdOnPadsInZones;
580
581 js.push_back( entry );
582 }
583
584 return js;
585 },
586 [&]( const nlohmann::json& aObj )
587 {
588 if( !aObj.is_array() )
589 return;
590
591 for( const nlohmann::json& entry : aObj )
592 {
593 if( entry.empty() || !entry.is_object() )
594 continue;
595
596 if( !entry.contains( "td_target_name" ) )
597 continue;
598
599 int idx = GetTeardropTargetTypeFromCanonicalName( entry["td_target_name"].get<std::string>() );
600
601 if( idx >= 0 && idx < 3 )
602 {
604
605 if( entry.contains( "td_maxlen" ) )
606 td_prm->m_TdMaxLen = pcbIUScale.mmToIU( entry["td_maxlen"].get<double>() );
607
608 if( entry.contains( "td_maxheight" ) )
609 td_prm->m_TdMaxWidth = pcbIUScale.mmToIU( entry["td_maxheight"].get<double>() );
610
611 if( entry.contains( "td_length_ratio" ) )
612 td_prm->m_BestLengthRatio = entry["td_length_ratio"].get<double>();
613
614 if( entry.contains( "td_height_ratio" ) )
615 td_prm->m_BestWidthRatio = entry["td_height_ratio"].get<double>();
616
617 if( entry.contains( "td_curve_segcount" ) )
618 {
619 if( entry["td_curve_segcount"].get<int>() > 0 )
620 td_prm->m_CurvedEdges = true;
621 }
622
623 if( entry.contains( "td_width_to_size_filter_ratio" ) )
624 td_prm->m_WidthtoSizeFilterRatio = entry["td_width_to_size_filter_ratio"].get<double>();
625
626 if( entry.contains( "td_allow_use_two_tracks" ) )
627 td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
628
629 if( entry.contains( "td_on_pad_in_zone" ) )
630 td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
631 }
632 }
633 },
634 {} ) );
635
636 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "tuning_pattern_settings",
637 [&]() -> nlohmann::json
638 {
639 nlohmann::json js = {};
640
641 auto make_settings =
642 []( const PNS::MEANDER_SETTINGS& aSettings )
643 {
644 nlohmann::json entry = {};
645
646 entry["min_amplitude"] = pcbIUScale.IUTomm( aSettings.m_minAmplitude );
647 entry["max_amplitude"] = pcbIUScale.IUTomm( aSettings.m_maxAmplitude );
648 entry["spacing"] = pcbIUScale.IUTomm( aSettings.m_spacing );
649 entry["corner_style"] = aSettings.m_cornerStyle == PNS::MEANDER_STYLE_CHAMFER ? 0 : 1;
650 entry["corner_radius_percentage"] = aSettings.m_cornerRadiusPercentage;
651 entry["single_sided"] = aSettings.m_singleSided;
652
653 return entry;
654 };
655
656 js["single_track_defaults"] = make_settings( m_SingleTrackMeanderSettings );
657 js["diff_pair_defaults"] = make_settings( m_DiffPairMeanderSettings );
658 js["diff_pair_skew_defaults"] = make_settings( m_SkewMeanderSettings );
659
660 return js;
661 },
662 [&]( const nlohmann::json& aObj )
663 {
664 auto read_settings =
665 []( const nlohmann::json& entry ) -> PNS::MEANDER_SETTINGS
666 {
667 PNS::MEANDER_SETTINGS settings;
668
669 if( entry.contains( "min_amplitude" ) )
670 settings.m_minAmplitude = pcbIUScale.mmToIU( entry["min_amplitude"].get<double>() );
671
672 if( entry.contains( "max_amplitude" ) )
673 settings.m_maxAmplitude = pcbIUScale.mmToIU( entry["max_amplitude"].get<double>() );
674
675 if( entry.contains( "spacing" ) )
676 settings.m_spacing = pcbIUScale.mmToIU( entry["spacing"].get<double>() );
677
678 if( entry.contains( "corner_style" ) )
679 {
680 settings.m_cornerStyle = entry["corner_style"] == 0 ? PNS::MEANDER_STYLE_CHAMFER
682 }
683
684 if( entry.contains( "corner_radius_percentage" ) )
685 settings.m_cornerRadiusPercentage = entry["corner_radius_percentage"].get<int>();
686
687 if( entry.contains( "single_sided" ) )
688 settings.m_singleSided = entry["single_sided"].get<bool>();
689
690 return settings;
691 };
692
693 if( aObj.contains( "single_track_defaults" ) )
694 m_SingleTrackMeanderSettings = read_settings( aObj["single_track_defaults"] );
695
696 if( aObj.contains( "diff_pair_defaults" ) )
697 m_DiffPairMeanderSettings = read_settings( aObj["diff_pair_defaults"] );
698
699 if( aObj.contains( "diff_pair_skew_defaults" ) )
700 m_SkewMeanderSettings = read_settings( aObj["diff_pair_skew_defaults"] );
701 },
702 {} ) );
703
704 int minTextSize = pcbIUScale.mmToIU( TEXT_MIN_SIZE_MM );
705 int maxTextSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
706 int minStroke = 1;
707 int maxStroke = pcbIUScale.mmToIU( 100 );
708
709 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_line_width",
711 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
712
713 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_v",
715 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
716
717 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_h",
719 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
720
721 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_thickness",
723 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
724
725 m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_italic",
726 &m_TextItalic[LAYER_CLASS_SILK], false ) );
727
728 m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_upright",
729 &m_TextUpright[ LAYER_CLASS_SILK ], true ) );
730
731 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_line_width",
733 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
734
735 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_v",
737 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
738
739 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_h",
741 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
742
743 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_thickness",
745 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
746
747 m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_italic",
748 &m_TextItalic[LAYER_CLASS_COPPER], false ) );
749
750 m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_upright",
752
753 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.board_outline_line_width",
755 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
756
757 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.courtyard_line_width",
759 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
760
761 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_line_width",
763 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
764
765 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_v",
767 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
768
769 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_h",
771 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
772
773 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_thickness",
775 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
776
777 m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_italic",
778 &m_TextItalic[LAYER_CLASS_FAB], false ) );
779
780 m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_upright",
781 &m_TextUpright[LAYER_CLASS_FAB], true ) );
782
783 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_line_width",
785 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
786
787 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_v",
789 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
790
791 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_h",
793 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
794
795 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_thickness",
797 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
798
799 m_params.emplace_back( new PARAM<bool>( "defaults.other_text_italic",
800 &m_TextItalic[LAYER_CLASS_OTHERS], false ) );
801
802 m_params.emplace_back( new PARAM<bool>( "defaults.other_text_upright",
804
805 m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_MODE>( "defaults.dimension_units",
806 &m_DimensionUnitsMode, DIM_UNITS_MODE::AUTOMATIC, DIM_UNITS_MODE::INCHES,
807 DIM_UNITS_MODE::AUTOMATIC ) );
808
809 m_params.emplace_back( new PARAM_ENUM<DIM_PRECISION>( "defaults.dimension_precision",
810 &m_DimensionPrecision, DIM_PRECISION::X_XXXX, DIM_PRECISION::X, DIM_PRECISION::V_VVVVV ) );
811
812 m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_FORMAT>( "defaults.dimensions.units_format",
813 &m_DimensionUnitsFormat, DIM_UNITS_FORMAT::NO_SUFFIX, DIM_UNITS_FORMAT::NO_SUFFIX,
814 DIM_UNITS_FORMAT::PAREN_SUFFIX ) );
815
816 m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.suppress_zeroes",
817 &m_DimensionSuppressZeroes, true ) );
818
819 // NOTE: excluding DIM_TEXT_POSITION::MANUAL from the valid range here
820 m_params.emplace_back( new PARAM_ENUM<DIM_TEXT_POSITION>( "defaults.dimensions.text_position",
821 &m_DimensionTextPosition, DIM_TEXT_POSITION::OUTSIDE, DIM_TEXT_POSITION::OUTSIDE,
822 DIM_TEXT_POSITION::INLINE ) );
823
824 m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.keep_text_aligned",
826
827 m_params.emplace_back( new PARAM<int>( "defaults.dimensions.arrow_length",
830
831 m_params.emplace_back( new PARAM<int>( "defaults.dimensions.extension_offset",
834
835 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_fields",
836 &m_StyleFPFields, false ) );
837 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_text",
838 &m_StyleFPText, false ) );
839 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_shapes",
840 &m_StyleFPShapes, false ) );
841
842 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.zones.min_clearance",
845
846 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "defaults.pads",
847 [&]() -> nlohmann::json
848 {
849 nlohmann::json ret =
850 {
851 { "width", pcbIUScale.IUTomm( m_Pad_Master->GetSize( PADSTACK::ALL_LAYERS ).x ) },
852 { "height", pcbIUScale.IUTomm( m_Pad_Master->GetSize( PADSTACK::ALL_LAYERS ).y ) },
853 { "drill", pcbIUScale.IUTomm( m_Pad_Master->GetDrillSize().x ) }
854 };
855
856 return ret;
857 },
858 [&]( const nlohmann::json& aJson )
859 {
860 if( aJson.contains( "width" ) && aJson.contains( "height" )
861 && aJson.contains( "drill" ) )
862 {
863 VECTOR2I sz;
864 sz.x = pcbIUScale.mmToIU( aJson["width"].get<double>() );
865 sz.y = pcbIUScale.mmToIU( aJson["height"].get<double>() );
866
867 m_Pad_Master->SetSize( PADSTACK::ALL_LAYERS, sz );
868
869 int drill = pcbIUScale.mmToIU( aJson["drill"].get<double>() );
870
871 m_Pad_Master->SetDrillSize( VECTOR2I( drill, drill ) );
872 }
873 }, {} ) );
874
875 m_params.emplace_back( new PARAM_SCALED<int>( "rules.max_error",
877 pcbIUScale.mmToIU( 0.0001 ), pcbIUScale.mmToIU( 1.0 ), pcbIUScale.MM_PER_IU ) );
878
879 m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_mask_to_copper_clearance",
882
883 m_params.emplace_back( new PARAM<bool>( "zones_allow_external_fillets",
884 &m_ZoneKeepExternalFillets, false ) );
885
887
888 registerMigration( 1, 2,
889 [&]() -> bool
890 {
891 // Schema 1 to 2: move mask and paste margin settings back to board.
892 // The parameters are removed, so we just have to manually load them here and
893 // they will get saved with the board
894 if( std::optional<double> optval = Get<double>( "rules.solder_mask_clearance" ) )
895 m_SolderMaskExpansion = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
896
897 if( std::optional<double> optval = Get<double>( "rules.solder_mask_min_width" ) )
898 m_SolderMaskMinWidth = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
899
900 if( std::optional<double> optval = Get<double>( "rules.solder_paste_clearance" ) )
901 m_SolderPasteMargin = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
902
903 if( std::optional<double> optval = Get<double>( "rules.solder_paste_margin_ratio" ) )
904 m_SolderPasteMarginRatio = *optval;
905
906 try
907 {
908 At( "rules" ).erase( "solder_mask_clearance" );
909 At( "rules" ).erase( "solder_mask_min_width" );
910 At( "rules" ).erase( "solder_paste_clearance" );
911 At( "rules" ).erase( "solder_paste_margin_ratio" );
912 }
913 catch( ... )
914 {}
915
916 return true;
917 } );
918}
919
920
922{
923 if( m_parent )
924 {
926 m_parent = nullptr;
927 }
928}
929
930
932 NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aOther.m_parent,
933 aOther.m_path ),
934 m_Pad_Master( nullptr )
935{
936 initFromOther( aOther );
937}
938
939
941{
942 initFromOther( aOther );
943 return *this;
944}
945
946
948{
949 // Copy of NESTED_SETTINGS around is not allowed, so let's just update the params.
958 m_MinConn = aOther.m_MinConn;
976 m_MaxError = aOther.m_MaxError;
987
988 std::copy( std::begin( aOther.m_LineThickness ), std::end( aOther.m_LineThickness ),
989 std::begin( m_LineThickness ) );
990
991 std::copy( std::begin( aOther.m_TextSize ), std::end( aOther.m_TextSize ),
992 std::begin( m_TextSize ) );
993
994 std::copy( std::begin( aOther.m_TextThickness ), std::end( aOther.m_TextThickness ),
995 std::begin( m_TextThickness ) );
996
997 std::copy( std::begin( aOther.m_TextItalic ), std::end( aOther.m_TextItalic ),
998 std::begin( m_TextItalic ) );
999
1000 std::copy( std::begin( aOther.m_TextUpright ), std::end( aOther.m_TextUpright ),
1001 std::begin( m_TextUpright ) );
1002
1011
1012 m_auxOrigin = aOther.m_auxOrigin;
1013 m_gridOrigin = aOther.m_gridOrigin;
1014 m_HasStackup = aOther.m_HasStackup;
1016
1030 m_stackup = aOther.m_stackup;
1032 m_Pad_Master = std::make_unique<PAD>( *aOther.m_Pad_Master );
1034
1038}
1039
1040
1042{
1043 if( m_TrackWidthList != aOther.m_TrackWidthList ) return false;
1044 if( m_ViasDimensionsList != aOther.m_ViasDimensionsList ) return false;
1045 if( m_DiffPairDimensionsList != aOther.m_DiffPairDimensionsList ) return false;
1046 if( m_CurrentViaType != aOther.m_CurrentViaType ) return false;
1047 if( m_UseConnectedTrackWidth != aOther.m_UseConnectedTrackWidth ) return false;
1048 if( m_TempOverrideTrackWidth != aOther.m_TempOverrideTrackWidth ) return false;
1049 if( m_MinClearance != aOther.m_MinClearance ) return false;
1050 if( m_MinGrooveWidth != aOther.m_MinGrooveWidth ) return false;
1051 if( m_MinConn != aOther.m_MinConn ) return false;
1052 if( m_TrackMinWidth != aOther.m_TrackMinWidth ) return false;
1053 if( m_ViasMinAnnularWidth != aOther.m_ViasMinAnnularWidth ) return false;
1054 if( m_ViasMinSize != aOther.m_ViasMinSize ) return false;
1055 if( m_MinThroughDrill != aOther.m_MinThroughDrill ) return false;
1056 if( m_MicroViasMinSize != aOther.m_MicroViasMinSize ) return false;
1057 if( m_MicroViasMinDrill != aOther.m_MicroViasMinDrill ) return false;
1058 if( m_CopperEdgeClearance != aOther.m_CopperEdgeClearance ) return false;
1059 if( m_HoleClearance != aOther.m_HoleClearance ) return false;
1060 if( m_HoleToHoleMin != aOther.m_HoleToHoleMin ) return false;
1061 if( m_SilkClearance != aOther.m_SilkClearance ) return false;
1062 if( m_MinResolvedSpokes != aOther.m_MinResolvedSpokes ) return false;
1063 if( m_MinSilkTextHeight != aOther.m_MinSilkTextHeight ) return false;
1064 if( m_MinSilkTextThickness != aOther.m_MinSilkTextThickness ) return false;
1065 if( m_DRCSeverities != aOther.m_DRCSeverities ) return false;
1066 if( m_DrcExclusions != aOther.m_DrcExclusions ) return false;
1067 if( m_DrcExclusionComments != aOther.m_DrcExclusionComments ) return false;
1068 if( m_ZoneKeepExternalFillets != aOther.m_ZoneKeepExternalFillets ) return false;
1069 if( m_MaxError != aOther.m_MaxError ) return false;
1070 if( m_SolderMaskExpansion != aOther.m_SolderMaskExpansion ) return false;
1071 if( m_SolderMaskMinWidth != aOther.m_SolderMaskMinWidth ) return false;
1073 if( m_SolderPasteMargin != aOther.m_SolderPasteMargin ) return false;
1074 if( m_SolderPasteMarginRatio != aOther.m_SolderPasteMarginRatio ) return false;
1076 if( m_TentViasFront != aOther.m_TentViasFront ) return false;
1077 if( m_TentViasBack != aOther.m_TentViasBack ) return false;
1078 if( m_DefaultFPTextItems != aOther.m_DefaultFPTextItems ) return false;
1079 if( m_UserLayerNames != aOther.m_UserLayerNames ) return false;
1080
1081 if( !std::equal( std::begin( m_LineThickness ), std::end( m_LineThickness ),
1082 std::begin( aOther.m_LineThickness ) ) )
1083 return false;
1084
1085 if( !std::equal( std::begin( m_TextSize ), std::end( m_TextSize ),
1086 std::begin( aOther.m_TextSize ) ) )
1087 return false;
1088
1089 if( !std::equal( std::begin( m_TextThickness ), std::end( m_TextThickness ),
1090 std::begin( aOther.m_TextThickness ) ) )
1091 return false;
1092
1093 if( !std::equal( std::begin( m_TextItalic ), std::end( m_TextItalic ),
1094 std::begin( aOther.m_TextItalic ) ) )
1095 return false;
1096
1097 if( !std::equal( std::begin( m_TextUpright ), std::end( m_TextUpright ),
1098 std::begin( aOther.m_TextUpright ) ) )
1099 return false;
1100
1101 if( m_DimensionUnitsMode != aOther.m_DimensionUnitsMode ) return false;
1102 if( m_DimensionPrecision != aOther.m_DimensionPrecision ) return false;
1103 if( m_DimensionUnitsFormat != aOther.m_DimensionUnitsFormat ) return false;
1104 if( m_DimensionSuppressZeroes != aOther.m_DimensionSuppressZeroes ) return false;
1105 if( m_DimensionTextPosition != aOther.m_DimensionTextPosition ) return false;
1106 if( m_DimensionKeepTextAligned != aOther.m_DimensionKeepTextAligned ) return false;
1107 if( m_DimensionArrowLength != aOther.m_DimensionArrowLength ) return false;
1108 if( m_DimensionExtensionOffset != aOther.m_DimensionExtensionOffset ) return false;
1109 if( m_auxOrigin != aOther.m_auxOrigin ) return false;
1110 if( m_gridOrigin != aOther.m_gridOrigin ) return false;
1111 if( m_HasStackup != aOther.m_HasStackup ) return false;
1112 if( m_UseHeightForLengthCalcs != aOther.m_UseHeightForLengthCalcs ) return false;
1113 if( m_trackWidthIndex != aOther.m_trackWidthIndex ) return false;
1114 if( m_viaSizeIndex != aOther.m_viaSizeIndex ) return false;
1115 if( m_diffPairIndex != aOther.m_diffPairIndex ) return false;
1116 if( m_useCustomTrackVia != aOther.m_useCustomTrackVia ) return false;
1117 if( m_customTrackWidth != aOther.m_customTrackWidth ) return false;
1118 if( m_customViaSize != aOther.m_customViaSize ) return false;
1119 if( m_useCustomDiffPair != aOther.m_useCustomDiffPair ) return false;
1120 if( m_customDiffPair != aOther.m_customDiffPair ) return false;
1121 if( m_copperLayerCount != aOther.m_copperLayerCount ) return false;
1122 if( m_userDefinedLayerCount != aOther.m_userDefinedLayerCount ) return false;
1123 if( m_enabledLayers != aOther.m_enabledLayers ) return false;
1124 if( m_boardThickness != aOther.m_boardThickness ) return false;
1125 if( m_currentNetClassName != aOther.m_currentNetClassName ) return false;
1126 if( m_stackup != aOther.m_stackup ) return false;
1127 if( *m_NetSettings != *aOther.m_NetSettings ) return false;
1128 if( *m_Pad_Master != *aOther.m_Pad_Master ) return false;
1129 if( m_defaultZoneSettings != aOther.m_defaultZoneSettings ) return false;
1130
1131 if( m_StyleFPFields != aOther.m_StyleFPFields ) return false;
1132 if( m_StyleFPText != aOther.m_StyleFPText ) return false;
1133 if( m_StyleFPShapes != aOther.m_StyleFPShapes ) return false;
1134
1135 return true;
1136}
1137
1138
1140{
1158 std::string units_ptr( "defaults.dimension_units" );
1159 std::string precision_ptr( "defaults.dimension_precision" );
1160
1161 if( !( Contains( units_ptr )
1162 && Contains( precision_ptr )
1163 && At( units_ptr ).is_number_integer()
1164 && At( precision_ptr ).is_number_integer() ) )
1165 {
1166 // if either is missing or invalid, migration doesn't make sense
1167 return true;
1168 }
1169
1170 int units = *Get<int>( units_ptr );
1171 int precision = *Get<int>( precision_ptr );
1172
1173 // The enum maps directly to precision if the units is mils
1174 int extraDigits = 0;
1175
1176 switch( units )
1177 {
1178 case 0: extraDigits = 3; break;
1179 case 2: extraDigits = 2; break;
1180 default: break;
1181 }
1182
1183 precision += extraDigits;
1184
1185 Set( precision_ptr, precision );
1186
1187 return true;
1188}
1189
1190
1191bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
1192{
1193 bool ret = NESTED_SETTINGS::LoadFromFile( aDirectory );
1194
1195 // A number of things won't have been translated by the PROJECT_FILE migration because of
1196 // descoped objects required to decode this data. So, it will be in the legacy.pcbnew
1197 // section and needs to be pulled out here
1198
1199 PROJECT_FILE* project = dynamic_cast<PROJECT_FILE*>( GetParent() );
1200
1201 if( !project )
1202 return ret;
1203
1204 bool migrated = false;
1205
1206 auto drcName =
1207 []( int aCode ) -> std::string
1208 {
1209 std::shared_ptr<DRC_ITEM> item = DRC_ITEM::Create( aCode );
1210 wxString name = item->GetSettingsKey();
1211 return std::string( name.ToUTF8() );
1212 };
1213
1214 const std::string rs = "rule_severities.";
1215 const std::string no_courtyard_key = "legacy_no_courtyard_defined";
1216 const std::string courtyard_overlap_key = "legacy_courtyards_overlap";
1217
1218 try
1219 {
1220 nlohmann::json& severities =
1221 project->Internals()->at( "/board/design_settings/rule_severities"_json_pointer );
1222
1223 if( severities.contains( no_courtyard_key ) )
1224 {
1225 if( severities[no_courtyard_key].get<bool>() )
1226 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "error" );
1227 else
1228 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "ignore" );
1229
1230 severities.erase( no_courtyard_key );
1231 migrated = true;
1232 }
1233
1234 if( severities.contains( courtyard_overlap_key ) )
1235 {
1236 if( severities[courtyard_overlap_key].get<bool>() )
1237 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "error" );
1238 else
1239 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "ignore" );
1240
1241 severities.erase( courtyard_overlap_key );
1242 migrated = true;
1243 }
1244 }
1245 catch( ... )
1246 {
1247 }
1248
1249 if( Contains( "legacy" ) )
1250 {
1251 // This defaults to false for new boards, but version 5.1.x and prior kept the fillets
1252 // so we do the same for legacy boards.
1254
1255 project->At( "legacy" ).erase( "pcbnew" );
1256 }
1257
1258 // Now that we have everything, we need to load again
1259 if( migrated )
1260 Load();
1261
1262 return ret;
1263}
1264
1265
1267{
1268 return m_DRCSeverities[ aDRCErrorCode ];
1269}
1270
1271
1272bool BOARD_DESIGN_SETTINGS::Ignore( int aDRCErrorCode )
1273{
1274 return m_DRCSeverities[ aDRCErrorCode ] == RPT_SEVERITY_IGNORE;
1275}
1276
1277
1279{
1280 int biggest = std::max( m_MinClearance, m_HoleClearance );
1281 DRC_CONSTRAINT constraint;
1282
1283 biggest = std::max( biggest, m_HoleToHoleMin );
1284 biggest = std::max( biggest, m_CopperEdgeClearance );
1285
1286 if( m_DRCEngine )
1287 {
1288 m_DRCEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, constraint );
1289 biggest = std::max( biggest, constraint.Value().Min() );
1290
1291 m_DRCEngine->QueryWorstConstraint( PHYSICAL_CLEARANCE_CONSTRAINT, constraint );
1292 biggest = std::max( biggest, constraint.Value().Min() );
1293
1294 m_DRCEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, constraint );
1295 biggest = std::max( biggest, constraint.Value().Min() );
1296
1297 m_DRCEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, constraint );
1298 biggest = std::max( biggest, constraint.Value().Min() );
1299
1300 m_DRCEngine->QueryWorstConstraint( HOLE_TO_HOLE_CONSTRAINT, constraint );
1301 biggest = std::max( biggest, constraint.Value().Min() );
1302 }
1303
1304 return biggest;
1305}
1306
1307
1309{
1310 int clearance = m_NetSettings->GetDefaultNetclass()->GetClearance();
1311
1312 for( const auto& [name, netclass] : m_NetSettings->GetNetclasses() )
1313 clearance = std::min( clearance, netclass->GetClearance() );
1314
1315 return clearance;
1316}
1317
1318
1320{
1321 m_viaSizeIndex = std::min( aIndex, (unsigned) m_ViasDimensionsList.size() );
1322 m_useCustomTrackVia = false;
1323}
1324
1325
1327{
1330 else if( m_viaSizeIndex == 0 )
1331 return m_NetSettings->GetDefaultNetclass()->GetViaDiameter();
1332 else
1333 return m_ViasDimensionsList[ m_viaSizeIndex ].m_Diameter;
1334}
1335
1336
1338{
1339 int drill;
1340
1342 drill = m_customViaSize.m_Drill;
1343 else if( m_viaSizeIndex == 0 )
1344 drill = m_NetSettings->GetDefaultNetclass()->GetViaDrill();
1345 else
1346 drill = m_ViasDimensionsList[ m_viaSizeIndex ].m_Drill;
1347
1348 return drill > 0 ? drill : -1;
1349}
1350
1351
1353{
1354 m_trackWidthIndex = std::min( aIndex, (unsigned) m_TrackWidthList.size() );
1355 m_useCustomTrackVia = false;
1356}
1357
1358
1360{
1362 return m_customTrackWidth;
1363 else if( m_trackWidthIndex == 0 )
1364 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1365 else
1367}
1368
1369
1371{
1372 if( !m_DiffPairDimensionsList.empty() )
1373 {
1374 m_diffPairIndex = std::min( aIndex,
1375 static_cast<unsigned>( m_DiffPairDimensionsList.size() ) - 1 );
1376 }
1377
1378 m_useCustomDiffPair = false;
1379}
1380
1381
1383{
1385 {
1387 }
1388 else if( m_diffPairIndex == 0 )
1389 {
1390 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairWidth() )
1391 return m_NetSettings->GetDefaultNetclass()->GetDiffPairWidth();
1392 else
1393 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1394 }
1395 else
1396 {
1398 }
1399}
1400
1401
1403{
1405 {
1406 return m_customDiffPair.m_Gap;
1407 }
1408 else if( m_diffPairIndex == 0 )
1409 {
1410 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairGap() )
1411 return m_NetSettings->GetDefaultNetclass()->GetDiffPairGap();
1412 else
1413 return m_NetSettings->GetDefaultNetclass()->GetClearance();
1414 }
1415 else
1416 {
1418 }
1419}
1420
1421
1423{
1425 {
1427 }
1428 else if( m_diffPairIndex == 0 )
1429 {
1430 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairViaGap() )
1431 return m_NetSettings->GetDefaultNetclass()->GetDiffPairViaGap();
1432 else
1433 return GetCurrentDiffPairGap();
1434 }
1435 else
1436 {
1438 }
1439}
1440
1441
1443{
1444 m_copperLayerCount = aNewLayerCount;
1445
1446 // Update only enabled copper layers mask
1448
1449 if( aNewLayerCount > 0 )
1450 m_enabledLayers |= LSET::AllCuMask( aNewLayerCount );
1451}
1452
1453
1455{
1456 m_userDefinedLayerCount = aNewLayerCount;
1457
1459
1460 if( aNewLayerCount > 0 )
1461 m_enabledLayers |= LSET::UserDefinedLayersMask( aNewLayerCount );
1462}
1463
1464
1466{
1467 // Ensures mandatory back and front layers are always enabled regardless of board file
1468 // configuration.
1469 aMask.set( B_Cu ).set( F_Cu )
1470 .set( B_CrtYd ).set( F_CrtYd )
1471 .set( Edge_Cuts )
1472 .set( Margin );
1473
1474 m_enabledLayers = aMask;
1475
1476 // update layer counts to ensure their consistency with m_EnabledLayers
1477 m_copperLayerCount = (int) aMask.ClearNonCopperLayers().count();
1478 m_userDefinedLayerCount = (int) ( aMask & LSET::UserDefinedLayersMask() ).count();
1479}
1480
1481
1482// Return the layer class index { silk, copper, edges & courtyards, fab, others } of the
1483// given layer.
1485{
1486 if( aLayer == F_SilkS || aLayer == B_SilkS )
1487 return LAYER_CLASS_SILK;
1488 else if( IsCopperLayer( aLayer ) )
1489 return LAYER_CLASS_COPPER;
1490 else if( aLayer == Edge_Cuts )
1491 return LAYER_CLASS_EDGES;
1492 else if( aLayer == F_CrtYd || aLayer == B_CrtYd )
1493 return LAYER_CLASS_COURTYARD;
1494 else if( aLayer == F_Fab || aLayer == B_Fab )
1495 return LAYER_CLASS_FAB;
1496 else
1497 return LAYER_CLASS_OTHERS;
1498}
1499
1500
1502{
1503 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
1504}
1505
1506
1508{
1509 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
1510}
1511
1512
1514{
1515 return m_LineThickness[ GetLayerClass( aLayer ) ];
1516}
1517
1518
1520{
1521 return m_TextSize[ GetLayerClass( aLayer ) ];
1522}
1523
1524
1526{
1527 return m_TextThickness[ GetLayerClass( aLayer ) ];
1528}
1529
1530
1532{
1533 return m_TextItalic[ GetLayerClass( aLayer ) ];
1534}
1535
1536
1538{
1539 return m_TextUpright[ GetLayerClass( aLayer ) ];
1540}
1541
1543{
1546 m_Pad_Master->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
1548 m_Pad_Master->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::ROUNDRECT );
1549
1550 constexpr double RR_RADIUS = DEFAULT_PAD_HEIGTH_MM / DEFAULT_PAD_RR_RADIUS_RATIO;
1551 m_Pad_Master->SetRoundRectCornerRadius( PADSTACK::ALL_LAYERS, pcbIUScale.mmToIU( RR_RADIUS ) );
1552}
const char * name
Definition: DXF_plotter.cpp:59
constexpr int ARC_HIGH_DEF
Definition: base_units.h:120
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
const int bdsSchemaVersion
#define DEFAULT_MICROVIASMINDRILL
#define DEFAULT_SOLDERPASTE_CLEARANCE
#define DEFAULT_SOLDERPASTE_RATIO
#define DEFAULT_CUSTOMDPAIRWIDTH
#define DEFAULT_DP_MEANDER_SPACING
#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 DEFAULT_HOLECLEARANCE
#define DEFAULT_SOLDERMASK_EXPANSION
#define DEFAULT_SOLDERMASK_MIN_WIDTH
#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 DEFAULT_HOLETOHOLEMIN
#define DEFAULT_MINCONNECTION
#define DEFAULT_COPPER_LINE_WIDTH
#define DEFAULT_SILK_LINE_WIDTH
#define DEFAULT_SILKCLEARANCE
#define DEFAULT_MICROVIASMINSIZE
@ LAYER_CLASS_OTHERS
@ LAYER_CLASS_FAB
@ LAYER_CLASS_COURTYARD
@ LAYER_CLASS_SILK
@ LAYER_CLASS_COPPER
@ LAYER_CLASS_EDGES
#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
Container for design settings for a BOARD object.
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 SetDiffPairIndex(unsigned aIndex)
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
wxString m_currentNetClassName
Current net class name used to display netclass info.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
void SetEnabledLayers(LSET aMask)
Change the bit-mask of enabled layers to aMask.
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
void SetTrackWidthIndex(unsigned aIndex)
Set the current track width list index to aIndex.
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.
void SetViaSizeIndex(unsigned aIndex)
Set the current via size list index to aIndex.
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
int m_TextThickness[LAYER_CLASS_COUNT]
ZONE_SETTINGS m_defaultZoneSettings
The default settings that will be used for new zones.
SEVERITY GetSeverity(int aDRCErrorCode)
std::vector< int > m_TrackWidthList
DIFF_PAIR_DIMENSION m_customDiffPair
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.
DIM_UNITS_MODE m_DimensionUnitsMode
std::vector< VIA_DIMENSION > m_ViasDimensionsList
BOARD_DESIGN_SETTINGS & operator=(const BOARD_DESIGN_SETTINGS &aOther)
MINOPTMAX< int > & Value()
Definition: drc_rule.h:153
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities(bool aIncludeDeprecated=false)
Definition: drc_item.h:133
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition: drc_item.cpp:395
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::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...
void ReleaseNestedSettings(NESTED_SETTINGS *aSettings)
Saves and frees a nested settings object, if it exists within this one.
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
LSET & ClearUserDefinedLayers()
Clear the user defined layers in this set.
Definition: lset.cpp:918
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:564
LSET & ClearNonCopperLayers()
Clear the non-copper layers in this set.
Definition: lset.cpp:909
LSET & ClearCopperLayers()
Clear the copper layers in this set.
Definition: lset.cpp:900
static LSET UserDefinedLayersMask(int aUserDefinedLayerCount=MAX_USER_DEFINED_LAYERS)
Return a mask with the requested number of user defined layers.
Definition: lset.cpp:657
T Min() const
Definition: minoptmax.h:33
NESTED_SETTINGS is a JSON_SETTINGS that lives inside a JSON_SETTINGS.
JSON_SETTINGS * GetParent()
JSON_SETTINGS * m_parent
A pointer to the parent object to load and store from.
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:144
Stores an enum as an integer.
Definition: parameters.h:228
Like a normal param, but with custom getter and setter functions.
Definition: parameters.h:295
Represents a parameter that has a scaling factor between the value in the file and the value used int...
Definition: parameters.h:392
Dimensions for the meandering algorithm.
Definition: pns_meander.h:68
int m_minAmplitude
Maximum meandering amplitude.
Definition: pns_meander.h:83
int m_cornerRadiusPercentage
Place meanders on one side.
Definition: pns_meander.h:109
bool m_singleSided
Initial side when placing meanders at segment.
Definition: pns_meander.h:112
MEANDER_STYLE m_cornerStyle
Rounding percentage (0 - 100).
Definition: pns_meander.h:106
int m_maxAmplitude
Meandering period/spacing (see dialog picture for explanation).
Definition: pns_meander.h:86
int m_spacing
Amplitude/spacing adjustment step.
Definition: pns_meander.h:89
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:72
A holder for a rule check item, DRC in Pcbnew or ERC in Eeschema.
Definition: rc_item.h:79
bool m_UseRoundShapesOnly
True to create teardrops for round shapes only.
bool m_TargetVias
True to create teardrops for vias.
bool m_TargetPTHPads
True to create teardrops for pads with holes.
bool m_TargetTrack2Track
True to create teardrops at the end of a track connected to the end of another track having a differe...
TEARDROP_PARAMETERS * GetParameters(TARGET_TD aTdType)
bool m_TargetSMDPads
True to create teardrops for pads SMD, edge connectors,.
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_SILK_EDGE_CLEARANCE
Definition: drc_item.h:98
@ DRCE_FOOTPRINT_FILTERS
Definition: drc_item.h:79
@ DRCE_PADSTACK
Definition: drc_item.h:62
@ DRCE_MIRRORED_TEXT_ON_FRONT_LAYER
Definition: drc_item.h:109
@ DRCE_LIB_FOOTPRINT_ISSUES
Definition: drc_item.h:82
@ DRCE_OVERLAPPING_FOOTPRINTS
Definition: drc_item.h:65
@ DRCE_OVERLAPPING_SILK
Definition: drc_item.h:101
@ DRCE_MISSING_COURTYARD
Definition: drc_item.h:66
@ DRCE_ISOLATED_COPPER
Definition: drc_item.h:48
@ DRCE_DRILLED_HOLES_TOO_CLOSE
Definition: drc_item.h:52
@ DRCE_COPPER_SLIVER
Definition: drc_item.h:92
@ DRCE_PTH_IN_COURTYARD
Definition: drc_item.h:69
@ DRCE_FIRST
Definition: drc_item.h:38
@ DRCE_DANGLING_VIA
Definition: drc_item.h:50
@ DRCE_FOOTPRINT_TYPE_MISMATCH
Definition: drc_item.h:81
@ DRCE_NONMIRRORED_TEXT_ON_BACK_LAYER
Definition: drc_item.h:110
@ DRCE_DUPLICATE_FOOTPRINT
Definition: drc_item.h:75
@ DRCE_DANGLING_TRACK
Definition: drc_item.h:51
@ DRCE_TEXT_HEIGHT
Definition: drc_item.h:99
@ DRCE_DRILLED_HOLES_COLOCATED
Definition: drc_item.h:53
@ DRCE_EXTRA_FOOTPRINT
Definition: drc_item.h:76
@ DRCE_SILK_CLEARANCE
Definition: drc_item.h:96
@ DRCE_LAST
Definition: drc_item.h:112
@ DRCE_LIB_FOOTPRINT_MISMATCH
Definition: drc_item.h:83
@ DRCE_NET_CONFLICT
Definition: drc_item.h:77
@ DRCE_MISSING_FOOTPRINT
Definition: drc_item.h:74
@ DRCE_TEXT_THICKNESS
Definition: drc_item.h:100
@ DRCE_NPTH_IN_COURTYARD
Definition: drc_item.h:70
@ DRCE_CONNECTION_WIDTH
Definition: drc_item.h:59
@ DRCE_SCHEMATIC_PARITY
Definition: drc_item.h:78
@ EDGE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:53
@ CLEARANCE_CONSTRAINT
Definition: drc_rule.h:49
@ HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:51
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:74
@ HOLE_TO_HOLE_CONSTRAINT
Definition: drc_rule.h:52
#define TEXT_MIN_SIZE_MM
Minimum text size (1 micron).
Definition: eda_text.h:47
#define TEXT_MAX_SIZE_MM
Maximum text size in mm (~10 inches)
Definition: eda_text.h:48
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:618
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ F_CrtYd
Definition: layer_ids.h:116
@ Edge_Cuts
Definition: layer_ids.h:112
@ B_Cu
Definition: layer_ids.h:65
@ F_Fab
Definition: layer_ids.h:119
@ Margin
Definition: layer_ids.h:113
@ F_SilkS
Definition: layer_ids.h:100
@ B_CrtYd
Definition: layer_ids.h:115
@ B_SilkS
Definition: layer_ids.h:101
@ F_Cu
Definition: layer_ids.h:64
@ B_Fab
Definition: layer_ids.h:118
@ MEANDER_STYLE_ROUND
Definition: pns_meander.h:52
@ MEANDER_STYLE_CHAMFER
Definition: pns_meander.h:53
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_IGNORE
Container to handle a stock of specific differential pairs each with unique track width,...
constexpr double IUTomm(int iu) const
Definition: base_units.h:86
const double IU_PER_MM
Definition: base_units.h:76
const double MM_PER_IU
Definition: base_units.h:78
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
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
wxString SeverityToString(const SEVERITY &aSeverity)
Definition: ui_common.cpp:66
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695
#define ZONE_CLEARANCE_MM
Definition: zones.h:37