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 <cmath>
27#include <layer_ids.h>
28#include <lset.h>
29#include <kiface_base.h>
30#include <pad.h>
33#include <drc/drc_item.h>
34#include <drc/drc_engine.h>
36#include <settings/parameters.h>
38#include <advanced_config.h>
39
40const int bdsSchemaVersion = 2;
41
42
43BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
44 NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aParent, aPath )
45{
46 // We want to leave alone parameters that aren't found in the project JSON as they may be
47 // initialized by the board file parser before NESTED_SETTINGS::LoadFromFile is called.
49
50 // Create a default NET_SETTINGS so that things don't break horribly if there's no project
51 // loaded. This also is used during file load for legacy boards that have netclasses stored
52 // in the file. After load, this information will be moved to the project and the pointer
53 // updated.
54 m_NetSettings = std::make_shared<NET_SETTINGS>( nullptr, "" );
55
56 m_HasStackup = false; // no stackup defined by default
57
58 m_Pad_Master = std::make_unique<PAD>( nullptr );
60
61 LSET all_set = LSET().set();
62 m_enabledLayers = all_set; // All layers enabled at first.
63 // SetCopperLayerCount() will adjust this.
64
65 // Default design is a double layer board with 4 user defined layers
68
70
71 // if true, when creating a new track starting on an existing track, use this track width
74
75 // First is always the reference designator
76 m_DefaultFPTextItems.emplace_back( wxT( "REF**" ), true, F_SilkS );
77 // Second is always the value
78 m_DefaultFPTextItems.emplace_back( wxT( "" ), true, F_Fab );
79 // Any following ones are freebies
80 m_DefaultFPTextItems.emplace_back( wxT( "${REFERENCE}" ), true, F_Fab );
81
88
95
96 // Edges & Courtyards; text properties aren't used but better to have them holding
97 // reasonable values than not.
100 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
104
107 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
111
114 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
116 m_TextItalic[ LAYER_CLASS_FAB ] = false;
118
121 pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
125
126 m_StyleFPFields = false;
127 m_StyleFPText = false;
128 m_StyleFPShapes = false;
129 m_StyleFPDimensions = false;
130 m_StyleFPBarcodes = false;
131
140
141 m_useCustomTrackVia = false;
143 m_customViaSize.m_Diameter = pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE );
145
146 m_useCustomDiffPair = false;
150
167
168 for( int errorCode = DRCE_FIRST; errorCode <= DRCE_LAST; ++errorCode )
169 m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
170
173
177
180
183
185
193
199
201
204
206
209
212
214
218
219 // Global mask margins:
223
224 // Solder paste margin absolute value
226 // Solder paste margin as a ratio of pad size
227 // The final margin is the sum of these 2 values
228 // Usually < 0 because the mask is smaller than pad
230
232 m_TentViasFront = true;
233 m_TentViasBack = true;
234
235 m_CoverViasFront = false;
236 m_CoverViasBack = false;
237
238 m_PlugViasFront = false;
239 m_PlugViasBack = false;
240
241 m_CapVias = false;
242
243 m_FillVias = false;
244
245 // Layer thickness for 3D viewer
247
248 // Default spacing for meanders
252
253 m_viaSizeIndex = 0;
255 m_diffPairIndex = 0;
256
257 // Parameters stored in JSON in the project file
258
259 // NOTE: Previously, BOARD_DESIGN_SETTINGS stored the basic board layer information (layer
260 // names and enable/disable state) in the project file even though this information is also
261 // stored in the board file. This was implemented for importing these settings from another
262 // project. Going forward, the import feature will just import from other board files (since
263 // we could have multi-board projects in the future anyway) so this functionality is dropped.
264
265
266 m_params.emplace_back( new PARAM<bool>( "rules.use_height_for_length_calcs",
267 &m_UseHeightForLengthCalcs, true ) );
268
269 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_clearance",
271 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
272
273 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_connection",
275 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
276
277 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_track_width",
279 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
280
281 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_annular_width",
283 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
284
285 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_diameter",
287 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
288
289 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_through_hole_diameter",
291 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
292
293 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_diameter",
295 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), pcbIUScale.MM_PER_IU ) );
296
297 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_drill",
299 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), pcbIUScale.MM_PER_IU ) );
300
301 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_to_hole",
303 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), pcbIUScale.MM_PER_IU ) );
304
305 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_clearance",
307 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
308
309 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_silk_clearance",
311 pcbIUScale.mmToIU( -10.0 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
312
313 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_groove_width",
315 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
316
317 // While the maximum *effective* value is 4, we've had users interpret this as the count on
318 // all layers, and enter something like 10. They'll figure it out soon enough *unless* we
319 // enforce a max of 4 (and therefore reset it back to the default of 2), at which point it
320 // just looks buggy.
321 m_params.emplace_back( new PARAM<int>( "rules.min_resolved_spokes",
323
324 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_height",
326 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
327
328 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_thickness",
330 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
331
332 // Note: a clearance of -0.01 is a flag indicating we should use the legacy (pre-6.0) method
333 // based on the edge cut thicknesses.
334 m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_copper_edge_clearance",
336 pcbIUScale.mmToIU( -0.01 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
337
338 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
339 [&]() -> nlohmann::json
340 {
341 nlohmann::json ret = {};
342
343 for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
344 {
345 wxString name = item.GetSettingsKey();
346 int code = item.GetErrorCode();
347
348 if( name.IsEmpty() || m_DRCSeverities.count( code ) == 0 )
349 continue;
350
351 ret[std::string( name.ToUTF8() )] = SeverityToString( m_DRCSeverities[code] );
352 }
353
354 return ret;
355 },
356 [&]( const nlohmann::json& aJson )
357 {
358 if( !aJson.is_object() )
359 return;
360
361 // Load V8 'hole_near_hole' token first (if present). Any current 'hole_to_hole' token
362 // found will then overwrite it.
363 // We can't use the migration architecture because we forgot to bump the version number
364 // when the change was made. But this is a one-off as any future deprecations should
365 // bump the version number and use registerMigration().
366 if( aJson.contains( "hole_near_hole" ) )
368
369 for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
370 {
371 wxString name = item.GetSettingsKey();
372 std::string key( name.ToUTF8() );
373
374 if( aJson.contains( key ) )
375 m_DRCSeverities[item.GetErrorCode()] = SeverityFromString( aJson[key] );
376 }
377 }, {} ) );
378
379 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "drc_exclusions",
380 [&]() -> nlohmann::json
381 {
382 nlohmann::json js = nlohmann::json::array();
383
384 for( const wxString& entry : m_DrcExclusions )
385 js.push_back( { entry, m_DrcExclusionComments[ entry ] } );
386
387 return js;
388 },
389 [&]( const nlohmann::json& aObj )
390 {
391 m_DrcExclusions.clear();
392
393 if( !aObj.is_array() )
394 return;
395
396 for( const nlohmann::json& entry : aObj )
397 {
398 if( entry.is_array() )
399 {
400 wxString serialized = entry[0].get<wxString>();
401 m_DrcExclusions.insert( serialized );
402 m_DrcExclusionComments[ serialized ] = entry[1].get<wxString>();
403 }
404 else if( entry.is_string() )
405 {
406 m_DrcExclusions.insert( entry.get<wxString>() );
407 }
408 }
409 },
410 {} ) );
411
412 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "track_widths",
413 [&]() -> nlohmann::json
414 {
415 nlohmann::json js = nlohmann::json::array();
416
417 for( const int& width : m_TrackWidthList )
418 js.push_back( pcbIUScale.IUTomm( width ) );
419
420 return js;
421 },
422 [&]( const nlohmann::json& aJson )
423 {
424 if( !aJson.is_array() )
425 return;
426
427 m_TrackWidthList.clear();
428
429 for( const nlohmann::json& entry : aJson )
430 {
431 if( entry.empty() )
432 continue;
433
434 m_TrackWidthList.emplace_back( pcbIUScale.mmToIU( entry.get<double>() ) );
435 }
436 },
437 {} ) );
438
439 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "via_dimensions",
440 [&]() -> nlohmann::json
441 {
442 nlohmann::json js = nlohmann::json::array();
443
444 for( const auto& via : m_ViasDimensionsList )
445 {
446 nlohmann::json entry = {};
447
448 entry["diameter"] = pcbIUScale.IUTomm( via.m_Diameter );
449 entry["drill"] = pcbIUScale.IUTomm( via.m_Drill );
450
451 js.push_back( entry );
452 }
453
454 return js;
455 },
456 [&]( const nlohmann::json& aObj )
457 {
458 if( !aObj.is_array() )
459 return;
460
461 m_ViasDimensionsList.clear();
462
463 for( const nlohmann::json& entry : aObj )
464 {
465 if( entry.empty() || !entry.is_object() )
466 continue;
467
468 if( !entry.contains( "diameter" ) || !entry.contains( "drill" ) )
469 continue;
470
471 int diameter = pcbIUScale.mmToIU( entry["diameter"].get<double>() );
472 int drill = pcbIUScale.mmToIU( entry["drill"].get<double>() );
473
474 m_ViasDimensionsList.emplace_back( VIA_DIMENSION( diameter, drill ) );
475 }
476 },
477 {} ) );
478
479 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "diff_pair_dimensions",
480 [&]() -> nlohmann::json
481 {
482 nlohmann::json js = nlohmann::json::array();
483
484 for( const auto& pair : m_DiffPairDimensionsList )
485 {
486 nlohmann::json entry = {};
487
488 entry["width"] = pcbIUScale.IUTomm( pair.m_Width );
489 entry["gap"] = pcbIUScale.IUTomm( pair.m_Gap );
490 entry["via_gap"] = pcbIUScale.IUTomm( pair.m_ViaGap );
491
492 js.push_back( entry );
493 }
494
495 return js;
496 },
497 [&]( const nlohmann::json& aObj )
498 {
499 if( !aObj.is_array() )
500 return;
501
503
504 for( const nlohmann::json& entry : aObj )
505 {
506 if( entry.empty() || !entry.is_object() )
507 continue;
508
509 if( !entry.contains( "width" )
510 || !entry.contains( "gap" )
511 || !entry.contains( "via_gap" ) )
512 {
513 continue;
514 }
515
516 int width = pcbIUScale.mmToIU( entry["width"].get<double>() );
517 int gap = pcbIUScale.mmToIU( entry["gap"].get<double>() );
518 int via_gap = pcbIUScale.mmToIU( entry["via_gap"].get<double>() );
519
520 m_DiffPairDimensionsList.emplace_back( DIFF_PAIR_DIMENSION( width, gap, via_gap ) );
521 }
522 },
523 {} ) );
524
525 // Handle options for teardrops (targets and some others):
526 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_options",
527 [&]() -> nlohmann::json
528 {
529 nlohmann::json js = nlohmann::json::array();
530 nlohmann::json entry = {};
531
532 entry["td_onvia"] = m_TeardropParamsList.m_TargetVias;
533 entry["td_onpthpad"] = m_TeardropParamsList.m_TargetPTHPads;
534 entry["td_onsmdpad"] = m_TeardropParamsList.m_TargetSMDPads;
535 entry["td_ontrackend"] = m_TeardropParamsList.m_TargetTrack2Track;
536 entry["td_onroundshapesonly"] = m_TeardropParamsList.m_UseRoundShapesOnly;
537
538 js.push_back( entry );
539
540 return js;
541 },
542 [&]( const nlohmann::json& aObj )
543 {
544 if( !aObj.is_array() )
545 return;
546
547 for( const nlohmann::json& entry : aObj )
548 {
549 if( entry.empty() || !entry.is_object() )
550 continue;
551
552 if( entry.contains( "td_onvia" ) )
553 m_TeardropParamsList.m_TargetVias = entry["td_onvia"].get<bool>();
554
555 if( entry.contains( "td_onpthpad" ) )
556 m_TeardropParamsList.m_TargetPTHPads = entry["td_onpthpad"].get<bool>();
557
558 if( entry.contains( "td_onsmdpad" ) )
559 m_TeardropParamsList.m_TargetSMDPads = entry["td_onsmdpad"].get<bool>();
560
561 if( entry.contains( "td_ontrackend" ) )
562 m_TeardropParamsList.m_TargetTrack2Track = entry["td_ontrackend"].get<bool>();
563
564 if( entry.contains( "td_onroundshapesonly" ) )
565 m_TeardropParamsList.m_UseRoundShapesOnly = entry["td_onroundshapesonly"].get<bool>();
566
567 // Legacy settings
568 for( int ii = 0; ii < 3; ++ii )
569 {
570 TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)ii );
571
572 if( entry.contains( "td_allow_use_two_tracks" ) )
573 td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
574
575 if( entry.contains( "td_curve_segcount" ) )
576 {
577 if( entry["td_curve_segcount"].get<int>() > 0 )
578 td_prm->m_CurvedEdges = true;
579 }
580
581 if( entry.contains( "td_on_pad_in_zone" ) )
582 td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
583 }
584 }
585 },
586 {} ) );
587
588 // Handle parameters (sizes, shape) for each type of teardrop:
589 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_parameters",
590 [&]() -> nlohmann::json
591 {
592 nlohmann::json js = nlohmann::json::array();
593
594 for( size_t ii = 0; ii < m_TeardropParamsList.GetParametersCount(); ii++ )
595 {
596 nlohmann::json entry = {};
597 TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)ii );
598
599 entry["td_target_name"] = GetTeardropTargetCanonicalName( (TARGET_TD)ii );
600 entry["td_maxlen"] = pcbIUScale.IUTomm( td_prm->m_TdMaxLen );
601 entry["td_maxheight"] = pcbIUScale.IUTomm( td_prm->m_TdMaxWidth );
602 entry["td_length_ratio"] = td_prm->m_BestLengthRatio;
603 entry["td_height_ratio"] = td_prm->m_BestWidthRatio;
604 entry["td_curve_segcount"] = td_prm->m_CurvedEdges ? 1 : 0;
605 entry["td_width_to_size_filter_ratio"] = td_prm->m_WidthtoSizeFilterRatio;
606 entry["td_allow_use_two_tracks"] = td_prm->m_AllowUseTwoTracks;
607 entry["td_on_pad_in_zone"] = td_prm->m_TdOnPadsInZones;
608
609 js.push_back( entry );
610 }
611
612 return js;
613 },
614 [&]( const nlohmann::json& aObj )
615 {
616 if( !aObj.is_array() )
617 return;
618
619 for( const nlohmann::json& entry : aObj )
620 {
621 if( entry.empty() || !entry.is_object() )
622 continue;
623
624 if( !entry.contains( "td_target_name" ) )
625 continue;
626
627 int idx = GetTeardropTargetTypeFromCanonicalName( entry["td_target_name"].get<std::string>() );
628
629 if( idx >= 0 && idx < 3 )
630 {
631 TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)idx );
632
633 if( entry.contains( "td_maxlen" ) )
634 td_prm->m_TdMaxLen = pcbIUScale.mmToIU( entry["td_maxlen"].get<double>() );
635
636 if( entry.contains( "td_maxheight" ) )
637 td_prm->m_TdMaxWidth = pcbIUScale.mmToIU( entry["td_maxheight"].get<double>() );
638
639 if( entry.contains( "td_length_ratio" ) )
640 td_prm->m_BestLengthRatio = entry["td_length_ratio"].get<double>();
641
642 if( entry.contains( "td_height_ratio" ) )
643 td_prm->m_BestWidthRatio = entry["td_height_ratio"].get<double>();
644
645 if( entry.contains( "td_curve_segcount" ) )
646 {
647 if( entry["td_curve_segcount"].get<int>() > 0 )
648 td_prm->m_CurvedEdges = true;
649 }
650
651 if( entry.contains( "td_width_to_size_filter_ratio" ) )
652 td_prm->m_WidthtoSizeFilterRatio = entry["td_width_to_size_filter_ratio"].get<double>();
653
654 if( entry.contains( "td_allow_use_two_tracks" ) )
655 td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
656
657 if( entry.contains( "td_on_pad_in_zone" ) )
658 td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
659 }
660 }
661 },
662 {} ) );
663
664 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "tuning_pattern_settings",
665 [&]() -> nlohmann::json
666 {
667 nlohmann::json js = {};
668
669 auto make_settings =
670 []( const PNS::MEANDER_SETTINGS& aSettings )
671 {
672 nlohmann::json entry = {};
673
674 entry["min_amplitude"] = pcbIUScale.IUTomm( aSettings.m_minAmplitude );
675 entry["max_amplitude"] = pcbIUScale.IUTomm( aSettings.m_maxAmplitude );
676 entry["spacing"] = pcbIUScale.IUTomm( aSettings.m_spacing );
677 entry["corner_style"] = aSettings.m_cornerStyle == PNS::MEANDER_STYLE_CHAMFER ? 0 : 1;
678 entry["corner_radius_percentage"] = aSettings.m_cornerRadiusPercentage;
679 entry["single_sided"] = aSettings.m_singleSided;
680
681 return entry;
682 };
683
684 js["single_track_defaults"] = make_settings( m_SingleTrackMeanderSettings );
685 js["diff_pair_defaults"] = make_settings( m_DiffPairMeanderSettings );
686 js["diff_pair_skew_defaults"] = make_settings( m_SkewMeanderSettings );
687
688 return js;
689 },
690 [&]( const nlohmann::json& aObj )
691 {
692 auto read_settings =
693 []( const nlohmann::json& entry ) -> PNS::MEANDER_SETTINGS
694 {
695 PNS::MEANDER_SETTINGS settings;
696
697 if( entry.contains( "min_amplitude" ) )
698 settings.m_minAmplitude = pcbIUScale.mmToIU( entry["min_amplitude"].get<double>() );
699
700 if( entry.contains( "max_amplitude" ) )
701 settings.m_maxAmplitude = pcbIUScale.mmToIU( entry["max_amplitude"].get<double>() );
702
703 if( entry.contains( "spacing" ) )
704 settings.m_spacing = pcbIUScale.mmToIU( entry["spacing"].get<double>() );
705
706 if( entry.contains( "corner_style" ) )
707 {
708 settings.m_cornerStyle = entry["corner_style"] == 0 ? PNS::MEANDER_STYLE_CHAMFER
710 }
711
712 if( entry.contains( "corner_radius_percentage" ) )
713 settings.m_cornerRadiusPercentage = entry["corner_radius_percentage"].get<int>();
714
715 if( entry.contains( "single_sided" ) )
716 settings.m_singleSided = entry["single_sided"].get<bool>();
717
718 return settings;
719 };
720
721 if( aObj.contains( "single_track_defaults" ) )
722 m_SingleTrackMeanderSettings = read_settings( aObj["single_track_defaults"] );
723
724 if( aObj.contains( "diff_pair_defaults" ) )
725 m_DiffPairMeanderSettings = read_settings( aObj["diff_pair_defaults"] );
726
727 if( aObj.contains( "diff_pair_skew_defaults" ) )
728 m_SkewMeanderSettings = read_settings( aObj["diff_pair_skew_defaults"] );
729 },
730 {} ) );
731
732 int minTextSize = pcbIUScale.mmToIU( TEXT_MIN_SIZE_MM );
733 int maxTextSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
734 int minStroke = 1;
735 int maxStroke = pcbIUScale.mmToIU( 100 );
736
737 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_line_width",
739 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
740
741 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_v",
743 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
744
745 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_h",
747 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
748
749 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_thickness",
751 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
752
753 m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_italic",
754 &m_TextItalic[LAYER_CLASS_SILK], false ) );
755
756 m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_upright",
757 &m_TextUpright[ LAYER_CLASS_SILK ], true ) );
758
759 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_line_width",
761 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
762
763 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_v",
765 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
766
767 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_h",
769 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
770
771 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_thickness",
773 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
774
775 m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_italic",
776 &m_TextItalic[LAYER_CLASS_COPPER], false ) );
777
778 m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_upright",
780
781 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.board_outline_line_width",
783 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
784
785 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.courtyard_line_width",
787 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
788
789 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_line_width",
791 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
792
793 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_v",
795 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
796
797 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_h",
799 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
800
801 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_thickness",
803 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
804
805 m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_italic",
806 &m_TextItalic[LAYER_CLASS_FAB], false ) );
807
808 m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_upright",
809 &m_TextUpright[LAYER_CLASS_FAB], true ) );
810
811 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_line_width",
813 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
814
815 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_v",
817 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
818
819 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_h",
821 minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
822
823 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_thickness",
825 minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
826
827 m_params.emplace_back( new PARAM<bool>( "defaults.other_text_italic",
828 &m_TextItalic[LAYER_CLASS_OTHERS], false ) );
829
830 m_params.emplace_back( new PARAM<bool>( "defaults.other_text_upright",
832
833 m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_MODE>( "defaults.dimension_units",
836
837 m_params.emplace_back( new PARAM_ENUM<DIM_PRECISION>( "defaults.dimension_precision",
839
840 m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_FORMAT>( "defaults.dimensions.units_format",
843
844 m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.suppress_zeroes",
845 &m_DimensionSuppressZeroes, true ) );
846
847 // NOTE: excluding DIM_TEXT_POSITION::MANUAL from the valid range here
848 m_params.emplace_back( new PARAM_ENUM<DIM_TEXT_POSITION>( "defaults.dimensions.text_position",
851
852 m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.keep_text_aligned",
854
855 m_params.emplace_back( new PARAM<int>( "defaults.dimensions.arrow_length",
858
859 m_params.emplace_back( new PARAM<int>( "defaults.dimensions.extension_offset",
862
863 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_fields",
864 &m_StyleFPFields, false ) );
865 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_text",
866 &m_StyleFPText, false ) );
867 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_shapes",
868 &m_StyleFPShapes, false ) );
869 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_dimensions",
870 &m_StyleFPDimensions, false ) );
871 m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_barcodes",
872 &m_StyleFPBarcodes, false ) );
873
874 m_params.emplace_back( new PARAM_SCALED<int>( "defaults.zones.min_clearance",
875 &m_defaultZoneSettings.m_ZoneClearance, pcbIUScale.mmToIU( ZONE_CLEARANCE_MM ),
876 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
877
878 m_params.emplace_back( new PARAM_SCALED<int>(
879 "defaults.zones.min_thickness", &m_defaultZoneSettings.m_ZoneMinThickness,
881 pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
882
883 m_params.emplace_back( new PARAM_ENUM<ZONE_FILL_MODE>( "defaults.zones.fill_mode",
887
888 m_params.emplace_back(
889 new PARAM_SCALED<int>( "defaults.zones.hatch_thickness", &m_defaultZoneSettings.m_HatchThickness,
890 std::max( pcbIUScale.mmToIU( ZONE_THICKNESS_MM ) * 4, pcbIUScale.mmToIU( 1.0 ) ),
891 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
892
893 m_params.emplace_back(
894 new PARAM_SCALED<int>( "defaults.zones.hatch_gap", &m_defaultZoneSettings.m_HatchGap,
895 std::max( pcbIUScale.mmToIU( ZONE_THICKNESS_MM ) * 6, pcbIUScale.mmToIU( 1.5 ) ),
896 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
897
898 m_params.emplace_back( new PARAM_LAMBDA<double>(
899 "defaults.zones.hatch_orientation",
900 [&]() -> double
901 {
902 return m_defaultZoneSettings.m_HatchOrientation.AsDegrees();
903 },
904 [&]( double aVal )
905 {
906 m_defaultZoneSettings.m_HatchOrientation = EDA_ANGLE( aVal, DEGREES_T );
907 },
908 0.0 ) );
909
910 m_params.emplace_back( new PARAM<int>( "defaults.zones.hatch_smoothing_level",
911 &m_defaultZoneSettings.m_HatchSmoothingLevel, 0, 0, 2 ) );
912
913 m_params.emplace_back( new PARAM<double>( "defaults.zones.hatch_smoothing_value",
914 &m_defaultZoneSettings.m_HatchSmoothingValue, 0.1, 0.0, 1.0 ) );
915
917 "defaults.zones.border_display_style", &m_defaultZoneSettings.m_ZoneBorderDisplayStyle,
920
921 m_params.emplace_back( new PARAM_SCALED<int>(
922 "defaults.zones.border_hatch_pitch", &m_defaultZoneSettings.m_BorderHatchPitch,
924 pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MAXDIST_MM ), pcbIUScale.MM_PER_IU ) );
925
926 m_params.emplace_back(
927 new PARAM_SCALED<long>( "defaults.zones.thermal_relief_gap", &m_defaultZoneSettings.m_ThermalReliefGap,
928 pcbIUScale.mmToIU( ZONE_THERMAL_RELIEF_GAP_MM ), pcbIUScale.mmToIU( 0.0 ),
929 pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
930
931 m_params.emplace_back( new PARAM_SCALED<long>(
932 "defaults.zones.thermal_relief_spoke_width", &m_defaultZoneSettings.m_ThermalReliefSpokeWidth,
934 pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
935
936 m_params.emplace_back( new PARAM_LAMBDA<int>(
937 "defaults.zones.pad_connection",
938 [&]() -> int
939 {
940 return static_cast<int>( m_defaultZoneSettings.GetPadConnection() );
941 },
942 [&]( int aVal )
943 {
944 m_defaultZoneSettings.SetPadConnection( static_cast<ZONE_CONNECTION>( aVal ) );
945 },
946 static_cast<int>( ZONE_CONNECTION::THERMAL ) ) );
947
948 m_params.emplace_back( new PARAM_LAMBDA<int>(
949 "defaults.zones.corner_smoothing",
950 [&]() -> int
951 {
952 return m_defaultZoneSettings.GetCornerSmoothingType();
953 },
954 [&]( int aVal )
955 {
956 m_defaultZoneSettings.SetCornerSmoothingType( aVal );
957 },
959
960 m_params.emplace_back( new PARAM_LAMBDA<double>(
961 "defaults.zones.corner_radius",
962 [&]() -> double
963 {
964 return pcbIUScale.IUTomm( m_defaultZoneSettings.GetCornerRadius() );
965 },
966 [&]( double aVal )
967 {
968 m_defaultZoneSettings.SetCornerRadius( pcbIUScale.mmToIU( aVal ) );
969 },
970 0.0 ) );
971
972 m_params.emplace_back( new PARAM_LAMBDA<int>(
973 "defaults.zones.remove_islands",
974 [&]() -> int
975 {
976 return static_cast<int>( m_defaultZoneSettings.GetIslandRemovalMode() );
977 },
978 [&]( int aVal )
979 {
980 m_defaultZoneSettings.SetIslandRemovalMode( static_cast<ISLAND_REMOVAL_MODE>( aVal ) );
981 },
982 static_cast<int>( ISLAND_REMOVAL_MODE::ALWAYS ) ) );
983
984 m_params.emplace_back( new PARAM_LAMBDA<double>(
985 "defaults.zones.min_island_area",
986 [&]() -> double
987 {
988 const double iuPerMm2 = pcbIUScale.IU_PER_MM * pcbIUScale.IU_PER_MM;
989 return static_cast<double>( m_defaultZoneSettings.GetMinIslandArea() ) / iuPerMm2;
990 },
991 [&]( double aVal )
992 {
993 const double iuPerMm2 = pcbIUScale.IU_PER_MM * pcbIUScale.IU_PER_MM;
994 m_defaultZoneSettings.SetMinIslandArea( static_cast<long long int>( aVal * iuPerMm2 ) );
995 },
996 10.0 ) );
997
998 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "defaults.pads",
999 [&]() -> nlohmann::json
1000 {
1001 nlohmann::json ret =
1002 {
1003 { "width", pcbIUScale.IUTomm( m_Pad_Master->GetSize( PADSTACK::ALL_LAYERS ).x ) },
1004 { "height", pcbIUScale.IUTomm( m_Pad_Master->GetSize( PADSTACK::ALL_LAYERS ).y ) },
1005 { "drill", pcbIUScale.IUTomm( m_Pad_Master->GetDrillSize().x ) }
1006 };
1007
1008 return ret;
1009 },
1010 [&]( const nlohmann::json& aJson )
1011 {
1012 if( aJson.contains( "width" ) && aJson.contains( "height" )
1013 && aJson.contains( "drill" ) )
1014 {
1015 VECTOR2I sz;
1016 sz.x = pcbIUScale.mmToIU( aJson["width"].get<double>() );
1017 sz.y = pcbIUScale.mmToIU( aJson["height"].get<double>() );
1018
1019 m_Pad_Master->SetSize( PADSTACK::ALL_LAYERS, sz );
1020
1021 int drill = pcbIUScale.mmToIU( aJson["drill"].get<double>() );
1022
1023 m_Pad_Master->SetDrillSize( VECTOR2I( drill, drill ) );
1024 }
1025 }, {} ) );
1026
1027 m_params.emplace_back( new PARAM_SCALED<int>( "rules.max_error",
1029 pcbIUScale.mmToIU( 0.0001 ), pcbIUScale.mmToIU( 1.0 ), pcbIUScale.MM_PER_IU ) );
1030
1031 m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_mask_to_copper_clearance",
1033 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
1034
1035 m_params.emplace_back( new PARAM<bool>( "zones_allow_external_fillets",
1036 &m_ZoneKeepExternalFillets, false ) );
1037
1039
1040 registerMigration( 1, 2,
1041 [&]() -> bool
1042 {
1043 // Schema 1 to 2: move mask and paste margin settings back to board.
1044 // The parameters are removed, so we just have to manually load them here and
1045 // they will get saved with the board
1046 if( std::optional<double> optval = Get<double>( "rules.solder_mask_clearance" ) )
1047 m_SolderMaskExpansion = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
1048
1049 if( std::optional<double> optval = Get<double>( "rules.solder_mask_min_width" ) )
1050 m_SolderMaskMinWidth = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
1051
1052 if( std::optional<double> optval = Get<double>( "rules.solder_paste_clearance" ) )
1053 m_SolderPasteMargin = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
1054
1055 if( std::optional<double> optval = Get<double>( "rules.solder_paste_margin_ratio" ) )
1056 m_SolderPasteMarginRatio = *optval;
1057
1058 try
1059 {
1060 At( "rules" ).erase( "solder_mask_clearance" );
1061 At( "rules" ).erase( "solder_mask_min_width" );
1062 At( "rules" ).erase( "solder_paste_clearance" );
1063 At( "rules" ).erase( "solder_paste_margin_ratio" );
1064 }
1065 catch( ... )
1066 {}
1067
1068 return true;
1069 } );
1070}
1071
1072
1074{
1075 if( m_parent )
1076 {
1077 m_parent->ReleaseNestedSettings( this );
1078 m_parent = nullptr;
1079 }
1080}
1081
1082
1084 NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aOther.m_parent,
1085 aOther.m_path ),
1086 m_Pad_Master( nullptr )
1087{
1088 initFromOther( aOther );
1089}
1090
1091
1093{
1094 initFromOther( aOther );
1095 return *this;
1096}
1097
1098
1100{
1101 // Copy of NESTED_SETTINGS around is not allowed, so let's just update the params.
1110 m_MinConn = aOther.m_MinConn;
1128 m_MaxError = aOther.m_MaxError;
1141 m_CapVias = aOther.m_CapVias;
1142 m_FillVias = aOther.m_FillVias;
1145
1146 std::copy( std::begin( aOther.m_LineThickness ), std::end( aOther.m_LineThickness ),
1147 std::begin( m_LineThickness ) );
1148
1149 std::copy( std::begin( aOther.m_TextSize ), std::end( aOther.m_TextSize ),
1150 std::begin( m_TextSize ) );
1151
1152 std::copy( std::begin( aOther.m_TextThickness ), std::end( aOther.m_TextThickness ),
1153 std::begin( m_TextThickness ) );
1154
1155 std::copy( std::begin( aOther.m_TextItalic ), std::end( aOther.m_TextItalic ),
1156 std::begin( m_TextItalic ) );
1157
1158 std::copy( std::begin( aOther.m_TextUpright ), std::end( aOther.m_TextUpright ),
1159 std::begin( m_TextUpright ) );
1160
1169
1170 m_auxOrigin = aOther.m_auxOrigin;
1171 m_gridOrigin = aOther.m_gridOrigin;
1172 m_HasStackup = aOther.m_HasStackup;
1174
1188 m_stackup = aOther.m_stackup;
1190 m_Pad_Master = std::make_unique<PAD>( *aOther.m_Pad_Master );
1192
1198}
1199
1200
1202{
1203 if( m_TrackWidthList != aOther.m_TrackWidthList ) return false;
1204 if( m_ViasDimensionsList != aOther.m_ViasDimensionsList ) return false;
1205 if( m_DiffPairDimensionsList != aOther.m_DiffPairDimensionsList ) return false;
1206 if( m_CurrentViaType != aOther.m_CurrentViaType ) return false;
1207 if( m_UseConnectedTrackWidth != aOther.m_UseConnectedTrackWidth ) return false;
1208 if( m_TempOverrideTrackWidth != aOther.m_TempOverrideTrackWidth ) return false;
1209 if( m_MinClearance != aOther.m_MinClearance ) return false;
1210 if( m_MinGrooveWidth != aOther.m_MinGrooveWidth ) return false;
1211 if( m_MinConn != aOther.m_MinConn ) return false;
1212 if( m_TrackMinWidth != aOther.m_TrackMinWidth ) return false;
1213 if( m_ViasMinAnnularWidth != aOther.m_ViasMinAnnularWidth ) return false;
1214 if( m_ViasMinSize != aOther.m_ViasMinSize ) return false;
1215 if( m_MinThroughDrill != aOther.m_MinThroughDrill ) return false;
1216 if( m_MicroViasMinSize != aOther.m_MicroViasMinSize ) return false;
1217 if( m_MicroViasMinDrill != aOther.m_MicroViasMinDrill ) return false;
1218 if( m_CopperEdgeClearance != aOther.m_CopperEdgeClearance ) return false;
1219 if( m_HoleClearance != aOther.m_HoleClearance ) return false;
1220 if( m_HoleToHoleMin != aOther.m_HoleToHoleMin ) return false;
1221 if( m_SilkClearance != aOther.m_SilkClearance ) return false;
1222 if( m_MinResolvedSpokes != aOther.m_MinResolvedSpokes ) return false;
1223 if( m_MinSilkTextHeight != aOther.m_MinSilkTextHeight ) return false;
1224 if( m_MinSilkTextThickness != aOther.m_MinSilkTextThickness ) return false;
1225 if( m_DRCSeverities != aOther.m_DRCSeverities ) return false;
1226 if( m_DrcExclusions != aOther.m_DrcExclusions ) return false;
1227 if( m_DrcExclusionComments != aOther.m_DrcExclusionComments ) return false;
1228 if( m_ZoneKeepExternalFillets != aOther.m_ZoneKeepExternalFillets ) return false;
1229 if( m_MaxError != aOther.m_MaxError ) return false;
1230 if( m_SolderMaskExpansion != aOther.m_SolderMaskExpansion ) return false;
1231 if( m_SolderMaskMinWidth != aOther.m_SolderMaskMinWidth ) return false;
1233 if( m_SolderPasteMargin != aOther.m_SolderPasteMargin ) return false;
1234 if( m_SolderPasteMarginRatio != aOther.m_SolderPasteMarginRatio ) return false;
1236 if( m_TentViasFront != aOther.m_TentViasFront ) return false;
1237 if( m_TentViasBack != aOther.m_TentViasBack ) return false;
1238 if( m_CoverViasFront != aOther.m_CoverViasFront ) return false;
1239 if( m_CoverViasBack != aOther.m_CoverViasBack ) return false;
1240 if( m_PlugViasFront != aOther.m_PlugViasFront ) return false;
1241 if( m_PlugViasBack != aOther.m_PlugViasBack ) return false;
1242 if( m_CapVias != aOther.m_CapVias ) return false;
1243 if( m_FillVias != aOther.m_FillVias ) return false;
1244 if( m_DefaultFPTextItems != aOther.m_DefaultFPTextItems ) return false;
1245 if( m_UserLayerNames != aOther.m_UserLayerNames ) return false;
1246
1247 if( !std::equal( std::begin( m_LineThickness ), std::end( m_LineThickness ),
1248 std::begin( aOther.m_LineThickness ) ) )
1249 return false;
1250
1251 if( !std::equal( std::begin( m_TextSize ), std::end( m_TextSize ),
1252 std::begin( aOther.m_TextSize ) ) )
1253 return false;
1254
1255 if( !std::equal( std::begin( m_TextThickness ), std::end( m_TextThickness ),
1256 std::begin( aOther.m_TextThickness ) ) )
1257 return false;
1258
1259 if( !std::equal( std::begin( m_TextItalic ), std::end( m_TextItalic ),
1260 std::begin( aOther.m_TextItalic ) ) )
1261 return false;
1262
1263 if( !std::equal( std::begin( m_TextUpright ), std::end( m_TextUpright ),
1264 std::begin( aOther.m_TextUpright ) ) )
1265 return false;
1266
1267 if( m_DimensionUnitsMode != aOther.m_DimensionUnitsMode ) return false;
1268 if( m_DimensionPrecision != aOther.m_DimensionPrecision ) return false;
1269 if( m_DimensionUnitsFormat != aOther.m_DimensionUnitsFormat ) return false;
1270 if( m_DimensionSuppressZeroes != aOther.m_DimensionSuppressZeroes ) return false;
1271 if( m_DimensionTextPosition != aOther.m_DimensionTextPosition ) return false;
1272 if( m_DimensionKeepTextAligned != aOther.m_DimensionKeepTextAligned ) return false;
1273 if( m_DimensionArrowLength != aOther.m_DimensionArrowLength ) return false;
1274 if( m_DimensionExtensionOffset != aOther.m_DimensionExtensionOffset ) return false;
1275 if( m_auxOrigin != aOther.m_auxOrigin ) return false;
1276 if( m_gridOrigin != aOther.m_gridOrigin ) return false;
1277 if( m_HasStackup != aOther.m_HasStackup ) return false;
1278 if( m_UseHeightForLengthCalcs != aOther.m_UseHeightForLengthCalcs ) return false;
1279 if( m_trackWidthIndex != aOther.m_trackWidthIndex ) return false;
1280 if( m_viaSizeIndex != aOther.m_viaSizeIndex ) return false;
1281 if( m_diffPairIndex != aOther.m_diffPairIndex ) return false;
1282 if( m_useCustomTrackVia != aOther.m_useCustomTrackVia ) return false;
1283 if( m_customTrackWidth != aOther.m_customTrackWidth ) return false;
1284 if( m_customViaSize != aOther.m_customViaSize ) return false;
1285 if( m_useCustomDiffPair != aOther.m_useCustomDiffPair ) return false;
1286 if( m_customDiffPair != aOther.m_customDiffPair ) return false;
1287 if( m_copperLayerCount != aOther.m_copperLayerCount ) return false;
1288 if( m_userDefinedLayerCount != aOther.m_userDefinedLayerCount ) return false;
1289 if( m_enabledLayers != aOther.m_enabledLayers ) return false;
1290 if( m_boardThickness != aOther.m_boardThickness ) return false;
1291 if( m_currentNetClassName != aOther.m_currentNetClassName ) return false;
1292 if( m_stackup != aOther.m_stackup ) return false;
1293 if( *m_NetSettings != *aOther.m_NetSettings ) return false;
1294 if( *m_Pad_Master != *aOther.m_Pad_Master ) return false;
1295 if( m_defaultZoneSettings != aOther.m_defaultZoneSettings ) return false;
1296
1297 if( m_StyleFPFields != aOther.m_StyleFPFields ) return false;
1298 if( m_StyleFPText != aOther.m_StyleFPText ) return false;
1299 if( m_StyleFPShapes != aOther.m_StyleFPShapes ) return false;
1300 if( m_StyleFPDimensions != aOther.m_StyleFPDimensions ) return false;
1301 if( m_StyleFPBarcodes != aOther.m_StyleFPBarcodes ) return false;
1302
1303 return true;
1304}
1305
1306
1308{
1326 std::string units_ptr( "defaults.dimension_units" );
1327 std::string precision_ptr( "defaults.dimension_precision" );
1328
1329 if( !( Contains( units_ptr )
1330 && Contains( precision_ptr )
1331 && At( units_ptr ).is_number_integer()
1332 && At( precision_ptr ).is_number_integer() ) )
1333 {
1334 // if either is missing or invalid, migration doesn't make sense
1335 return true;
1336 }
1337
1338 int units = *Get<int>( units_ptr );
1339 int precision = *Get<int>( precision_ptr );
1340
1341 // The enum maps directly to precision if the units is mils
1342 int extraDigits = 0;
1343
1344 switch( units )
1345 {
1346 case 0: extraDigits = 3; break;
1347 case 2: extraDigits = 2; break;
1348 default: break;
1349 }
1350
1351 precision += extraDigits;
1352
1353 Set( precision_ptr, precision );
1354
1355 return true;
1356}
1357
1358
1359bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
1360{
1361 bool ret = NESTED_SETTINGS::LoadFromFile( aDirectory );
1362
1363 // A number of things won't have been translated by the PROJECT_FILE migration because of
1364 // descoped objects required to decode this data. So, it will be in the legacy.pcbnew
1365 // section and needs to be pulled out here
1366
1367 PROJECT_FILE* project = dynamic_cast<PROJECT_FILE*>( GetParent() );
1368
1369 if( !project )
1370 return ret;
1371
1372 bool migrated = false;
1373
1374 auto drcName =
1375 []( int aCode ) -> std::string
1376 {
1377 return std::string( DRC_ITEM::Create( aCode )->GetSettingsKey().ToUTF8() );
1378 };
1379
1380 const std::string rs = "rule_severities.";
1381 const std::string no_courtyard_key = "legacy_no_courtyard_defined";
1382 const std::string courtyard_overlap_key = "legacy_courtyards_overlap";
1383
1384 try
1385 {
1386 nlohmann::json& severities =
1387 project->Internals()->at( "/board/design_settings/rule_severities"_json_pointer );
1388
1389 if( severities.contains( no_courtyard_key ) )
1390 {
1391 if( severities[no_courtyard_key].get<bool>() )
1392 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "error" );
1393 else
1394 Set( rs + drcName( DRCE_MISSING_COURTYARD ), "ignore" );
1395
1396 severities.erase( no_courtyard_key );
1397 migrated = true;
1398 }
1399
1400 if( severities.contains( courtyard_overlap_key ) )
1401 {
1402 if( severities[courtyard_overlap_key].get<bool>() )
1403 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "error" );
1404 else
1405 Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "ignore" );
1406
1407 severities.erase( courtyard_overlap_key );
1408 migrated = true;
1409 }
1410 }
1411 catch( ... )
1412 {
1413 }
1414
1415 if( Contains( "legacy" ) )
1416 {
1417 // This defaults to false for new boards, but version 5.1.x and prior kept the fillets
1418 // so we do the same for legacy boards.
1420
1421 project->At( "legacy" ).erase( "pcbnew" );
1422 }
1423
1424 // Now that we have everything, we need to load again
1425 if( migrated )
1426 Load();
1427
1428 return ret;
1429}
1430
1431
1433{
1434 return m_DRCSeverities[ aDRCErrorCode ];
1435}
1436
1437
1438bool BOARD_DESIGN_SETTINGS::Ignore( int aDRCErrorCode )
1439{
1440 return m_DRCSeverities[ aDRCErrorCode ] == RPT_SEVERITY_IGNORE;
1441}
1442
1443
1444std::vector<BOARD_DESIGN_SETTINGS::VALIDATION_ERROR>
1445BOARD_DESIGN_SETTINGS::ValidateDesignRules( std::optional<EDA_UNITS> aUnits ) const
1446{
1447 std::vector<VALIDATION_ERROR> errors;
1448 EDA_UNITS units = aUnits.value_or( EDA_UNITS::MM );
1449
1450 auto addRangeError =
1451 [&]( const wxString& aField, int aValue, int aMin, int aMax )
1452 {
1453 if( aValue < aMin || aValue > aMax )
1454 {
1455 wxString minValue = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units,
1456 aMin, true );
1457 wxString maxValue = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units,
1458 aMax, true );
1459
1460 errors.push_back( {
1461 aField,
1462 wxString::Format( _( "Value must be between %s and %s." ),
1463 minValue, maxValue )
1464 } );
1465 }
1466 };
1467
1468 auto addRatioRangeError =
1469 [&]( const wxString& aField, double aValue, double aMin, double aMax )
1470 {
1471 if( !std::isfinite( aValue ) || aValue < aMin || aValue > aMax )
1472 {
1473 errors.push_back( {
1474 aField,
1475 wxString::Format( _( "Value must be between %.3f and %.3f." ),
1476 aMin, aMax )
1477 } );
1478 }
1479 };
1480
1481 addRangeError( wxS( "min_clearance" ), m_MinClearance,
1482 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1483 addRangeError( wxS( "min_connection" ), m_MinConn,
1484 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ) );
1485 addRangeError( wxS( "min_track_width" ), m_TrackMinWidth,
1486 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1487 addRangeError( wxS( "min_via_annular_width" ), m_ViasMinAnnularWidth,
1488 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1489 addRangeError( wxS( "min_via_diameter" ), m_ViasMinSize,
1490 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1491 addRangeError( wxS( "min_through_hole_diameter" ), m_MinThroughDrill,
1492 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1493 addRangeError( wxS( "min_microvia_diameter" ), m_MicroViasMinSize,
1494 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ) );
1495 addRangeError( wxS( "min_microvia_drill" ), m_MicroViasMinDrill,
1496 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ) );
1497 addRangeError( wxS( "min_hole_to_hole" ), m_HoleToHoleMin,
1498 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ) );
1499 addRangeError( wxS( "min_hole_clearance" ), m_HoleClearance,
1500 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ) );
1501 addRangeError( wxS( "min_silk_clearance" ), m_SilkClearance,
1502 pcbIUScale.mmToIU( -10.0 ), pcbIUScale.mmToIU( 100.0 ) );
1503 addRangeError( wxS( "min_groove_width" ), m_MinGrooveWidth,
1504 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1505 addRangeError( wxS( "min_text_height" ), m_MinSilkTextHeight,
1506 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ) );
1507 addRangeError( wxS( "min_text_thickness" ), m_MinSilkTextThickness,
1508 pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ) );
1509 addRangeError( wxS( "min_copper_edge_clearance" ), m_CopperEdgeClearance,
1510 pcbIUScale.mmToIU( -0.01 ), pcbIUScale.mmToIU( 25.0 ) );
1511
1513 {
1514 errors.push_back( {
1515 wxS( "min_resolved_spokes" ),
1516 _( "Value must be between 0 and 99." )
1517 } );
1518 }
1519
1520 addRangeError( wxS( "max_error" ), m_MaxError,
1523
1524 addRangeError( wxS( "solder_mask_expansion" ), m_SolderMaskExpansion,
1525 pcbIUScale.mmToIU( -25.0 ), pcbIUScale.mmToIU( 25.0 ) );
1526 addRangeError( wxS( "solder_mask_min_width" ), m_SolderMaskMinWidth,
1527 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ) );
1528 addRangeError( wxS( "solder_mask_to_copper_clearance" ), m_SolderMaskToCopperClearance,
1529 pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ) );
1530 addRangeError( wxS( "solder_paste_margin" ), m_SolderPasteMargin,
1531 pcbIUScale.mmToIU( -25.0 ), pcbIUScale.mmToIU( 25.0 ) );
1532 addRatioRangeError( wxS( "solder_paste_margin_ratio" ), m_SolderPasteMarginRatio,
1533 -1.0, 1.0 );
1534
1535 TEARDROP_PARAMETERS_LIST& teardropParamsList =
1537
1538 for( size_t ii = 0; ii < teardropParamsList.GetParametersCount(); ++ii )
1539 {
1540 const TEARDROP_PARAMETERS* params = teardropParamsList.GetParameters( static_cast<TARGET_TD>( ii ) );
1541 std::string target = GetTeardropTargetCanonicalName( static_cast<TARGET_TD>( ii ) );
1542
1543 if( params->m_TdMaxLen < 0 )
1544 {
1545 errors.push_back( {
1546 wxString::Format( wxS( "teardrop_parameters[%s].max_length" ), target ),
1547 _( "Value must be greater than or equal to 0." )
1548 } );
1549 }
1550
1551 if( params->m_TdMaxWidth < 0 )
1552 {
1553 errors.push_back( {
1554 wxString::Format( wxS( "teardrop_parameters[%s].max_width" ), target ),
1555 _( "Value must be greater than or equal to 0." )
1556 } );
1557 }
1558
1559 addRatioRangeError( wxString::Format( wxS( "teardrop_parameters[%s].best_length_ratio" ), target ),
1560 params->m_BestLengthRatio, 0.0, 1.0 );
1561 addRatioRangeError( wxString::Format( wxS( "teardrop_parameters[%s].best_width_ratio" ), target ),
1562 params->m_BestWidthRatio, 0.0, 1.0 );
1563 addRatioRangeError( wxString::Format( wxS( "teardrop_parameters[%s].width_to_size_filter_ratio" ),
1564 target ),
1565 params->m_WidthtoSizeFilterRatio, 0.0, 1.0 );
1566 }
1567
1568 for( size_t ii = 1; ii < m_DiffPairDimensionsList.size(); ++ii )
1569 {
1570 const DIFF_PAIR_DIMENSION& diffPair = m_DiffPairDimensionsList[ii];
1571
1572 if( diffPair.m_Width > 0 && diffPair.m_Gap <= 0 )
1573 {
1574 errors.push_back( {
1575 wxString::Format( wxS( "diff_pair_dimensions_list[%zu].gap" ), ii ),
1576 _( "No differential pair gap defined." )
1577 } );
1578 }
1579 }
1580
1581 for( size_t ii = 1; ii < m_ViasDimensionsList.size(); ++ii )
1582 {
1583 const VIA_DIMENSION& viaDim = m_ViasDimensionsList[ii];
1584
1585 std::optional<int> viaDiameter;
1586 std::optional<int> viaDrill;
1587
1588 if( viaDim.m_Diameter > 0 )
1589 viaDiameter = viaDim.m_Diameter;
1590
1591 if( viaDim.m_Drill > 0 )
1592 viaDrill = viaDim.m_Drill;
1593
1594 if( std::optional<PCB_VIA::VIA_PARAMETER_ERROR> error =
1595 PCB_VIA::ValidateViaParameters( viaDiameter, viaDrill ) )
1596 {
1597 errors.push_back( {
1598 wxString::Format( wxS( "via_dimensions_list[%zu]" ), ii ),
1599 error->m_Message
1600 } );
1601 }
1602 }
1603
1604 return errors;
1605}
1606
1607
1609{
1610 int biggest = std::max( m_MinClearance, m_HoleClearance );
1611 DRC_CONSTRAINT constraint;
1612
1613 biggest = std::max( biggest, m_HoleToHoleMin );
1614 biggest = std::max( biggest, m_CopperEdgeClearance );
1615
1616 if( m_DRCEngine )
1617 {
1618 m_DRCEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, constraint );
1619 biggest = std::max( biggest, constraint.Value().Min() );
1620
1621 m_DRCEngine->QueryWorstConstraint( PHYSICAL_CLEARANCE_CONSTRAINT, constraint );
1622 biggest = std::max( biggest, constraint.Value().Min() );
1623
1624 m_DRCEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, constraint );
1625 biggest = std::max( biggest, constraint.Value().Min() );
1626
1627 m_DRCEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, constraint );
1628 biggest = std::max( biggest, constraint.Value().Min() );
1629
1630 m_DRCEngine->QueryWorstConstraint( HOLE_TO_HOLE_CONSTRAINT, constraint );
1631 biggest = std::max( biggest, constraint.Value().Min() );
1632 }
1633
1634 // Clip to avoid integer overflows in subsequent calculations
1635 return std::min( biggest, MAXIMUM_CLEARANCE );
1636}
1637
1638
1640{
1641 int clearance = m_NetSettings->GetDefaultNetclass()->GetClearance();
1642
1643 for( const auto& [name, netclass] : m_NetSettings->GetNetclasses() )
1644 clearance = std::min( clearance, netclass->GetClearance() );
1645
1646 return clearance;
1647}
1648
1649
1651{
1652 m_viaSizeIndex = std::min( aIndex, (int) m_ViasDimensionsList.size() - 1 );
1653 m_useCustomTrackVia = false;
1654}
1655
1656
1658{
1660 return m_customViaSize.m_Diameter;
1662 return m_NetSettings->GetDefaultNetclass()->GetViaDiameter();
1663 else
1664 return m_ViasDimensionsList[ m_viaSizeIndex ].m_Diameter;
1665}
1666
1667
1669{
1670 int drill;
1671
1673 drill = m_customViaSize.m_Drill;
1675 drill = m_NetSettings->GetDefaultNetclass()->GetViaDrill();
1676 else
1677 drill = m_ViasDimensionsList[ m_viaSizeIndex ].m_Drill;
1678
1679 return drill > 0 ? drill : -1;
1680}
1681
1682
1684{
1685 m_trackWidthIndex = std::min( aIndex, (int) m_TrackWidthList.size() - 1 );
1686 m_useCustomTrackVia = false;
1687}
1688
1689
1691{
1693 return m_customTrackWidth;
1695 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1696 else
1698}
1699
1700
1702{
1703 if( !m_DiffPairDimensionsList.empty() )
1704 m_diffPairIndex = std::min( aIndex, (int) m_DiffPairDimensionsList.size() - 1 );
1705
1706 m_useCustomDiffPair = false;
1707}
1708
1709
1711{
1713 {
1714 return m_customDiffPair.m_Width;
1715 }
1717 {
1718 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairWidth() )
1719 return m_NetSettings->GetDefaultNetclass()->GetDiffPairWidth();
1720 else
1721 return m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1722 }
1723 else
1724 {
1726 }
1727}
1728
1729
1731{
1733 {
1734 return m_customDiffPair.m_Gap;
1735 }
1737 {
1738 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairGap() )
1739 return m_NetSettings->GetDefaultNetclass()->GetDiffPairGap();
1740 else
1741 return m_NetSettings->GetDefaultNetclass()->GetClearance();
1742 }
1743 else
1744 {
1746 }
1747}
1748
1749
1751{
1753 {
1754 return m_customDiffPair.m_ViaGap;
1755 }
1757 {
1758 if( m_NetSettings->GetDefaultNetclass()->HasDiffPairViaGap() )
1759 return m_NetSettings->GetDefaultNetclass()->GetDiffPairViaGap();
1760 else
1761 return GetCurrentDiffPairGap();
1762 }
1763 else
1764 {
1766 }
1767}
1768
1769
1771{
1772 m_copperLayerCount = aNewLayerCount;
1773
1774 // Update only enabled copper layers mask
1775 m_enabledLayers.ClearCopperLayers();
1776
1777 if( aNewLayerCount > 0 )
1778 m_enabledLayers |= LSET::AllCuMask( aNewLayerCount );
1779}
1780
1781
1783{
1784 m_userDefinedLayerCount = aNewLayerCount;
1785
1786 m_enabledLayers.ClearUserDefinedLayers();
1787
1788 if( aNewLayerCount > 0 )
1789 m_enabledLayers |= LSET::UserDefinedLayersMask( aNewLayerCount );
1790}
1791
1792
1794{
1795 m_enabledLayers = aMask;
1796
1797 // Ensures mandatory back and front layers are always enabled regardless of board file
1798 // configuration.
1799 m_enabledLayers.set( B_Cu ).set( F_Cu )
1800 .set( B_CrtYd ).set( F_CrtYd )
1801 .set( Edge_Cuts )
1802 .set( Margin );
1803
1804 // update layer counts to ensure their consistency with m_EnabledLayers
1805 LSET copperLayers = aMask;
1806 copperLayers.ClearNonCopperLayers();
1807
1808 LSET userLayers = aMask & LSET::UserDefinedLayersMask();
1809
1810 m_copperLayerCount = (int) copperLayers.count();
1811 m_userDefinedLayerCount = (int) userLayers.count();
1812}
1813
1814
1815// Return the layer class index { silk, copper, edges & courtyards, fab, others } of the
1816// given layer.
1818{
1819 if( aLayer == F_SilkS || aLayer == B_SilkS )
1820 return LAYER_CLASS_SILK;
1821 else if( IsCopperLayer( aLayer ) )
1822 return LAYER_CLASS_COPPER;
1823 else if( aLayer == Edge_Cuts )
1824 return LAYER_CLASS_EDGES;
1825 else if( aLayer == F_CrtYd || aLayer == B_CrtYd )
1826 return LAYER_CLASS_COURTYARD;
1827 else if( aLayer == F_Fab || aLayer == B_Fab )
1828 return LAYER_CLASS_FAB;
1829 else
1830 return LAYER_CLASS_OTHERS;
1831}
1832
1833
1835{
1836 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
1837}
1838
1839
1841{
1842 return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
1843}
1844
1845
1847{
1848 return m_LineThickness[ GetLayerClass( aLayer ) ];
1849}
1850
1851
1853{
1854 return m_TextSize[ GetLayerClass( aLayer ) ];
1855}
1856
1857
1859{
1860 return m_TextThickness[ GetLayerClass( aLayer ) ];
1861}
1862
1863
1865{
1866 return m_TextItalic[ GetLayerClass( aLayer ) ];
1867}
1868
1869
1871{
1872 return m_TextUpright[ GetLayerClass( aLayer ) ];
1873}
1874
1876{
1877 m_Pad_Master->SetSizeX( pcbIUScale.mmToIU( DEFAULT_PAD_WIDTH_MM ) );
1878 m_Pad_Master->SetSizeY( pcbIUScale.mmToIU( DEFAULT_PAD_HEIGTH_MM ) );
1879 m_Pad_Master->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
1880 m_Pad_Master->SetDrillSize( VECTOR2I( pcbIUScale.mmToIU( DEFAULT_PAD_DRILL_DIAMETER_MM ), 0 ) );
1882
1883 constexpr double RR_RADIUS = DEFAULT_PAD_HEIGTH_MM * DEFAULT_PAD_RR_RADIUS_RATIO;
1884 m_Pad_Master->SetRoundRectCornerRadius( PADSTACK::ALL_LAYERS, pcbIUScale.mmToIU( RR_RADIUS ) );
1885
1886 if( m_Pad_Master->GetFrontShape() == PAD_SHAPE::CIRCLE )
1887 m_Pad_Master->SetThermalSpokeAngle( ANGLE_45 );
1888 else
1889 m_Pad_Master->SetThermalSpokeAngle( ANGLE_90 );
1890}
const char * name
constexpr int ARC_HIGH_DEF
Definition base_units.h:141
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:125
const int bdsSchemaVersion
#define DEFAULT_MICROVIASMINDRILL
#define DEFAULT_SOLDERPASTE_CLEARANCE
#define DEFAULT_SOLDERPASTE_RATIO
#define DEFAULT_CUSTOMDPAIRWIDTH
#define DEFAULT_DP_MEANDER_SPACING
@ LAYER_CLASS_OTHERS
@ LAYER_CLASS_FAB
@ LAYER_CLASS_COURTYARD
@ LAYER_CLASS_SILK
@ LAYER_CLASS_COPPER
@ LAYER_CLASS_EDGES
#define DEFAULT_PAD_WIDTH_MM
#define DEFAULT_VIASMINSIZE
#define DEFAULT_PAD_DRILL_DIAMETER_MM
#define DEFAULT_TEXT_WIDTH
#define DEFAULT_COPPER_TEXT_WIDTH
#define DEFAULT_CUSTOMDPAIRGAP
#define DEFAULT_MINCLEARANCE
#define MAXIMUM_ERROR_SIZE_MM
#define DEFAULT_HOLECLEARANCE
#define DEFAULT_SOLDERMASK_EXPANSION
#define DEFAULT_SOLDERMASK_MIN_WIDTH
#define MINIMUM_ERROR_SIZE_MM
#define DEFAULT_DIMENSION_EXTENSION_OFFSET
#define DEFAULT_COPPEREDGECLEARANCE
#define DEFAULT_PAD_HEIGTH_MM
#define DEFAULT_DIMENSION_ARROW_LENGTH
#define DEFAULT_TRACKMINWIDTH
#define DEFAULT_MINTHROUGHDRILL
#define DEFAULT_PAD_RR_RADIUS_RATIO
#define DEFAULT_SILK_TEXT_SIZE
#define MAXIMUM_CLEARANCE
#define DEFAULT_HOLETOHOLEMIN
#define DEFAULT_MINCONNECTION
#define DEFAULT_COPPER_LINE_WIDTH
#define DEFAULT_SILK_LINE_WIDTH
#define DEFAULT_SILKCLEARANCE
#define DEFAULT_MICROVIASMINSIZE
#define DEFAULT_SILK_TEXT_WIDTH
#define DEFAULT_MINGROOVEWIDTH
#define DEFAULT_TEXT_SIZE
#define DEFAULT_EDGE_WIDTH
#define DEFAULT_CUSTOMTRACKWIDTH
#define DEFAULT_CUSTOMDPAIRVIAGAP
#define DEFAULT_COPPER_TEXT_SIZE
#define DEFAULT_SOLDERMASK_TO_COPPER_CLEARANCE
#define DEFAULT_LINE_WIDTH
#define DEFAULT_MEANDER_SPACING
#define DEFAULT_COURTYARD_WIDTH
#define DEFAULT_BOARD_THICKNESS_MM
#define DEFAULT_MINRESOLVEDSPOKES
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
BASE_SET & set(size_t pos)
Definition base_set.h:116
DIM_PRECISION m_DimensionPrecision
Number of digits after the decimal.
std::vector< TEXT_ITEM_INFO > m_DefaultFPTextItems
int GetHolePlatingThickness() const
Pad & via drills are finish size.
VIATYPE m_CurrentViaType
(VIA_BLIND_BURIED, VIA_THROUGH, VIA_MICROVIA)
void SetEnabledLayers(const LSET &aMask)
Change the bit-mask of enabled layers to aMask.
std::shared_ptr< NET_SETTINGS > m_NetSettings
bool operator==(const BOARD_DESIGN_SETTINGS &aOther) const
std::map< wxString, wxString > m_DrcExclusionComments
DIM_UNITS_FORMAT m_DimensionUnitsFormat
void initFromOther(const BOARD_DESIGN_SETTINGS &aOther)
bool GetTextUpright(PCB_LAYER_ID aLayer) const
std::map< int, SEVERITY > m_DRCSeverities
VECTOR2I m_gridOrigin
origin for grid offsets
int GetTextThickness(PCB_LAYER_ID aLayer) const
Return the default text thickness from the layer class for the given layer.
VECTOR2I m_auxOrigin
origin for plot exports
bool m_TextUpright[LAYER_CLASS_COUNT]
BOARD_DESIGN_SETTINGS(JSON_SETTINGS *aParent, const std::string &aPath)
bool GetTextItalic(PCB_LAYER_ID aLayer) const
wxString m_currentNetClassName
Current net class name used to display netclass info.
void SetViaSizeIndex(int aIndex)
Set the current via size list index to aIndex.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
std::set< wxString > m_DrcExclusions
bool Ignore(int aDRCErrorCode)
Return true if the DRC error code's severity is SEVERITY_IGNORE.
std::map< std::string, wxString > m_UserLayerNames
std::unique_ptr< PAD > m_Pad_Master
TEARDROP_PARAMETERS_LIST m_TeardropParamsList
The parameters of teardrops for the different teardrop targets (via/pad, track end).
void SetUserDefinedLayerCount(int aNewLayerCount)
Set the number of user defined layers to aNewLayerCount.
int GetDRCEpsilon() const
Return an epsilon which accounts for rounding errors, etc.
int GetLayerClass(PCB_LAYER_ID aLayer) const
PNS::MEANDER_SETTINGS m_DiffPairMeanderSettings
int m_boardThickness
Board thickness for 3D viewer.
int m_copperLayerCount
Number of copper layers for this design.
int m_userDefinedLayerCount
Number of user defined layers for this design.
bool LoadFromFile(const wxString &aDirectory="") override
Loads the backing file from disk and then calls Load()
PNS::MEANDER_SETTINGS m_SingleTrackMeanderSettings
void SetTrackWidthIndex(int aIndex)
Set the current track width list index to aIndex.
int m_TextThickness[LAYER_CLASS_COUNT]
ZONE_SETTINGS m_defaultZoneSettings
The default settings that will be used for new zones.
SEVERITY GetSeverity(int aDRCErrorCode)
std::vector< int > m_TrackWidthList
DIFF_PAIR_DIMENSION m_customDiffPair
std::vector< VALIDATION_ERROR > ValidateDesignRules(std::optional< EDA_UNITS > aUnits=std::nullopt) const
Validate design settings values and return per-field errors.
int m_LineThickness[LAYER_CLASS_COUNT]
VECTOR2I GetTextSize(PCB_LAYER_ID aLayer) const
Return the default text size from the layer class for the given layer.
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
bool m_UseHeightForLengthCalcs
Enable inclusion of stackup height in track length measurements and length tuning.
VECTOR2I m_TextSize[LAYER_CLASS_COUNT]
PNS::MEANDER_SETTINGS m_SkewMeanderSettings
LSET m_enabledLayers
Bit-mask for layer enabling.
bool m_TextItalic[LAYER_CLASS_COUNT]
void SetCopperLayerCount(int aNewLayerCount)
Set the copper layer count to aNewLayerCount.
DIM_TEXT_POSITION m_DimensionTextPosition
BOARD_STACKUP m_stackup
The description of layers stackup, for board fabrication only physical layers are in layers stackup.
std::vector< VIA_DIMENSION > m_ViasDimensionsList
BOARD_DESIGN_SETTINGS & operator=(const BOARD_DESIGN_SETTINGS &aOther)
MINOPTMAX< int > & Value()
Definition drc_rule.h:201
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition drc_item.h:145
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition drc_item.cpp:417
void Set(const std::string &aPath, ValueType aVal)
Stores a value into the JSON document Will throw an exception if ValueType isn't something that the l...
bool Contains(const std::string &aPath) const
virtual void Load()
Updates the parameters of this object based on the current JSON document contents.
std::optional< ValueType > Get(const std::string &aPath) const
Fetches a value from within the JSON document.
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
void registerMigration(int aOldSchemaVersion, int aNewSchemaVersion, std::function< bool(void)> aMigrator)
Registers a migration from one schema version to another.
nlohmann::json & At(const std::string &aPath)
Wrappers for the underlying JSON API so that most consumers don't need json.hpp All of these function...
JSON_SETTINGS(const wxString &aFilename, SETTINGS_LOC aLocation, int aSchemaVersion)
bool m_resetParamsIfMissing
Whether or not to set parameters to their default value if missing from JSON on Load()
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:608
LSET & ClearNonCopperLayers()
Clear the non-copper layers in this set.
Definition lset.cpp:950
static LSET UserDefinedLayersMask(int aUserDefinedLayerCount=MAX_USER_DEFINED_LAYERS)
Return a mask with the requested number of user defined layers.
Definition lset.cpp:704
T Min() const
Definition minoptmax.h:33
std::string m_path
The path (in pointer format) of where to store this document in the parent.
JSON_SETTINGS * GetParent()
JSON_SETTINGS * m_parent
A pointer to the parent object to load and store from.
NESTED_SETTINGS(const std::string &aName, int aSchemaVersion, JSON_SETTINGS *aParent, const std::string &aPath, bool aLoadFromFile=true)
bool LoadFromFile(const wxString &aDirectory="") override
Loads the JSON document from the parent and then calls Load()
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:177
Stores an enum as an integer.
Definition parameters.h:230
Like a normal param, but with custom getter and setter functions.
Definition parameters.h:297
Represents a parameter that has a scaling factor between the value in the file and the value used int...
Definition parameters.h:394
static std::optional< VIA_PARAMETER_ERROR > ValidateViaParameters(std::optional< int > aDiameter, std::optional< int > aPrimaryDrill, std::optional< PCB_LAYER_ID > aPrimaryStartLayer=std::nullopt, std::optional< PCB_LAYER_ID > aPrimaryEndLayer=std::nullopt, std::optional< int > aSecondaryDrill=std::nullopt, std::optional< PCB_LAYER_ID > aSecondaryStartLayer=std::nullopt, std::optional< PCB_LAYER_ID > aSecondaryEndLayer=std::nullopt, std::optional< int > aTertiaryDrill=std::nullopt, std::optional< PCB_LAYER_ID > aTertiaryStartLayer=std::nullopt, std::optional< PCB_LAYER_ID > aTertiaryEndLayer=std::nullopt, int aCopperLayerCount=0)
Dimensions for the meandering algorithm.
Definition pns_meander.h:70
int m_minAmplitude
Maximum meandering amplitude.
int m_cornerRadiusPercentage
Place meanders on one side.
bool m_singleSided
Initial side when placing meanders at segment.
MEANDER_STYLE m_cornerStyle
Rounding percentage (0 - 100).
int m_maxAmplitude
Meandering period/spacing (see dialog picture for explanation).
int m_spacing
Amplitude/spacing adjustment step.
The backing store for a PROJECT, in JSON format.
A holder for a rule check item, DRC in Pcbnew or ERC in Eeschema.
Definition rc_item.h:84
TEARDROP_PARAMETERS_LIST is a helper class to handle the list of TEARDROP_PARAMETERS needed to build ...
TEARDROP_PARAMETERS * GetParameters(TARGET_TD aTdType)
TEARDROP_PARAMETARS is a helper class to handle parameters needed to build teardrops for a board thes...
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_CurvedEdges
True if the teardrop should be curved.
@ DRCE_TUNING_PROFILE_IMPLICIT_RULES
Definition drc_item.h:116
@ DRCE_SILK_EDGE_CLEARANCE
Definition drc_item.h:99
@ DRCE_FOOTPRINT_FILTERS
Definition drc_item.h:80
@ DRCE_SILK_MASK_CLEARANCE
Definition drc_item.h:97
@ DRCE_PADSTACK
Definition drc_item.h:63
@ DRCE_MIRRORED_TEXT_ON_FRONT_LAYER
Definition drc_item.h:112
@ DRCE_LIB_FOOTPRINT_ISSUES
Definition drc_item.h:83
@ DRCE_OVERLAPPING_FOOTPRINTS
Definition drc_item.h:66
@ DRCE_SCHEMATIC_FIELDS_PARITY
Definition drc_item.h:122
@ DRCE_MISSING_COURTYARD
Definition drc_item.h:67
@ DRCE_TRACK_NOT_CENTERED_ON_VIA
Definition drc_item.h:120
@ DRCE_ISOLATED_COPPER
Definition drc_item.h:49
@ DRCE_MISSING_TUNING_PROFILE
Definition drc_item.h:115
@ DRCE_DRILLED_HOLES_TOO_CLOSE
Definition drc_item.h:53
@ DRCE_COPPER_SLIVER
Definition drc_item.h:93
@ DRCE_PTH_IN_COURTYARD
Definition drc_item.h:70
@ DRCE_FIRST
Definition drc_item.h:39
@ DRCE_DANGLING_VIA
Definition drc_item.h:51
@ DRCE_FOOTPRINT_TYPE_MISMATCH
Definition drc_item.h:82
@ DRCE_NONMIRRORED_TEXT_ON_BACK_LAYER
Definition drc_item.h:113
@ DRCE_DUPLICATE_FOOTPRINT
Definition drc_item.h:76
@ DRCE_DANGLING_TRACK
Definition drc_item.h:52
@ DRCE_TEXT_HEIGHT
Definition drc_item.h:101
@ DRCE_DRILLED_HOLES_COLOCATED
Definition drc_item.h:54
@ DRCE_EXTRA_FOOTPRINT
Definition drc_item.h:77
@ DRCE_SILK_CLEARANCE
Definition drc_item.h:100
@ DRCE_LAST
Definition drc_item.h:124
@ DRCE_LIB_FOOTPRINT_MISMATCH
Definition drc_item.h:84
@ DRCE_NET_CONFLICT
Definition drc_item.h:78
@ DRCE_MISSING_FOOTPRINT
Definition drc_item.h:75
@ DRCE_TEXT_THICKNESS
Definition drc_item.h:102
@ DRCE_NPTH_IN_COURTYARD
Definition drc_item.h:71
@ DRCE_CONNECTION_WIDTH
Definition drc_item.h:60
@ DRCE_SCHEMATIC_PARITY
Definition drc_item.h:79
@ EDGE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:59
@ CLEARANCE_CONSTRAINT
Definition drc_rule.h:55
@ HOLE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:57
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition drc_rule.h:86
@ HOLE_TO_HOLE_CONSTRAINT
Definition drc_rule.h:58
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:413
@ DEGREES_T
Definition eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_45
Definition eda_angle.h:412
#define TEXT_MIN_SIZE_MM
Minimum text size (1 micron).
Definition eda_text.h:60
#define TEXT_MAX_SIZE_MM
Maximum text size in mm (~10 inches)
Definition eda_text.h:61
EDA_UNITS
Definition eda_units.h:48
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:679
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
KICOMMON_API wxString StringFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Return the string from aValue according to aUnits (inch, mm ...) for display.
@ MEANDER_STYLE_ROUND
Definition pns_meander.h:54
@ MEANDER_STYLE_CHAMFER
Definition pns_meander.h:55
@ ROUNDRECT
Definition padstack.h:57
@ OUTSIDE
Text appears outside the dimension line (default)
@ INLINE
Text appears in line with the dimension line.
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_IGNORE
Container to handle a stock of specific differential pairs each with unique track width,...
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
std::string GetTeardropTargetCanonicalName(TARGET_TD aTdType)
TARGET_TD GetTeardropTargetTypeFromCanonicalName(const std::string &aTargetName)
int clearance
SEVERITY SeverityFromString(const wxString &aSeverity)
Definition ui_common.cpp:56
wxString SeverityToString(const SEVERITY &aSeverity)
Definition ui_common.cpp:67
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687
ISLAND_REMOVAL_MODE
Whether or not to remove isolated islands from a zone.
#define ZONE_THERMAL_RELIEF_GAP_MM
Definition zones.h:32
ZONE_CONNECTION
How pads are covered by copper in zone.
Definition zones.h:47
@ THERMAL
Use thermal relief for pads.
Definition zones.h:50
#define ZONE_BORDER_HATCH_DIST_MM
Definition zones.h:38
#define ZONE_BORDER_HATCH_MINDIST_MM
Definition zones.h:39
#define ZONE_THERMAL_RELIEF_COPPER_WIDTH_MM
Definition zones.h:33
#define ZONE_CLEARANCE_MM
Definition zones.h:36
#define ZONE_THICKNESS_MIN_VALUE_MM
Definition zones.h:35
#define ZONE_THICKNESS_MM
Definition zones.h:34
#define ZONE_BORDER_HATCH_MAXDIST_MM
Definition zones.h:40