KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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 m_CoverViasFront = false;
226 m_CoverViasBack = false;
227
228 m_PlugViasFront = false;
229 m_PlugViasBack = false;
230
231 m_CapVias = false;
232
233 m_FillVias = false;
234
235 // Layer thickness for 3D viewer
237
238 // Default spacing for meanders
242
243 m_viaSizeIndex = 0;
245 m_diffPairIndex = 0;
246
247 // Parameters stored in JSON in the project file
248
249 // NOTE: Previously, BOARD_DESIGN_SETTINGS stored the basic board layer information (layer
250 // names and enable/disable state) in the project file even though this information is also
251 // stored in the board file. This was implemented for importing these settings from another
252 // project. Going forward, the import feature will just import from other board files (since
253 // we could have multi-board projects in the future anyway) so this functionality is dropped.
254
255
256 m_params.emplace_back( new PARAM<bool>( "rules.use_height_for_length_calcs",
257 &m_UseHeightForLengthCalcs, true ) );
258
259 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_clearance",
262
263 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_connection",
265 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
266
267 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_track_width",
270
271 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_annular_width",
274
275 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_diameter",
278
279 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_through_hole_diameter",
282
283 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_diameter",
286
287 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_drill",
290
291 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_to_hole",
294
295 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_clearance",
297 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
298
299 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_silk_clearance",
301 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
302
303 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_groove_width",
306
307 // While the maximum *effective* value is 4, we've had users interpret this as the count on
308 // all layers, and enter something like 10. They'll figure it out soon enough *unless* we
309 // enforce a max of 4 (and therefore reset it back to the default of 2), at which point it
310 // just looks buggy.
311 m_params.emplace_back( new PARAM<int>( "rules.min_resolved_spokes",
313
314 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_height",
316 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
317
318 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_thickness",
321
322 // Note: a clearance of -0.01 is a flag indicating we should use the legacy (pre-6.0) method
323 // based on the edge cut thicknesses.
324 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_copper_edge_clearance",
326 pcbIUScale.mmToIU( -0.01 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
327
328 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
329 [&]() -> nlohmann::json
330 {
331 nlohmann::json ret = {};
332
333 for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
334 {
335 wxString name = item.GetSettingsKey();
336 int code = item.GetErrorCode();
337
338 if( name.IsEmpty() || m_DRCSeverities.count( code ) == 0 )
339 continue;
340
341 ret[std::string( name.ToUTF8() )] = SeverityToString( m_DRCSeverities[code] );
342 }
343
344 return ret;
345 },
346 [&]( const nlohmann::json& aJson )
347 {
348 if( !aJson.is_object() )
349 return;
350
351 for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities( true ) )
352 {
353 wxString name = item.GetSettingsKey();
354 std::string key( name.ToUTF8() );
355
356 if( aJson.contains( key ) )
357 m_DRCSeverities[item.GetErrorCode()] = SeverityFromString( aJson[key] );
358 }
359 }, {} ) );
360
361 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "drc_exclusions",
362 [&]() -> nlohmann::json
363 {
364 nlohmann::json js = nlohmann::json::array();
365
366 for( const wxString& entry : m_DrcExclusions )
367 js.push_back( { entry, m_DrcExclusionComments[ entry ] } );
368
369 return js;
370 },
371 [&]( const nlohmann::json& aObj )
372 {
373 m_DrcExclusions.clear();
374
375 if( !aObj.is_array() )
376 return;
377
378 for( const nlohmann::json& entry : aObj )
379 {
380 if( entry.is_array() )
381 {
382 wxString serialized = entry[0].get<wxString>();
383 m_DrcExclusions.insert( serialized );
384 m_DrcExclusionComments[ serialized ] = entry[1].get<wxString>();
385 }
386 else if( entry.is_string() )
387 {
388 m_DrcExclusions.insert( entry.get<wxString>() );
389 }
390 }
391 },
392 {} ) );
393
394 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "track_widths",
395 [&]() -> nlohmann::json
396 {
397 nlohmann::json js = nlohmann::json::array();
398
399 for( const int& width : m_TrackWidthList )
400 js.push_back( pcbIUScale.IUTomm( width ) );
401
402 return js;
403 },
404 [&]( const nlohmann::json& aJson )
405 {
406 if( !aJson.is_array() )
407 return;
408
409 m_TrackWidthList.clear();
410
411 for( const nlohmann::json& entry : aJson )
412 {
413 if( entry.empty() )
414 continue;
415
416 m_TrackWidthList.emplace_back( pcbIUScale.mmToIU( entry.get<double>() ) );
417 }
418 },
419 {} ) );
420
421 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "via_dimensions",
422 [&]() -> nlohmann::json
423 {
424 nlohmann::json js = nlohmann::json::array();
425
426 for( const auto& via : m_ViasDimensionsList )
427 {
428 nlohmann::json entry = {};
429
430 entry["diameter"] = pcbIUScale.IUTomm( via.m_Diameter );
431 entry["drill"] = pcbIUScale.IUTomm( via.m_Drill );
432
433 js.push_back( entry );
434 }
435
436 return js;
437 },
438 [&]( const nlohmann::json& aObj )
439 {
440 if( !aObj.is_array() )
441 return;
442
443 m_ViasDimensionsList.clear();
444
445 for( const nlohmann::json& entry : aObj )
446 {
447 if( entry.empty() || !entry.is_object() )
448 continue;
449
450 if( !entry.contains( "diameter" ) || !entry.contains( "drill" ) )
451 continue;
452
453 int diameter = pcbIUScale.mmToIU( entry["diameter"].get<double>() );
454 int drill = pcbIUScale.mmToIU( entry["drill"].get<double>() );
455
456 m_ViasDimensionsList.emplace_back( VIA_DIMENSION( diameter, drill ) );
457 }
458 },
459 {} ) );
460
461 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "diff_pair_dimensions",
462 [&]() -> nlohmann::json
463 {
464 nlohmann::json js = nlohmann::json::array();
465
466 for( const auto& pair : m_DiffPairDimensionsList )
467 {
468 nlohmann::json entry = {};
469
470 entry["width"] = pcbIUScale.IUTomm( pair.m_Width );
471 entry["gap"] = pcbIUScale.IUTomm( pair.m_Gap );
472 entry["via_gap"] = pcbIUScale.IUTomm( pair.m_ViaGap );
473
474 js.push_back( entry );
475 }
476
477 return js;
478 },
479 [&]( const nlohmann::json& aObj )
480 {
481 if( !aObj.is_array() )
482 return;
483
485
486 for( const nlohmann::json& entry : aObj )
487 {
488 if( entry.empty() || !entry.is_object() )
489 continue;
490
491 if( !entry.contains( "width" )
492 || !entry.contains( "gap" )
493 || !entry.contains( "via_gap" ) )
494 {
495 continue;
496 }
497
498 int width = pcbIUScale.mmToIU( entry["width"].get<double>() );
499 int gap = pcbIUScale.mmToIU( entry["gap"].get<double>() );
500 int via_gap = pcbIUScale.mmToIU( entry["via_gap"].get<double>() );
501
502 m_DiffPairDimensionsList.emplace_back( DIFF_PAIR_DIMENSION( width, gap, via_gap ) );
503 }
504 },
505 {} ) );
506
507 // Handle options for teardrops (targets and some others):
508 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_options",
509 [&]() -> nlohmann::json
510 {
511 nlohmann::json js = nlohmann::json::array();
512 nlohmann::json entry = {};
513
514 entry["td_onvia"] = m_TeardropParamsList.m_TargetVias;
515 entry["td_onpthpad"] = m_TeardropParamsList.m_TargetPTHPads;
516 entry["td_onsmdpad"] = m_TeardropParamsList.m_TargetSMDPads;
517 entry["td_ontrackend"] = m_TeardropParamsList.m_TargetTrack2Track;
518 entry["td_onroundshapesonly"] = m_TeardropParamsList.m_UseRoundShapesOnly;
519
520 js.push_back( entry );
521
522 return js;
523 },
524 [&]( const nlohmann::json& aObj )
525 {
526 if( !aObj.is_array() )
527 return;
528
529 for( const nlohmann::json& entry : aObj )
530 {
531 if( entry.empty() || !entry.is_object() )
532 continue;
533
534 if( entry.contains( "td_onvia" ) )
535 m_TeardropParamsList.m_TargetVias = entry["td_onvia"].get<bool>();
536
537 if( entry.contains( "td_onpthpad" ) )
538 m_TeardropParamsList.m_TargetPTHPads = entry["td_onpthpad"].get<bool>();
539
540 if( entry.contains( "td_onsmdpad" ) )
541 m_TeardropParamsList.m_TargetSMDPads = entry["td_onsmdpad"].get<bool>();
542
543 if( entry.contains( "td_ontrackend" ) )
544 m_TeardropParamsList.m_TargetTrack2Track = entry["td_ontrackend"].get<bool>();
545
546 if( entry.contains( "td_onroundshapesonly" ) )
547 m_TeardropParamsList.m_UseRoundShapesOnly = entry["td_onroundshapesonly"].get<bool>();
548
549 // Legacy settings
550 for( int ii = 0; ii < 3; ++ii )
551 {
553
554 if( entry.contains( "td_allow_use_two_tracks" ) )
555 td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
556
557 if( entry.contains( "td_curve_segcount" ) )
558 {
559 if( entry["td_curve_segcount"].get<int>() > 0 )
560 td_prm->m_CurvedEdges = true;
561 }
562
563 if( entry.contains( "td_on_pad_in_zone" ) )
564 td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
565 }
566 }
567 },
568 {} ) );
569
570 // Handle parameters (sizes, shape) for each type of teardrop:
571 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_parameters",
572 [&]() -> nlohmann::json
573 {
574 nlohmann::json js = nlohmann::json::array();
575
576 for( size_t ii = 0; ii < m_TeardropParamsList.GetParametersCount(); ii++ )
577 {
578 nlohmann::json entry = {};
580
581 entry["td_target_name"] = GetTeardropTargetCanonicalName( (TARGET_TD)ii );
582 entry["td_maxlen"] = pcbIUScale.IUTomm( td_prm->m_TdMaxLen );
583 entry["td_maxheight"] = pcbIUScale.IUTomm( td_prm->m_TdMaxWidth );
584 entry["td_length_ratio"] = td_prm->m_BestLengthRatio;
585 entry["td_height_ratio"] = td_prm->m_BestWidthRatio;
586 entry["td_curve_segcount"] = td_prm->m_CurvedEdges ? 1 : 0;
587 entry["td_width_to_size_filter_ratio"] = td_prm->m_WidthtoSizeFilterRatio;
588 entry["td_allow_use_two_tracks"] = td_prm->m_AllowUseTwoTracks;
589 entry["td_on_pad_in_zone"] = td_prm->m_TdOnPadsInZones;
590
591 js.push_back( entry );
592 }
593
594 return js;
595 },
596 [&]( const nlohmann::json& aObj )
597 {
598 if( !aObj.is_array() )
599 return;
600
601 for( const nlohmann::json& entry : aObj )
602 {
603 if( entry.empty() || !entry.is_object() )
604 continue;
605
606 if( !entry.contains( "td_target_name" ) )
607 continue;
608
609 int idx = GetTeardropTargetTypeFromCanonicalName( entry["td_target_name"].get<std::string>() );
610
611 if( idx >= 0 && idx < 3 )
612 {
614
615 if( entry.contains( "td_maxlen" ) )
616 td_prm->m_TdMaxLen = pcbIUScale.mmToIU( entry["td_maxlen"].get<double>() );
617
618 if( entry.contains( "td_maxheight" ) )
619 td_prm->m_TdMaxWidth = pcbIUScale.mmToIU( entry["td_maxheight"].get<double>() );
620
621 if( entry.contains( "td_length_ratio" ) )
622 td_prm->m_BestLengthRatio = entry["td_length_ratio"].get<double>();
623
624 if( entry.contains( "td_height_ratio" ) )
625 td_prm->m_BestWidthRatio = entry["td_height_ratio"].get<double>();
626
627 if( entry.contains( "td_curve_segcount" ) )
628 {
629 if( entry["td_curve_segcount"].get<int>() > 0 )
630 td_prm->m_CurvedEdges = true;
631 }
632
633 if( entry.contains( "td_width_to_size_filter_ratio" ) )
634 td_prm->m_WidthtoSizeFilterRatio = entry["td_width_to_size_filter_ratio"].get<double>();
635
636 if( entry.contains( "td_allow_use_two_tracks" ) )
637 td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
638
639 if( entry.contains( "td_on_pad_in_zone" ) )
640 td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
641 }
642 }
643 },
644 {} ) );
645
646 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "tuning_pattern_settings",
647 [&]() -> nlohmann::json
648 {
649 nlohmann::json js = {};
650
651 auto make_settings =
652 []( const PNS::MEANDER_SETTINGS& aSettings )
653 {
654 nlohmann::json entry = {};
655
656 entry["min_amplitude"] = pcbIUScale.IUTomm( aSettings.m_minAmplitude );
657 entry["max_amplitude"] = pcbIUScale.IUTomm( aSettings.m_maxAmplitude );
658 entry["spacing"] = pcbIUScale.IUTomm( aSettings.m_spacing );
659 entry["corner_style"] = aSettings.m_cornerStyle == PNS::MEANDER_STYLE_CHAMFER ? 0 : 1;
660 entry["corner_radius_percentage"] = aSettings.m_cornerRadiusPercentage;
661 entry["single_sided"] = aSettings.m_singleSided;
662
663 return entry;
664 };
665
666 js["single_track_defaults"] = make_settings( m_SingleTrackMeanderSettings );
667 js["diff_pair_defaults"] = make_settings( m_DiffPairMeanderSettings );
668 js["diff_pair_skew_defaults"] = make_settings( m_SkewMeanderSettings );
669
670 return js;
671 },
672 [&]( const nlohmann::json& aObj )
673 {
674 auto read_settings =
675 []( const nlohmann::json& entry ) -> PNS::MEANDER_SETTINGS
676 {
677 PNS::MEANDER_SETTINGS settings;
678
679 if( entry.contains( "min_amplitude" ) )
680 settings.m_minAmplitude = pcbIUScale.mmToIU( entry["min_amplitude"].get<double>() );
681
682 if( entry.contains( "max_amplitude" ) )
683 settings.m_maxAmplitude = pcbIUScale.mmToIU( entry["max_amplitude"].get<double>() );
684
685 if( entry.contains( "spacing" ) )
686 settings.m_spacing = pcbIUScale.mmToIU( entry["spacing"].get<double>() );
687
688 if( entry.contains( "corner_style" ) )
689 {
690 settings.m_cornerStyle = entry["corner_style"] == 0 ? PNS::MEANDER_STYLE_CHAMFER
692 }
693
694 if( entry.contains( "corner_radius_percentage" ) )
695 settings.m_cornerRadiusPercentage = entry["corner_radius_percentage"].get<int>();
696
697 if( entry.contains( "single_sided" ) )
698 settings.m_singleSided = entry["single_sided"].get<bool>();
699
700 return settings;
701 };
702
703 if( aObj.contains( "single_track_defaults" ) )
704 m_SingleTrackMeanderSettings = read_settings( aObj["single_track_defaults"] );
705
706 if( aObj.contains( "diff_pair_defaults" ) )
707 m_DiffPairMeanderSettings = read_settings( aObj["diff_pair_defaults"] );
708
709 if( aObj.contains( "diff_pair_skew_defaults" ) )
710 m_SkewMeanderSettings = read_settings( aObj["diff_pair_skew_defaults"] );
711 },
712 {} ) );
713
714 int minTextSize = pcbIUScale.mmToIU( TEXT_MIN_SIZE_MM );
715 int maxTextSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
716 int minStroke = 1;
717 int maxStroke = pcbIUScale.mmToIU( 100 );
718
719 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_line_width",
721 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
722
723 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_v",
725 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
726
727 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_h",
729 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
730
731 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_thickness",
733 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
734
735 m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_italic",
736 &m_TextItalic[LAYER_CLASS_SILK], false ) );
737
738 m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_upright",
739 &m_TextUpright[ LAYER_CLASS_SILK ], true ) );
740
741 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_line_width",
743 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
744
745 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_v",
747 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
748
749 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_h",
751 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
752
753 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_thickness",
755 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
756
757 m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_italic",
758 &m_TextItalic[LAYER_CLASS_COPPER], false ) );
759
760 m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_upright",
762
763 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.board_outline_line_width",
765 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
766
767 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.courtyard_line_width",
769 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
770
771 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_line_width",
773 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
774
775 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_v",
777 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
778
779 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_h",
781 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
782
783 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_thickness",
785 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
786
787 m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_italic",
788 &m_TextItalic[LAYER_CLASS_FAB], false ) );
789
790 m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_upright",
791 &m_TextUpright[LAYER_CLASS_FAB], true ) );
792
793 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_line_width",
795 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
796
797 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_v",
799 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
800
801 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_h",
803 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
804
805 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_thickness",
807 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
808
809 m_params.emplace_back( new PARAM<bool>( "defaults.other_text_italic",
810 &m_TextItalic[LAYER_CLASS_OTHERS], false ) );
811
812 m_params.emplace_back( new PARAM<bool>( "defaults.other_text_upright",
814
815 m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_MODE>( "defaults.dimension_units",
816 &m_DimensionUnitsMode, DIM_UNITS_MODE::AUTOMATIC, DIM_UNITS_MODE::INCH,
817 DIM_UNITS_MODE::AUTOMATIC ) );
818
819 m_params.emplace_back( new PARAM_ENUM<DIM_PRECISION>( "defaults.dimension_precision",
820 &m_DimensionPrecision, DIM_PRECISION::X_XXXX, DIM_PRECISION::X, DIM_PRECISION::V_VVVVV ) );
821
822 m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_FORMAT>( "defaults.dimensions.units_format",
823 &m_DimensionUnitsFormat, DIM_UNITS_FORMAT::NO_SUFFIX, DIM_UNITS_FORMAT::NO_SUFFIX,
824 DIM_UNITS_FORMAT::PAREN_SUFFIX ) );
825
826 m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.suppress_zeroes",
827 &m_DimensionSuppressZeroes, true ) );
828
829 // NOTE: excluding DIM_TEXT_POSITION::MANUAL from the valid range here
830 m_params.emplace_back( new PARAM_ENUM<DIM_TEXT_POSITION>( "defaults.dimensions.text_position",
831 &m_DimensionTextPosition, DIM_TEXT_POSITION::OUTSIDE, DIM_TEXT_POSITION::OUTSIDE,
832 DIM_TEXT_POSITION::INLINE ) );
833
834 m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.keep_text_aligned",
836
837 m_params.emplace_back( new PARAM<int>( "defaults.dimensions.arrow_length",
840
841 m_params.emplace_back( new PARAM<int>( "defaults.dimensions.extension_offset",
844
845 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_fields",
846 &m_StyleFPFields, false ) );
847 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_text",
848 &m_StyleFPText, false ) );
849 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_shapes",
850 &m_StyleFPShapes, false ) );
851
852 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.zones.min_clearance",
855
856 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "defaults.pads",
857 [&]() -> nlohmann::json
858 {
859 nlohmann::json ret =
860 {
861 { "width", pcbIUScale.IUTomm( m_Pad_Master->GetSize( PADSTACK::ALL_LAYERS ).x ) },
862 { "height", pcbIUScale.IUTomm( m_Pad_Master->GetSize( PADSTACK::ALL_LAYERS ).y ) },
863 { "drill", pcbIUScale.IUTomm( m_Pad_Master->GetDrillSize().x ) }
864 };
865
866 return ret;
867 },
868 [&]( const nlohmann::json& aJson )
869 {
870 if( aJson.contains( "width" ) && aJson.contains( "height" )
871 && aJson.contains( "drill" ) )
872 {
873 VECTOR2I sz;
874 sz.x = pcbIUScale.mmToIU( aJson["width"].get<double>() );
875 sz.y = pcbIUScale.mmToIU( aJson["height"].get<double>() );
876
877 m_Pad_Master->SetSize( PADSTACK::ALL_LAYERS, sz );
878
879 int drill = pcbIUScale.mmToIU( aJson["drill"].get<double>() );
880
881 m_Pad_Master->SetDrillSize( VECTOR2I( drill, drill ) );
882 }
883 }, {} ) );
884
885 m_params.emplace_back( new PARAM_SCALED<int>( "rules.max_error",
887 pcbIUScale.mmToIU( 0.0001 ), pcbIUScale.mmToIU( 1.0 ), pcbIUScale.MM_PER_IU ) );
888
889 m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_mask_to_copper_clearance",
892
893 m_params.emplace_back( new PARAM<bool>( "zones_allow_external_fillets",
894 &m_ZoneKeepExternalFillets, false ) );
895
897
898 registerMigration( 1, 2,
899 [&]() -> bool
900 {
901 // Schema 1 to 2: move mask and paste margin settings back to board.
902 // The parameters are removed, so we just have to manually load them here and
903 // they will get saved with the board
904 if( std::optional<double> optval = Get<double>( "rules.solder_mask_clearance" ) )
905 m_SolderMaskExpansion = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
906
907 if( std::optional<double> optval = Get<double>( "rules.solder_mask_min_width" ) )
908 m_SolderMaskMinWidth = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
909
910 if( std::optional<double> optval = Get<double>( "rules.solder_paste_clearance" ) )
911 m_SolderPasteMargin = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
912
913 if( std::optional<double> optval = Get<double>( "rules.solder_paste_margin_ratio" ) )
914 m_SolderPasteMarginRatio = *optval;
915
916 try
917 {
918 At( "rules" ).erase( "solder_mask_clearance" );
919 At( "rules" ).erase( "solder_mask_min_width" );
920 At( "rules" ).erase( "solder_paste_clearance" );
921 At( "rules" ).erase( "solder_paste_margin_ratio" );
922 }
923 catch( ... )
924 {}
925
926 return true;
927 } );
928}
929
930
932{
933 if( m_parent )
934 {
936 m_parent = nullptr;
937 }
938}
939
940
942 NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aOther.m_parent,
943 aOther.m_path ),
944 m_Pad_Master( nullptr )
945{
946 initFromOther( aOther );
947}
948
949
951{
952 initFromOther( aOther );
953 return *this;
954}
955
956
958{
959 // Copy of NESTED_SETTINGS around is not allowed, so let's just update the params.
968 m_MinConn = aOther.m_MinConn;
986 m_MaxError = aOther.m_MaxError;
997
998 std::copy( std::begin( aOther.m_LineThickness ), std::end( aOther.m_LineThickness ),
999 std::begin( m_LineThickness ) );
1000
1001 std::copy( std::begin( aOther.m_TextSize ), std::end( aOther.m_TextSize ),
1002 std::begin( m_TextSize ) );
1003
1004 std::copy( std::begin( aOther.m_TextThickness ), std::end( aOther.m_TextThickness ),
1005 std::begin( m_TextThickness ) );
1006
1007 std::copy( std::begin( aOther.m_TextItalic ), std::end( aOther.m_TextItalic ),
1008 std::begin( m_TextItalic ) );
1009
1010 std::copy( std::begin( aOther.m_TextUpright ), std::end( aOther.m_TextUpright ),
1011 std::begin( m_TextUpright ) );
1012
1021
1022 m_auxOrigin = aOther.m_auxOrigin;
1023 m_gridOrigin = aOther.m_gridOrigin;
1024 m_HasStackup = aOther.m_HasStackup;
1026
1040 m_stackup = aOther.m_stackup;
1042 m_Pad_Master = std::make_unique<PAD>( *aOther.m_Pad_Master );
1044
1048}
1049
1050
1052{
1053 if( m_TrackWidthList != aOther.m_TrackWidthList ) return false;
1054 if( m_ViasDimensionsList != aOther.m_ViasDimensionsList ) return false;
1055 if( m_DiffPairDimensionsList != aOther.m_DiffPairDimensionsList ) return false;
1056 if( m_CurrentViaType != aOther.m_CurrentViaType ) return false;
1057 if( m_UseConnectedTrackWidth != aOther.m_UseConnectedTrackWidth ) return false;
1058 if( m_TempOverrideTrackWidth != aOther.m_TempOverrideTrackWidth ) return false;
1059 if( m_MinClearance != aOther.m_MinClearance ) return false;
1060 if( m_MinGrooveWidth != aOther.m_MinGrooveWidth ) return false;
1061 if( m_MinConn != aOther.m_MinConn ) return false;
1062 if( m_TrackMinWidth != aOther.m_TrackMinWidth ) return false;
1063 if( m_ViasMinAnnularWidth != aOther.m_ViasMinAnnularWidth ) return false;
1064 if( m_ViasMinSize != aOther.m_ViasMinSize ) return false;
1065 if( m_MinThroughDrill != aOther.m_MinThroughDrill ) return false;
1066 if( m_MicroViasMinSize != aOther.m_MicroViasMinSize ) return false;
1067 if( m_MicroViasMinDrill != aOther.m_MicroViasMinDrill ) return false;
1068 if( m_CopperEdgeClearance != aOther.m_CopperEdgeClearance ) return false;
1069 if( m_HoleClearance != aOther.m_HoleClearance ) return false;
1070 if( m_HoleToHoleMin != aOther.m_HoleToHoleMin ) return false;
1071 if( m_SilkClearance != aOther.m_SilkClearance ) return false;
1072 if( m_MinResolvedSpokes != aOther.m_MinResolvedSpokes ) return false;
1073 if( m_MinSilkTextHeight != aOther.m_MinSilkTextHeight ) return false;
1074 if( m_MinSilkTextThickness != aOther.m_MinSilkTextThickness ) return false;
1075 if( m_DRCSeverities != aOther.m_DRCSeverities ) return false;
1076 if( m_DrcExclusions != aOther.m_DrcExclusions ) return false;
1077 if( m_DrcExclusionComments != aOther.m_DrcExclusionComments ) return false;
1078 if( m_ZoneKeepExternalFillets != aOther.m_ZoneKeepExternalFillets ) return false;
1079 if( m_MaxError != aOther.m_MaxError ) return false;
1080 if( m_SolderMaskExpansion != aOther.m_SolderMaskExpansion ) return false;
1081 if( m_SolderMaskMinWidth != aOther.m_SolderMaskMinWidth ) return false;
1083 if( m_SolderPasteMargin != aOther.m_SolderPasteMargin ) return false;
1084 if( m_SolderPasteMarginRatio != aOther.m_SolderPasteMarginRatio ) return false;
1086 if( m_TentViasFront != aOther.m_TentViasFront ) return false;
1087 if( m_TentViasBack != aOther.m_TentViasBack ) return false;
1088 if( m_DefaultFPTextItems != aOther.m_DefaultFPTextItems ) return false;
1089 if( m_UserLayerNames != aOther.m_UserLayerNames ) return false;
1090
1091 if( !std::equal( std::begin( m_LineThickness ), std::end( m_LineThickness ),
1092 std::begin( aOther.m_LineThickness ) ) )
1093 return false;
1094
1095 if( !std::equal( std::begin( m_TextSize ), std::end( m_TextSize ),
1096 std::begin( aOther.m_TextSize ) ) )
1097 return false;
1098
1099 if( !std::equal( std::begin( m_TextThickness ), std::end( m_TextThickness ),
1100 std::begin( aOther.m_TextThickness ) ) )
1101 return false;
1102
1103 if( !std::equal( std::begin( m_TextItalic ), std::end( m_TextItalic ),
1104 std::begin( aOther.m_TextItalic ) ) )
1105 return false;
1106
1107 if( !std::equal( std::begin( m_TextUpright ), std::end( m_TextUpright ),
1108 std::begin( aOther.m_TextUpright ) ) )
1109 return false;
1110
1111 if( m_DimensionUnitsMode != aOther.m_DimensionUnitsMode ) return false;
1112 if( m_DimensionPrecision != aOther.m_DimensionPrecision ) return false;
1113 if( m_DimensionUnitsFormat != aOther.m_DimensionUnitsFormat ) return false;
1114 if( m_DimensionSuppressZeroes != aOther.m_DimensionSuppressZeroes ) return false;
1115 if( m_DimensionTextPosition != aOther.m_DimensionTextPosition ) return false;
1116 if( m_DimensionKeepTextAligned != aOther.m_DimensionKeepTextAligned ) return false;
1117 if( m_DimensionArrowLength != aOther.m_DimensionArrowLength ) return false;
1118 if( m_DimensionExtensionOffset != aOther.m_DimensionExtensionOffset ) return false;
1119 if( m_auxOrigin != aOther.m_auxOrigin ) return false;
1120 if( m_gridOrigin != aOther.m_gridOrigin ) return false;
1121 if( m_HasStackup != aOther.m_HasStackup ) return false;
1122 if( m_UseHeightForLengthCalcs != aOther.m_UseHeightForLengthCalcs ) return false;
1123 if( m_trackWidthIndex != aOther.m_trackWidthIndex ) return false;
1124 if( m_viaSizeIndex != aOther.m_viaSizeIndex ) return false;
1125 if( m_diffPairIndex != aOther.m_diffPairIndex ) return false;
1126 if( m_useCustomTrackVia != aOther.m_useCustomTrackVia ) return false;
1127 if( m_customTrackWidth != aOther.m_customTrackWidth ) return false;
1128 if( m_customViaSize != aOther.m_customViaSize ) return false;
1129 if( m_useCustomDiffPair != aOther.m_useCustomDiffPair ) return false;
1130 if( m_customDiffPair != aOther.m_customDiffPair ) return false;
1131 if( m_copperLayerCount != aOther.m_copperLayerCount ) return false;
1132 if( m_userDefinedLayerCount != aOther.m_userDefinedLayerCount ) return false;
1133 if( m_enabledLayers != aOther.m_enabledLayers ) return false;
1134 if( m_boardThickness != aOther.m_boardThickness ) return false;
1135 if( m_currentNetClassName != aOther.m_currentNetClassName ) return false;
1136 if( m_stackup != aOther.m_stackup ) return false;
1137 if( *m_NetSettings != *aOther.m_NetSettings ) return false;
1138 if( *m_Pad_Master != *aOther.m_Pad_Master ) return false;
1139 if( m_defaultZoneSettings != aOther.m_defaultZoneSettings ) return false;
1140
1141 if( m_StyleFPFields != aOther.m_StyleFPFields ) return false;
1142 if( m_StyleFPText != aOther.m_StyleFPText ) return false;
1143 if( m_StyleFPShapes != aOther.m_StyleFPShapes ) return false;
1144
1145 return true;
1146}
1147
1148
1150{
1168 std::string units_ptr( "defaults.dimension_units" );
1169 std::string precision_ptr( "defaults.dimension_precision" );
1170
1171 if( !( Contains( units_ptr )
1172 && Contains( precision_ptr )
1173 && At( units_ptr ).is_number_integer()
1174 && At( precision_ptr ).is_number_integer() ) )
1175 {
1176 // if either is missing or invalid, migration doesn't make sense
1177 return true;
1178 }
1179
1180 int units = *Get<int>( units_ptr );
1181 int precision = *Get<int>( precision_ptr );
1182
1183 // The enum maps directly to precision if the units is mils
1184 int extraDigits = 0;
1185
1186 switch( units )
1187 {
1188 case 0: extraDigits = 3; break;
1189 case 2: extraDigits = 2; break;
1190 default: break;
1191 }
1192
1193 precision += extraDigits;
1194
1195 Set( precision_ptr, precision );
1196
1197 return true;
1198}
1199
1200
1201bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
1202{
1203 bool ret = NESTED_SETTINGS::LoadFromFile( aDirectory );
1204
1205 // A number of things won't have been translated by the PROJECT_FILE migration because of
1206 // descoped objects required to decode this data. So, it will be in the legacy.pcbnew
1207 // section and needs to be pulled out here
1208
1209 PROJECT_FILE* project = dynamic_cast<PROJECT_FILE*>( GetParent() );
1210
1211 if( !project )
1212 return ret;
1213
1214 bool migrated = false;
1215
1216 auto drcName =
1217 []( int aCode ) -> std::string
1218 {
1219 std::shared_ptr<DRC_ITEM> item = DRC_ITEM::Create( aCode );
1220 wxString name = item->GetSettingsKey();
1221 return std::string( name.ToUTF8() );
1222 };
1223
1224 const std::string rs = "rule_severities.";
1225 const std::string no_courtyard_key = "legacy_no_courtyard_defined";
1226 const std::string courtyard_overlap_key = "legacy_courtyards_overlap";
1227
1228 try
1229 {
1230 nlohmann::json& severities =
1231 project->Internals()->at( "/board/design_settings/rule_severities"_json_pointer );
1232
1233 if( severities.contains( no_courtyard_key ) )
1234 {
1235 if( severities[no_courtyard_key].get<bool>() )
1236 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "error" );
1237 else
1238 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "ignore" );
1239
1240 severities.erase( no_courtyard_key );
1241 migrated = true;
1242 }
1243
1244 if( severities.contains( courtyard_overlap_key ) )
1245 {
1246 if( severities[courtyard_overlap_key].get<bool>() )
1247 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "error" );
1248 else
1249 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "ignore" );
1250
1251 severities.erase( courtyard_overlap_key );
1252 migrated = true;
1253 }
1254 }
1255 catch( ... )
1256 {
1257 }
1258
1259 if( Contains( "legacy" ) )
1260 {
1261 // This defaults to false for new boards, but version 5.1.x and prior kept the fillets
1262 // so we do the same for legacy boards.
1264
1265 project->At( "legacy" ).erase( "pcbnew" );
1266 }
1267
1268 // Now that we have everything, we need to load again
1269 if( migrated )
1270 Load();
1271
1272 return ret;
1273}
1274
1275
1277{
1278 return m_DRCSeverities[ aDRCErrorCode ];
1279}
1280
1281
1282bool BOARD_DESIGN_SETTINGS::Ignore( int aDRCErrorCode )
1283{
1284 return m_DRCSeverities[ aDRCErrorCode ] == RPT_SEVERITY_IGNORE;
1285}
1286
1287
1289{
1290 int biggest = std::max( m_MinClearance, m_HoleClearance );
1291 DRC_CONSTRAINT constraint;
1292
1293 biggest = std::max( biggest, m_HoleToHoleMin );
1294 biggest = std::max( biggest, m_CopperEdgeClearance );
1295
1296 if( m_DRCEngine )
1297 {
1298 m_DRCEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, constraint );
1299 biggest = std::max( biggest, constraint.Value().Min() );
1300
1301 m_DRCEngine->QueryWorstConstraint( PHYSICAL_CLEARANCE_CONSTRAINT, constraint );
1302 biggest = std::max( biggest, constraint.Value().Min() );
1303
1304 m_DRCEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, constraint );
1305 biggest = std::max( biggest, constraint.Value().Min() );
1306
1307 m_DRCEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, constraint );
1308 biggest = std::max( biggest, constraint.Value().Min() );
1309
1310 m_DRCEngine->QueryWorstConstraint( HOLE_TO_HOLE_CONSTRAINT, constraint );
1311 biggest = std::max( biggest, constraint.Value().Min() );
1312 }
1313
1314 // Clip to avoid integer overflows in subsequent calculations
1315 return std::min( biggest, MAXIMUM_CLEARANCE );
1316}
1317
1318
1320{
1321 int clearance = m_NetSettings->GetDefaultNetclass()->GetClearance();
1322
1323 for( const auto& [name, netclass] : m_NetSettings->GetNetclasses() )
1324 clearance = std::min( clearance, netclass->GetClearance() );
1325
1326 return clearance;
1327}
1328
1329
1331{
1332 m_viaSizeIndex = std::min( aIndex, (unsigned) m_ViasDimensionsList.size() );
1333 m_useCustomTrackVia = false;
1334}
1335
1336
1338{
1341 else if( m_viaSizeIndex == 0 )
1342 return m_NetSettings->GetDefaultNetclass()->GetViaDiameter();
1343 else
1344 return m_ViasDimensionsList[ m_viaSizeIndex ].m_Diameter;
1345}
1346
1347
1349{
1350 int drill;
1351
1353 drill = m_customViaSize.m_Drill;
1354 else if( m_viaSizeIndex == 0 )
1355 drill = m_NetSettings->GetDefaultNetclass()->GetViaDrill();
1356 else
1357 drill = m_ViasDimensionsList[ m_viaSizeIndex ].m_Drill;
1358
1359 return drill > 0 ? drill : -1;
1360}
1361
1362
1364{
1365 m_trackWidthIndex = std::min( aIndex, (unsigned) m_TrackWidthList.size() );
1366 m_useCustomTrackVia = false;
1367}
1368
1369
1371{
1373 return m_customTrackWidth;
1374 else if( m_trackWidthIndex == 0 )
1375 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1376 else
1378}
1379
1380
1382{
1383 if( !m_DiffPairDimensionsList.empty() )
1384 {
1385 m_diffPairIndex = std::min( aIndex,
1386 static_cast<unsigned>( m_DiffPairDimensionsList.size() ) - 1 );
1387 }
1388
1389 m_useCustomDiffPair = false;
1390}
1391
1392
1394{
1396 {
1398 }
1399 else if( m_diffPairIndex == 0 )
1400 {
1401 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairWidth() )
1402 return m_NetSettings->GetDefaultNetclass()->GetDiffPairWidth();
1403 else
1404 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1405 }
1406 else
1407 {
1409 }
1410}
1411
1412
1414{
1416 {
1417 return m_customDiffPair.m_Gap;
1418 }
1419 else if( m_diffPairIndex == 0 )
1420 {
1421 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairGap() )
1422 return m_NetSettings->GetDefaultNetclass()->GetDiffPairGap();
1423 else
1424 return m_NetSettings->GetDefaultNetclass()->GetClearance();
1425 }
1426 else
1427 {
1429 }
1430}
1431
1432
1434{
1436 {
1438 }
1439 else if( m_diffPairIndex == 0 )
1440 {
1441 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairViaGap() )
1442 return m_NetSettings->GetDefaultNetclass()->GetDiffPairViaGap();
1443 else
1444 return GetCurrentDiffPairGap();
1445 }
1446 else
1447 {
1449 }
1450}
1451
1452
1454{
1455 m_copperLayerCount = aNewLayerCount;
1456
1457 // Update only enabled copper layers mask
1459
1460 if( aNewLayerCount > 0 )
1461 m_enabledLayers |= LSET::AllCuMask( aNewLayerCount );
1462}
1463
1464
1466{
1467 m_userDefinedLayerCount = aNewLayerCount;
1468
1470
1471 if( aNewLayerCount > 0 )
1472 m_enabledLayers |= LSET::UserDefinedLayersMask( aNewLayerCount );
1473}
1474
1475
1477{
1478 m_enabledLayers = aMask;
1479
1480 // Ensures mandatory back and front layers are always enabled regardless of board file
1481 // configuration.
1483 .set( B_CrtYd ).set( F_CrtYd )
1484 .set( Edge_Cuts )
1485 .set( Margin );
1486
1487 // update layer counts to ensure their consistency with m_EnabledLayers
1488 LSET copperLayers = aMask;
1489 copperLayers.ClearNonCopperLayers();
1490
1491 LSET userLayers = aMask & LSET::UserDefinedLayersMask();
1492
1493 m_copperLayerCount = (int) copperLayers.count();
1494 m_userDefinedLayerCount = (int) userLayers.count();
1495}
1496
1497
1498// Return the layer class index { silk, copper, edges & courtyards, fab, others } of the
1499// given layer.
1501{
1502 if( aLayer == F_SilkS || aLayer == B_SilkS )
1503 return LAYER_CLASS_SILK;
1504 else if( IsCopperLayer( aLayer ) )
1505 return LAYER_CLASS_COPPER;
1506 else if( aLayer == Edge_Cuts )
1507 return LAYER_CLASS_EDGES;
1508 else if( aLayer == F_CrtYd || aLayer == B_CrtYd )
1509 return LAYER_CLASS_COURTYARD;
1510 else if( aLayer == F_Fab || aLayer == B_Fab )
1511 return LAYER_CLASS_FAB;
1512 else
1513 return LAYER_CLASS_OTHERS;
1514}
1515
1516
1518{
1519 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
1520}
1521
1522
1524{
1525 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
1526}
1527
1528
1530{
1531 return m_LineThickness[ GetLayerClass( aLayer ) ];
1532}
1533
1534
1536{
1537 return m_TextSize[ GetLayerClass( aLayer ) ];
1538}
1539
1540
1542{
1543 return m_TextThickness[ GetLayerClass( aLayer ) ];
1544}
1545
1546
1548{
1549 return m_TextItalic[ GetLayerClass( aLayer ) ];
1550}
1551
1552
1554{
1555 return m_TextUpright[ GetLayerClass( aLayer ) ];
1556}
1557
1559{
1562 m_Pad_Master->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
1564 m_Pad_Master->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::ROUNDRECT );
1565
1566 constexpr double RR_RADIUS = DEFAULT_PAD_HEIGTH_MM * DEFAULT_PAD_RR_RADIUS_RATIO;
1567 m_Pad_Master->SetRoundRectCornerRadius( PADSTACK::ALL_LAYERS, pcbIUScale.mmToIU( RR_RADIUS ) );
1568}
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
@ LAYER_CLASS_OTHERS
@ LAYER_CLASS_FAB
@ LAYER_CLASS_COURTYARD
@ LAYER_CLASS_SILK
@ LAYER_CLASS_COPPER
@ LAYER_CLASS_EDGES
#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 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
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)
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
wxString m_currentNetClassName
Current net class name used to display netclass info.
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
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:393
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:951
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:583
LSET & ClearNonCopperLayers()
Clear the non-copper layers in this set.
Definition: lset.cpp:942
LSET & ClearCopperLayers()
Clear the copper layers in this set.
Definition: lset.cpp:933
static LSET UserDefinedLayersMask(int aUserDefinedLayerCount=MAX_USER_DEFINED_LAYERS)
Return a mask with the requested number of user defined layers.
Definition: lset.cpp:690
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:73
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:663
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:67
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695
#define ZONE_CLEARANCE_MM
Definition: zones.h:37