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 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;
999 m_CapVias = aOther.m_CapVias;
1000 m_FillVias = aOther.m_FillVias;
1003
1004 std::copy( std::begin( aOther.m_LineThickness ), std::end( aOther.m_LineThickness ),
1005 std::begin( m_LineThickness ) );
1006
1007 std::copy( std::begin( aOther.m_TextSize ), std::end( aOther.m_TextSize ),
1008 std::begin( m_TextSize ) );
1009
1010 std::copy( std::begin( aOther.m_TextThickness ), std::end( aOther.m_TextThickness ),
1011 std::begin( m_TextThickness ) );
1012
1013 std::copy( std::begin( aOther.m_TextItalic ), std::end( aOther.m_TextItalic ),
1014 std::begin( m_TextItalic ) );
1015
1016 std::copy( std::begin( aOther.m_TextUpright ), std::end( aOther.m_TextUpright ),
1017 std::begin( m_TextUpright ) );
1018
1027
1028 m_auxOrigin = aOther.m_auxOrigin;
1029 m_gridOrigin = aOther.m_gridOrigin;
1030 m_HasStackup = aOther.m_HasStackup;
1032
1046 m_stackup = aOther.m_stackup;
1048 m_Pad_Master = std::make_unique<PAD>( *aOther.m_Pad_Master );
1050
1054}
1055
1056
1058{
1059 if( m_TrackWidthList != aOther.m_TrackWidthList ) return false;
1060 if( m_ViasDimensionsList != aOther.m_ViasDimensionsList ) return false;
1061 if( m_DiffPairDimensionsList != aOther.m_DiffPairDimensionsList ) return false;
1062 if( m_CurrentViaType != aOther.m_CurrentViaType ) return false;
1063 if( m_UseConnectedTrackWidth != aOther.m_UseConnectedTrackWidth ) return false;
1064 if( m_TempOverrideTrackWidth != aOther.m_TempOverrideTrackWidth ) return false;
1065 if( m_MinClearance != aOther.m_MinClearance ) return false;
1066 if( m_MinGrooveWidth != aOther.m_MinGrooveWidth ) return false;
1067 if( m_MinConn != aOther.m_MinConn ) return false;
1068 if( m_TrackMinWidth != aOther.m_TrackMinWidth ) return false;
1069 if( m_ViasMinAnnularWidth != aOther.m_ViasMinAnnularWidth ) return false;
1070 if( m_ViasMinSize != aOther.m_ViasMinSize ) return false;
1071 if( m_MinThroughDrill != aOther.m_MinThroughDrill ) return false;
1072 if( m_MicroViasMinSize != aOther.m_MicroViasMinSize ) return false;
1073 if( m_MicroViasMinDrill != aOther.m_MicroViasMinDrill ) return false;
1074 if( m_CopperEdgeClearance != aOther.m_CopperEdgeClearance ) return false;
1075 if( m_HoleClearance != aOther.m_HoleClearance ) return false;
1076 if( m_HoleToHoleMin != aOther.m_HoleToHoleMin ) return false;
1077 if( m_SilkClearance != aOther.m_SilkClearance ) return false;
1078 if( m_MinResolvedSpokes != aOther.m_MinResolvedSpokes ) return false;
1079 if( m_MinSilkTextHeight != aOther.m_MinSilkTextHeight ) return false;
1080 if( m_MinSilkTextThickness != aOther.m_MinSilkTextThickness ) return false;
1081 if( m_DRCSeverities != aOther.m_DRCSeverities ) return false;
1082 if( m_DrcExclusions != aOther.m_DrcExclusions ) return false;
1083 if( m_DrcExclusionComments != aOther.m_DrcExclusionComments ) return false;
1084 if( m_ZoneKeepExternalFillets != aOther.m_ZoneKeepExternalFillets ) return false;
1085 if( m_MaxError != aOther.m_MaxError ) return false;
1086 if( m_SolderMaskExpansion != aOther.m_SolderMaskExpansion ) return false;
1087 if( m_SolderMaskMinWidth != aOther.m_SolderMaskMinWidth ) return false;
1089 if( m_SolderPasteMargin != aOther.m_SolderPasteMargin ) return false;
1090 if( m_SolderPasteMarginRatio != aOther.m_SolderPasteMarginRatio ) return false;
1092 if( m_TentViasFront != aOther.m_TentViasFront ) return false;
1093 if( m_TentViasBack != aOther.m_TentViasBack ) return false;
1094 if( m_CoverViasFront != aOther.m_CoverViasFront ) return false;
1095 if( m_CoverViasBack != aOther.m_CoverViasBack ) return false;
1096 if( m_PlugViasFront != aOther.m_PlugViasFront ) return false;
1097 if( m_PlugViasBack != aOther.m_PlugViasBack ) return false;
1098 if( m_CapVias != aOther.m_CapVias ) return false;
1099 if( m_FillVias != aOther.m_FillVias ) return false;
1100 if( m_DefaultFPTextItems != aOther.m_DefaultFPTextItems ) return false;
1101 if( m_UserLayerNames != aOther.m_UserLayerNames ) return false;
1102
1103 if( !std::equal( std::begin( m_LineThickness ), std::end( m_LineThickness ),
1104 std::begin( aOther.m_LineThickness ) ) )
1105 return false;
1106
1107 if( !std::equal( std::begin( m_TextSize ), std::end( m_TextSize ),
1108 std::begin( aOther.m_TextSize ) ) )
1109 return false;
1110
1111 if( !std::equal( std::begin( m_TextThickness ), std::end( m_TextThickness ),
1112 std::begin( aOther.m_TextThickness ) ) )
1113 return false;
1114
1115 if( !std::equal( std::begin( m_TextItalic ), std::end( m_TextItalic ),
1116 std::begin( aOther.m_TextItalic ) ) )
1117 return false;
1118
1119 if( !std::equal( std::begin( m_TextUpright ), std::end( m_TextUpright ),
1120 std::begin( aOther.m_TextUpright ) ) )
1121 return false;
1122
1123 if( m_DimensionUnitsMode != aOther.m_DimensionUnitsMode ) return false;
1124 if( m_DimensionPrecision != aOther.m_DimensionPrecision ) return false;
1125 if( m_DimensionUnitsFormat != aOther.m_DimensionUnitsFormat ) return false;
1126 if( m_DimensionSuppressZeroes != aOther.m_DimensionSuppressZeroes ) return false;
1127 if( m_DimensionTextPosition != aOther.m_DimensionTextPosition ) return false;
1128 if( m_DimensionKeepTextAligned != aOther.m_DimensionKeepTextAligned ) return false;
1129 if( m_DimensionArrowLength != aOther.m_DimensionArrowLength ) return false;
1130 if( m_DimensionExtensionOffset != aOther.m_DimensionExtensionOffset ) return false;
1131 if( m_auxOrigin != aOther.m_auxOrigin ) return false;
1132 if( m_gridOrigin != aOther.m_gridOrigin ) return false;
1133 if( m_HasStackup != aOther.m_HasStackup ) return false;
1134 if( m_UseHeightForLengthCalcs != aOther.m_UseHeightForLengthCalcs ) return false;
1135 if( m_trackWidthIndex != aOther.m_trackWidthIndex ) return false;
1136 if( m_viaSizeIndex != aOther.m_viaSizeIndex ) return false;
1137 if( m_diffPairIndex != aOther.m_diffPairIndex ) return false;
1138 if( m_useCustomTrackVia != aOther.m_useCustomTrackVia ) return false;
1139 if( m_customTrackWidth != aOther.m_customTrackWidth ) return false;
1140 if( m_customViaSize != aOther.m_customViaSize ) return false;
1141 if( m_useCustomDiffPair != aOther.m_useCustomDiffPair ) return false;
1142 if( m_customDiffPair != aOther.m_customDiffPair ) return false;
1143 if( m_copperLayerCount != aOther.m_copperLayerCount ) return false;
1144 if( m_userDefinedLayerCount != aOther.m_userDefinedLayerCount ) return false;
1145 if( m_enabledLayers != aOther.m_enabledLayers ) return false;
1146 if( m_boardThickness != aOther.m_boardThickness ) return false;
1147 if( m_currentNetClassName != aOther.m_currentNetClassName ) return false;
1148 if( m_stackup != aOther.m_stackup ) return false;
1149 if( *m_NetSettings != *aOther.m_NetSettings ) return false;
1150 if( *m_Pad_Master != *aOther.m_Pad_Master ) return false;
1151 if( m_defaultZoneSettings != aOther.m_defaultZoneSettings ) return false;
1152
1153 if( m_StyleFPFields != aOther.m_StyleFPFields ) return false;
1154 if( m_StyleFPText != aOther.m_StyleFPText ) return false;
1155 if( m_StyleFPShapes != aOther.m_StyleFPShapes ) return false;
1156
1157 return true;
1158}
1159
1160
1162{
1180 std::string units_ptr( "defaults.dimension_units" );
1181 std::string precision_ptr( "defaults.dimension_precision" );
1182
1183 if( !( Contains( units_ptr )
1184 && Contains( precision_ptr )
1185 && At( units_ptr ).is_number_integer()
1186 && At( precision_ptr ).is_number_integer() ) )
1187 {
1188 // if either is missing or invalid, migration doesn't make sense
1189 return true;
1190 }
1191
1192 int units = *Get<int>( units_ptr );
1193 int precision = *Get<int>( precision_ptr );
1194
1195 // The enum maps directly to precision if the units is mils
1196 int extraDigits = 0;
1197
1198 switch( units )
1199 {
1200 case 0: extraDigits = 3; break;
1201 case 2: extraDigits = 2; break;
1202 default: break;
1203 }
1204
1205 precision += extraDigits;
1206
1207 Set( precision_ptr, precision );
1208
1209 return true;
1210}
1211
1212
1213bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
1214{
1215 bool ret = NESTED_SETTINGS::LoadFromFile( aDirectory );
1216
1217 // A number of things won't have been translated by the PROJECT_FILE migration because of
1218 // descoped objects required to decode this data. So, it will be in the legacy.pcbnew
1219 // section and needs to be pulled out here
1220
1221 PROJECT_FILE* project = dynamic_cast<PROJECT_FILE*>( GetParent() );
1222
1223 if( !project )
1224 return ret;
1225
1226 bool migrated = false;
1227
1228 auto drcName =
1229 []( int aCode ) -> std::string
1230 {
1231 std::shared_ptr<DRC_ITEM> item = DRC_ITEM::Create( aCode );
1232 wxString name = item->GetSettingsKey();
1233 return std::string( name.ToUTF8() );
1234 };
1235
1236 const std::string rs = "rule_severities.";
1237 const std::string no_courtyard_key = "legacy_no_courtyard_defined";
1238 const std::string courtyard_overlap_key = "legacy_courtyards_overlap";
1239
1240 try
1241 {
1242 nlohmann::json& severities =
1243 project->Internals()->at( "/board/design_settings/rule_severities"_json_pointer );
1244
1245 if( severities.contains( no_courtyard_key ) )
1246 {
1247 if( severities[no_courtyard_key].get<bool>() )
1248 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "error" );
1249 else
1250 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "ignore" );
1251
1252 severities.erase( no_courtyard_key );
1253 migrated = true;
1254 }
1255
1256 if( severities.contains( courtyard_overlap_key ) )
1257 {
1258 if( severities[courtyard_overlap_key].get<bool>() )
1259 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "error" );
1260 else
1261 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "ignore" );
1262
1263 severities.erase( courtyard_overlap_key );
1264 migrated = true;
1265 }
1266 }
1267 catch( ... )
1268 {
1269 }
1270
1271 if( Contains( "legacy" ) )
1272 {
1273 // This defaults to false for new boards, but version 5.1.x and prior kept the fillets
1274 // so we do the same for legacy boards.
1276
1277 project->At( "legacy" ).erase( "pcbnew" );
1278 }
1279
1280 // Now that we have everything, we need to load again
1281 if( migrated )
1282 Load();
1283
1284 return ret;
1285}
1286
1287
1289{
1290 return m_DRCSeverities[ aDRCErrorCode ];
1291}
1292
1293
1294bool BOARD_DESIGN_SETTINGS::Ignore( int aDRCErrorCode )
1295{
1296 return m_DRCSeverities[ aDRCErrorCode ] == RPT_SEVERITY_IGNORE;
1297}
1298
1299
1301{
1302 int biggest = std::max( m_MinClearance, m_HoleClearance );
1303 DRC_CONSTRAINT constraint;
1304
1305 biggest = std::max( biggest, m_HoleToHoleMin );
1306 biggest = std::max( biggest, m_CopperEdgeClearance );
1307
1308 if( m_DRCEngine )
1309 {
1310 m_DRCEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, constraint );
1311 biggest = std::max( biggest, constraint.Value().Min() );
1312
1313 m_DRCEngine->QueryWorstConstraint( PHYSICAL_CLEARANCE_CONSTRAINT, constraint );
1314 biggest = std::max( biggest, constraint.Value().Min() );
1315
1316 m_DRCEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, constraint );
1317 biggest = std::max( biggest, constraint.Value().Min() );
1318
1319 m_DRCEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, constraint );
1320 biggest = std::max( biggest, constraint.Value().Min() );
1321
1322 m_DRCEngine->QueryWorstConstraint( HOLE_TO_HOLE_CONSTRAINT, constraint );
1323 biggest = std::max( biggest, constraint.Value().Min() );
1324 }
1325
1326 // Clip to avoid integer overflows in subsequent calculations
1327 return std::min( biggest, MAXIMUM_CLEARANCE );
1328}
1329
1330
1332{
1333 int clearance = m_NetSettings->GetDefaultNetclass()->GetClearance();
1334
1335 for( const auto& [name, netclass] : m_NetSettings->GetNetclasses() )
1336 clearance = std::min( clearance, netclass->GetClearance() );
1337
1338 return clearance;
1339}
1340
1341
1343{
1344 m_viaSizeIndex = std::min( aIndex, (unsigned) m_ViasDimensionsList.size() );
1345 m_useCustomTrackVia = false;
1346}
1347
1348
1350{
1353 else if( m_viaSizeIndex == 0 )
1354 return m_NetSettings->GetDefaultNetclass()->GetViaDiameter();
1355 else
1356 return m_ViasDimensionsList[ m_viaSizeIndex ].m_Diameter;
1357}
1358
1359
1361{
1362 int drill;
1363
1365 drill = m_customViaSize.m_Drill;
1366 else if( m_viaSizeIndex == 0 )
1367 drill = m_NetSettings->GetDefaultNetclass()->GetViaDrill();
1368 else
1369 drill = m_ViasDimensionsList[ m_viaSizeIndex ].m_Drill;
1370
1371 return drill > 0 ? drill : -1;
1372}
1373
1374
1376{
1377 m_trackWidthIndex = std::min( aIndex, (unsigned) m_TrackWidthList.size() );
1378 m_useCustomTrackVia = false;
1379}
1380
1381
1383{
1385 return m_customTrackWidth;
1386 else if( m_trackWidthIndex == 0 )
1387 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1388 else
1390}
1391
1392
1394{
1395 if( !m_DiffPairDimensionsList.empty() )
1396 {
1397 m_diffPairIndex = std::min( aIndex,
1398 static_cast<unsigned>( m_DiffPairDimensionsList.size() ) - 1 );
1399 }
1400
1401 m_useCustomDiffPair = false;
1402}
1403
1404
1406{
1408 {
1410 }
1411 else if( m_diffPairIndex == 0 )
1412 {
1413 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairWidth() )
1414 return m_NetSettings->GetDefaultNetclass()->GetDiffPairWidth();
1415 else
1416 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1417 }
1418 else
1419 {
1421 }
1422}
1423
1424
1426{
1428 {
1429 return m_customDiffPair.m_Gap;
1430 }
1431 else if( m_diffPairIndex == 0 )
1432 {
1433 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairGap() )
1434 return m_NetSettings->GetDefaultNetclass()->GetDiffPairGap();
1435 else
1436 return m_NetSettings->GetDefaultNetclass()->GetClearance();
1437 }
1438 else
1439 {
1441 }
1442}
1443
1444
1446{
1448 {
1450 }
1451 else if( m_diffPairIndex == 0 )
1452 {
1453 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairViaGap() )
1454 return m_NetSettings->GetDefaultNetclass()->GetDiffPairViaGap();
1455 else
1456 return GetCurrentDiffPairGap();
1457 }
1458 else
1459 {
1461 }
1462}
1463
1464
1466{
1467 m_copperLayerCount = aNewLayerCount;
1468
1469 // Update only enabled copper layers mask
1471
1472 if( aNewLayerCount > 0 )
1473 m_enabledLayers |= LSET::AllCuMask( aNewLayerCount );
1474}
1475
1476
1478{
1479 m_userDefinedLayerCount = aNewLayerCount;
1480
1482
1483 if( aNewLayerCount > 0 )
1484 m_enabledLayers |= LSET::UserDefinedLayersMask( aNewLayerCount );
1485}
1486
1487
1489{
1490 m_enabledLayers = aMask;
1491
1492 // Ensures mandatory back and front layers are always enabled regardless of board file
1493 // configuration.
1495 .set( B_CrtYd ).set( F_CrtYd )
1496 .set( Edge_Cuts )
1497 .set( Margin );
1498
1499 // update layer counts to ensure their consistency with m_EnabledLayers
1500 LSET copperLayers = aMask;
1501 copperLayers.ClearNonCopperLayers();
1502
1503 LSET userLayers = aMask & LSET::UserDefinedLayersMask();
1504
1505 m_copperLayerCount = (int) copperLayers.count();
1506 m_userDefinedLayerCount = (int) userLayers.count();
1507}
1508
1509
1510// Return the layer class index { silk, copper, edges & courtyards, fab, others } of the
1511// given layer.
1513{
1514 if( aLayer == F_SilkS || aLayer == B_SilkS )
1515 return LAYER_CLASS_SILK;
1516 else if( IsCopperLayer( aLayer ) )
1517 return LAYER_CLASS_COPPER;
1518 else if( aLayer == Edge_Cuts )
1519 return LAYER_CLASS_EDGES;
1520 else if( aLayer == F_CrtYd || aLayer == B_CrtYd )
1521 return LAYER_CLASS_COURTYARD;
1522 else if( aLayer == F_Fab || aLayer == B_Fab )
1523 return LAYER_CLASS_FAB;
1524 else
1525 return LAYER_CLASS_OTHERS;
1526}
1527
1528
1530{
1531 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
1532}
1533
1534
1536{
1537 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
1538}
1539
1540
1542{
1543 return m_LineThickness[ GetLayerClass( aLayer ) ];
1544}
1545
1546
1548{
1549 return m_TextSize[ GetLayerClass( aLayer ) ];
1550}
1551
1552
1554{
1555 return m_TextThickness[ GetLayerClass( aLayer ) ];
1556}
1557
1558
1560{
1561 return m_TextItalic[ GetLayerClass( aLayer ) ];
1562}
1563
1564
1566{
1567 return m_TextUpright[ GetLayerClass( aLayer ) ];
1568}
1569
1571{
1574 m_Pad_Master->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
1576 m_Pad_Master->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::ROUNDRECT );
1577
1578 constexpr double RR_RADIUS = DEFAULT_PAD_HEIGTH_MM * DEFAULT_PAD_RR_RADIUS_RATIO;
1579 m_Pad_Master->SetRoundRectCornerRadius( PADSTACK::ALL_LAYERS, pcbIUScale.mmToIU( RR_RADIUS ) );
1580}
const char * name
Definition: DXF_plotter.cpp:62
constexpr int ARC_HIGH_DEF
Definition: base_units.h:127
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:110
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:158
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:93
int m_cornerRadiusPercentage
Place meanders on one side.
Definition: pns_meander.h:125
bool m_singleSided
Initial side when placing meanders at segment.
Definition: pns_meander.h:128
MEANDER_STYLE m_cornerStyle
Rounding percentage (0 - 100).
Definition: pns_meander.h:122
int m_maxAmplitude
Meandering period/spacing (see dialog picture for explanation).
Definition: pns_meander.h:96
int m_spacing
Amplitude/spacing adjustment step.
Definition: pns_meander.h:99
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:74
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_SILK_MASK_CLEARANCE
Definition: drc_item.h:96
@ 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_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:46
#define TEXT_MAX_SIZE_MM
Maximum text size in mm (~10 inches)
Definition: eda_text.h:47
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:88
const double IU_PER_MM
Definition: base_units.h:76
const double MM_PER_IU
Definition: base_units.h:80
constexpr int MilsToIU(int mils) const
Definition: base_units.h:95
constexpr int mmToIU(double mm) const
Definition: base_units.h:90
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