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