KiCad PCB EDA Suite
Loading...
Searching...
No Matches
odb_entity.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 * Author: SYSUEric <[email protected]>.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21
22#include <base_units.h>
24#include <build_version.h>
25#include <callback_gal.h>
29#include <font/font.h>
30#include <footprint.h>
31#include <hash_eda.h>
32#include <pad.h>
33#include <pcb_dimension.h>
34#include <pcb_shape.h>
35#include <pcb_text.h>
36#include <pcb_textbox.h>
37#include <pcb_track.h>
38#include <pcbnew_settings.h>
40#include <pgm_base.h>
41#include <progress_reporter.h>
43#include <wx_fstream_progress.h>
44
49
50#include <wx/log.h>
51#include <wx/numformatter.h>
52#include <wx/mstream.h>
53
54#include "odb_attribute.h"
55#include "odb_entity.h"
56#include "odb_defines.h"
57#include "odb_feature.h"
58#include "odb_util.h"
59#include "pcb_io_odbpp.h"
60
61
63{
64 try
65 {
67 return true;
68 }
69 catch( const std::exception& e )
70 {
71 std::cerr << e.what() << std::endl;
72 return false;
73 }
74}
75
76
78{
79 m_info = { { wxS( ODB_JOB_NAME ), wxS( "job" ) },
81 { wxS( "ODB_VERSION_MAJOR" ), wxS( "8" ) },
82 { wxS( "ODB_VERSION_MINOR" ), wxS( "1" ) },
83 { wxS( "ODB_SOURCE" ), wxS( "KiCad EDA" ) },
84 { wxS( "CREATION_DATE" ), wxDateTime::Now().Format( "%Y%m%d.%H%M%S" ) },
85 { wxS( "SAVE_DATE" ), wxDateTime::Now().Format( "%Y%m%d.%H%M%S" ) },
86 { wxS( "SAVE_APP" ), wxString::Format( wxS( "KiCad EDA %s" ), GetBuildVersion() ) } };
87}
88
89
91{
92 auto fileproxy = writer.CreateFileProxy( "info" );
93
94 ODB_TEXT_WRITER twriter( fileproxy.GetStream() );
95
96 for( auto& info : m_info )
97 {
98 twriter.WriteEquationLine( info.first, info.second );
99 }
100}
101
102
103void ODB_MATRIX_ENTITY::AddStep( const wxString& aStepName )
104{
105 m_matrixSteps.emplace( aStepName.Upper(), m_col++ );
106}
107
108
110{
111 AddStep( "PCB" );
112
114}
115
116
118{
119 BOARD_DESIGN_SETTINGS& dsnSettings = m_board->GetDesignSettings();
120 BOARD_STACKUP& stackup = dsnSettings.GetStackupDescriptor();
121 stackup.SynchronizeWithBoard( &dsnSettings );
122
123 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.GetList();
124 std::set<PCB_LAYER_ID> added_layers;
125
127
128 for( int i = 0; i < stackup.GetCount(); i++ )
129 {
130 BOARD_STACKUP_ITEM* stackup_item = layers.at( i );
131
132 for( int sublayer_id = 0; sublayer_id < stackup_item->GetSublayersCount(); sublayer_id++ )
133 {
134 wxString ly_name = stackup_item->GetLayerName();
135
136 if( ly_name.IsEmpty() )
137 {
138 if( IsValidLayer( stackup_item->GetBrdLayerId() ) )
139 ly_name = m_board->GetLayerName( stackup_item->GetBrdLayerId() );
140
141 if( ly_name.IsEmpty() && stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
142 ly_name = wxString::Format( "DIELECTRIC_%d",
143 stackup_item->GetDielectricLayerId() );
144 }
145
146 MATRIX_LAYER matrix( m_row++, ly_name );
147
148 if( stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
149 {
150 if( stackup_item->GetTypeName() == KEY_CORE )
151 matrix.m_diType.emplace( ODB_DIELECTRIC_TYPE::CORE );
152 else
153 matrix.m_diType.emplace( ODB_DIELECTRIC_TYPE::PREPREG );
154
158 m_matrixLayers.push_back( matrix );
159 m_plugin->GetLayerNameList().emplace_back(
160 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
161
162 continue;
163 }
164 else
165 {
166 added_layers.insert( stackup_item->GetBrdLayerId() );
167 AddMatrixLayerField( matrix, stackup_item->GetBrdLayerId() );
168 }
169 }
170 }
171
172 for( PCB_LAYER_ID layer : m_board->GetEnabledLayers().Seq() )
173 {
174 if( added_layers.find( layer ) != added_layers.end() )
175 continue;
176
177 MATRIX_LAYER matrix( m_row++, m_board->GetLayerName( layer ) );
178 added_layers.insert( layer );
179 AddMatrixLayerField( matrix, layer );
180 }
181
183
185
187
189}
190
191
193{
196 switch( aLayer )
197 {
198 case F_Paste:
199 case B_Paste: aMLayer.m_type = ODB_TYPE::SOLDER_PASTE; break;
200 case F_SilkS:
201 case B_SilkS: aMLayer.m_type = ODB_TYPE::SILK_SCREEN; break;
202 case F_Mask:
203 case B_Mask: aMLayer.m_type = ODB_TYPE::SOLDER_MASK; break;
204 case B_CrtYd:
205 case F_CrtYd:
206 case Edge_Cuts:
207 case B_Fab:
208 case F_Fab:
209 case F_Adhes:
210 case B_Adhes:
211 case Dwgs_User:
212 case Cmts_User:
213 case Eco1_User:
214 case Eco2_User:
215 case Margin:
216 case User_1:
217 case User_2:
218 case User_3:
219 case User_4:
220 case User_5:
221 case User_6:
222 case User_7:
223 case User_8:
224 case User_9:
225 case User_10:
226 case User_11:
227 case User_12:
228 case User_13:
229 case User_14:
230 case User_15:
231 case User_16:
232 case User_17:
233 case User_18:
234 case User_19:
235 case User_20:
236 case User_21:
237 case User_22:
238 case User_23:
239 case User_24:
240 case User_25:
241 case User_26:
242 case User_27:
243 case User_28:
244 case User_29:
245 case User_30:
246 case User_31:
247 case User_32:
248 case User_33:
249 case User_34:
250 case User_35:
251 case User_36:
252 case User_37:
253 case User_38:
254 case User_39:
255 case User_40:
256 case User_41:
257 case User_42:
258 case User_43:
259 case User_44:
260 case User_45:
262 aMLayer.m_type = ODB_TYPE::DOCUMENT;
263 break;
264
265 default:
266 if( IsCopperLayer( aLayer ) )
267 {
268 aMLayer.m_type = ODB_TYPE::SIGNAL;
269 }
270 else
271 {
272 // Do not handle other layers :
273 aMLayer.m_type = ODB_TYPE::UNDEFINED;
274 m_row--;
275 }
276
277 break;
278 }
279
280 if( aMLayer.m_type != ODB_TYPE::UNDEFINED )
281 {
282 m_matrixLayers.push_back( aMLayer );
283 m_plugin->GetLayerNameList().emplace_back( std::make_pair( aLayer, aMLayer.m_layerName ) );
284 }
285}
286
287
289{
290 std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& drill_layers =
291 m_plugin->GetDrillLayerItemsMap();
292
293 std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& slot_holes =
294 m_plugin->GetSlotHolesMap();
295
296 bool has_pth_layer = false;
297 bool has_npth_layer = false;
298
299 for( BOARD_ITEM* item : m_board->Tracks() )
300 {
301 if( item->Type() == PCB_VIA_T )
302 {
303 PCB_VIA* via = static_cast<PCB_VIA*>( item );
304 drill_layers[std::make_pair( via->TopLayer(), via->BottomLayer() )].push_back( via );
305 }
306 }
307
308 for( FOOTPRINT* fp : m_board->Footprints() )
309 {
310 // std::shared_ptr<FOOTPRINT> fp( static_cast<FOOTPRINT*>( it_fp->Clone() ) );
311
312 if( fp->IsFlipped() )
313 {
314 m_hasBotComp = true;
315 }
316
317 for( PAD* pad : fp->Pads() )
318 {
319 if( !has_pth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH )
320 has_pth_layer = true;
321 if( !has_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH )
322 has_npth_layer = true;
323
324 if( pad->HasHole() && pad->GetDrillSizeX() != pad->GetDrillSizeY() )
325 slot_holes[std::make_pair( F_Cu, B_Cu )].push_back( pad );
326 else if( pad->HasHole() )
327 drill_layers[std::make_pair( F_Cu, B_Cu )].push_back( pad );
328 }
329
330 // m_plugin->GetLoadedFootprintList().push_back( std::move( fp ) );
331 }
332
333 auto InitDrillMatrix =
334 [&]( const wxString& aHasPlated, std::pair<PCB_LAYER_ID, PCB_LAYER_ID> aLayerPair )
335 {
336 wxString dLayerName = wxString::Format( "drill_%s_%s-%s", aHasPlated,
337 m_board->GetLayerName( aLayerPair.first ),
338 m_board->GetLayerName( aLayerPair.second ) );
339 MATRIX_LAYER matrix( m_row++, dLayerName );
340
341 matrix.m_type = ODB_TYPE::DRILL;
344 matrix.m_span.emplace( std::make_pair(
345 ODB::GenLegalEntityName( m_board->GetLayerName( aLayerPair.first ) ),
346 ODB::GenLegalEntityName( m_board->GetLayerName( aLayerPair.second ) ) ) );
347 m_matrixLayers.push_back( matrix );
348 m_plugin->GetLayerNameList().emplace_back(
349 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
350 };
351
352 if( has_npth_layer )
353 InitDrillMatrix( "non-plated", std::make_pair( F_Cu, B_Cu ) );
354 // at least one non plated hole is present.
355
356 if( has_pth_layer && drill_layers.find( std::make_pair( F_Cu, B_Cu ) ) == drill_layers.end() )
357 InitDrillMatrix( "plated", std::make_pair( F_Cu, B_Cu ) );
358 // there is no circular plated dril hole present.
359
360 for( const auto& [layer_pair, vec] : drill_layers )
361 {
362 InitDrillMatrix( "plated", layer_pair );
363 }
364}
365
366
368{
369 MATRIX_LAYER matrix( m_row++, "COMP_+_TOP" );
372
373 if( aCompSide == F_Cu )
374 {
375 m_matrixLayers.push_back( matrix );
376 m_plugin->GetLayerNameList().emplace_back(
377 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
378 }
379
380 if( aCompSide == B_Cu && m_hasBotComp )
381 {
382 matrix.m_layerName = ODB::GenLegalEntityName( "COMP_+_BOT" );
383 m_matrixLayers.push_back( matrix );
384 m_plugin->GetLayerNameList().emplace_back(
385 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
386 }
387}
388
390{
391 auto& auxilliary_layers = m_plugin->GetAuxilliaryLayerItemsMap();
392
393 for( BOARD_ITEM* item : m_board->Tracks() )
394 {
395 if( item->Type() == PCB_VIA_T )
396 {
397 PCB_VIA* via = static_cast<PCB_VIA*>( item );
398
399 if( via->Padstack().IsFilled().value_or( false ) )
400 {
401 auxilliary_layers[std::make_tuple( ODB_AUX_LAYER_TYPE::FILLING, via->TopLayer(),
402 via->BottomLayer() )]
403 .push_back( via );
404 }
405
406 if( via->Padstack().IsCapped().value_or( false ) )
407 {
408 auxilliary_layers[std::make_tuple( ODB_AUX_LAYER_TYPE::CAPPING, via->TopLayer(),
409 via->BottomLayer() )]
410 .push_back( via );
411 }
412
413 for( PCB_LAYER_ID layer : { via->TopLayer(), via->BottomLayer() } )
414 {
415 if( via->Padstack().IsPlugged( layer ).value_or( false ) )
416 {
417 auxilliary_layers[std::make_tuple( ODB_AUX_LAYER_TYPE::PLUGGING, layer,
419 .push_back( via );
420 }
421
422 if( via->Padstack().IsCovered( layer ).value_or( false ) )
423 {
424 auxilliary_layers[std::make_tuple( ODB_AUX_LAYER_TYPE::COVERING, layer,
426 .push_back( via );
427 }
428
429 if( via->Padstack().IsTented( layer ).value_or( false ) )
430 {
431 auxilliary_layers[std::make_tuple( ODB_AUX_LAYER_TYPE::TENTING, layer,
433 .push_back( via );
434 }
435 }
436 }
437 }
438
439 auto InitAuxMatrix =
440 [&]( std::tuple<ODB_AUX_LAYER_TYPE, PCB_LAYER_ID, PCB_LAYER_ID> aLayerPair )
441 {
442 wxString featureName = "";
443 switch( std::get<0>( aLayerPair ) )
444 {
445 case ODB_AUX_LAYER_TYPE::TENTING: featureName = "tenting"; break;
446 case ODB_AUX_LAYER_TYPE::COVERING: featureName = "covering"; break;
447 case ODB_AUX_LAYER_TYPE::PLUGGING: featureName = "plugging"; break;
448 case ODB_AUX_LAYER_TYPE::FILLING: featureName = "filling"; break;
449 case ODB_AUX_LAYER_TYPE::CAPPING: featureName = "capping"; break;
450 default: return;
451 }
452
453 wxString dLayerName;
454
455 if( std::get<2>( aLayerPair ) != PCB_LAYER_ID::UNDEFINED_LAYER )
456 {
457 dLayerName = wxString::Format( "%s_%s-%s", featureName,
458 m_board->GetLayerName( std::get<1>( aLayerPair ) ),
459 m_board->GetLayerName( std::get<2>( aLayerPair ) ) );
460 }
461 else
462 {
463 if( m_board->IsFrontLayer( std::get<1>( aLayerPair ) ) )
464 dLayerName = wxString::Format( "%s_front", featureName );
465 else if( m_board->IsBackLayer( std::get<1>( aLayerPair ) ) )
466 dLayerName = wxString::Format( "%s_back", featureName );
467 else
468 return;
469 }
470 MATRIX_LAYER matrix( m_row++, dLayerName );
471
472 matrix.m_type = ODB_TYPE::DOCUMENT;
475
476 if( std::get<2>( aLayerPair ) != PCB_LAYER_ID::UNDEFINED_LAYER )
477 {
478 matrix.m_span.emplace( std::make_pair(
479 ODB::GenLegalEntityName( m_board->GetLayerName( std::get<1>( aLayerPair ) ) ),
481 m_board->GetLayerName( std::get<2>( aLayerPair ) ) ) ) );
482 }
483
484 m_matrixLayers.push_back( matrix );
485
486 if( std::get<2>( aLayerPair ) != PCB_LAYER_ID::UNDEFINED_LAYER )
487 {
488 m_plugin->GetLayerNameList().emplace_back(
489 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
490 }
491 else
492 {
493 m_plugin->GetLayerNameList().emplace_back(
494 std::make_pair( std::get<1>( aLayerPair ), matrix.m_layerName ) );
495 }
496 };
497
498 for( const auto& [layer_pair, vec] : auxilliary_layers )
499 {
500 InitAuxMatrix( layer_pair );
501 }
502}
503
504
506{
507 // Track occurrences of each layer name to detect and handle duplicates
508 std::map<wxString, std::vector<size_t>> name_to_indices;
509
510 // First pass: collect all layer names and their indices
511 for( size_t i = 0; i < m_matrixLayers.size(); ++i )
512 {
513 const wxString& layerName = m_matrixLayers[i].m_layerName;
514 name_to_indices[layerName].push_back( i );
515 }
516
517 // Second pass: for any layer names that appear more than once, add suffixes
518 for( auto& [layerName, indices] : name_to_indices )
519 {
520 if( indices.size() > 1 )
521 {
522 // Multiple layers have the same name, add suffixes to make them unique
523 for( size_t count = 0; count < indices.size(); ++count )
524 {
525 size_t idx = indices[count];
526 wxString newLayerName = wxString::Format( "%s_%zu", m_matrixLayers[idx].m_layerName, count + 1 );
527
528 // Ensure the new name doesn't exceed the 64-character limit
529 if( newLayerName.length() > 64 )
530 {
531 // Truncate the base name if necessary to fit the suffix
532 wxString baseName = m_matrixLayers[idx].m_layerName;
533 size_t suffixLen = wxString::Format( "_%zu", count + 1 ).length();
534
535 if( suffixLen < baseName.length() )
536 {
537 baseName.Truncate( 64 - suffixLen );
538 newLayerName = wxString::Format( "%s_%zu", baseName, count + 1 );
539 }
540 }
541
542 m_matrixLayers[idx].m_layerName = std::move( newLayerName );
543 }
544 }
545 }
546}
547
548
550{
551 auto fileproxy = writer.CreateFileProxy( "matrix" );
552
553 ODB_TEXT_WRITER twriter( fileproxy.GetStream() );
554
555 for( const auto& [step_name, column] : m_matrixSteps )
556 {
557 const auto array_proxy = twriter.MakeArrayProxy( "STEP" );
558 twriter.WriteEquationLine( "COL", column );
559 twriter.WriteEquationLine( "NAME", step_name );
560 }
561
562 for( const MATRIX_LAYER& layer : m_matrixLayers )
563 {
564 const auto array_proxy = twriter.MakeArrayProxy( "LAYER" );
565 twriter.WriteEquationLine( "ROW", layer.m_rowNumber );
566 twriter.write_line_enum( "CONTEXT", layer.m_context );
567 twriter.write_line_enum( "TYPE", layer.m_type );
568
569 if( layer.m_addType.has_value() )
570 {
571 twriter.write_line_enum( "ADD_TYPE", layer.m_addType.value() );
572 }
573
574 twriter.WriteEquationLine( "NAME", layer.m_layerName.Upper() );
575 twriter.WriteEquationLine( "OLD_NAME", wxEmptyString );
576 twriter.write_line_enum( "POLARITY", layer.m_polarity );
577
578 if( layer.m_diType.has_value() )
579 {
580 twriter.write_line_enum( "DIELECTRIC_TYPE", layer.m_diType.value() );
581 // twriter.WriteEquationLine( "DIELECTRIC_NAME", wxEmptyString );
582
583 // Can be used with DIELECTRIC_TYPE=CORE
584 // twriter.WriteEquationLine( "CU_TOP", wxEmptyString );
585 // twriter.WriteEquationLine( "CU_BOTTOM", wxEmptyString );
586 }
587
588 // Only applies to: soldermask, silkscreen, solderpaste and specifies the relevant cu layer
589 // twriter.WriteEquationLine( "REF", wxEmptyString );
590
591 if( layer.m_span.has_value() )
592 {
593 twriter.WriteEquationLine( "START_NAME", layer.m_span->first.Upper() );
594 twriter.WriteEquationLine( "END_NAME", layer.m_span->second.Upper() );
595 }
596
597 twriter.WriteEquationLine( "COLOR", "0" );
598 }
599}
600
601
603 std::map<int, std::vector<BOARD_ITEM*>>& aMap,
604 const PCB_LAYER_ID& aLayerID, const wxString& aLayerName ) :
605 ODB_ENTITY_BASE( aBoard, aPlugin ), m_layerItems( aMap ), m_layerID( aLayerID ),
606 m_matrixLayerName( aLayerName )
607{
608 m_featuresMgr = std::make_unique<FEATURES_MANAGER>( aBoard, aPlugin, aLayerName );
609}
610
611
613{
614 if( m_matrixLayerName.Contains( "drill" ) )
615 {
618 return;
619 }
620
621 if( m_matrixLayerName.Contains( "filling" ) || m_matrixLayerName.Contains( "capping" )
622 || m_matrixLayerName.Contains( "covering" ) || m_matrixLayerName.Contains( "plugging" )
623 || m_matrixLayerName.Contains( "tenting" ) )
624 {
627 return;
628 }
629
631 {
633 }
634}
635
637{
638 if( m_layerItems.empty() )
639 return;
640
641 const NETINFO_LIST& nets = m_board->GetNetInfo();
642
643 for( const NETINFO_ITEM* net : nets )
644 {
645 std::vector<BOARD_ITEM*>& vec = m_layerItems[net->GetNetCode()];
646
647 std::stable_sort( vec.begin(), vec.end(),
648 []( BOARD_ITEM* a, BOARD_ITEM* b )
649 {
650 if( a->GetParentFootprint() == b->GetParentFootprint() )
651 return a->Type() < b->Type();
652
653 return a->GetParentFootprint() < b->GetParentFootprint();
654 } );
655
656 if( vec.empty() )
657 continue;
658
659 m_featuresMgr->InitFeatureList( m_layerID, vec );
660 }
661}
662
663
665 const EDA_DATA::PACKAGE& aPkg )
666{
667 if( m_matrixLayerName == "COMP_+_BOT" )
668 {
669 if( !m_compBot.has_value() )
670 {
671 m_compBot.emplace();
672 }
673 return m_compBot.value().AddComponent( aFp, aPkg );
674 }
675 else
676 {
677 if( !m_compTop.has_value() )
678 {
679 m_compTop.emplace();
680 }
681
682 return m_compTop.value().AddComponent( aFp, aPkg );
683 }
684}
685
686
688{
689 std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& drill_layers =
690 m_plugin->GetDrillLayerItemsMap();
691
692 std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& slot_holes =
693 m_plugin->GetSlotHolesMap();
694
695 if( !m_layerItems.empty() )
696 {
697 m_layerItems.clear();
698 }
699
701
702 bool is_npth_layer = false;
703 wxString plated_name = "plated";
704
705 if( m_matrixLayerName.Contains( "non-plated" ) )
706 {
707 is_npth_layer = true;
708 plated_name = "non-plated";
709 }
710
711
712 for( const auto& [layer_pair, vec] : slot_holes )
713 {
714 wxString dLayerName = wxString::Format( "drill_%s_%s-%s", plated_name,
715 m_board->GetLayerName( layer_pair.first ),
716 m_board->GetLayerName( layer_pair.second ) );
717
718 if( ODB::GenLegalEntityName( dLayerName ) == m_matrixLayerName )
719 {
720 for( BOARD_ITEM* item : vec )
721 {
722 if( item->Type() == PCB_PAD_T )
723 {
724 PAD* pad = static_cast<PAD*>( item );
725
726 if( ( is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH )
727 || ( !is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
728 {
729 continue;
730 }
731
732 m_tools.value().AddDrillTools(
733 pad->GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NON_PLATED",
735 std::min( pad->GetDrillSizeX(), pad->GetDrillSizeY() ) ) );
736
737 // for drill features
738 m_layerItems[pad->GetNetCode()].push_back( item );
739 }
740 }
741
742 break;
743 }
744 }
745
746 for( const auto& [layer_pair, vec] : drill_layers )
747 {
748 wxString dLayerName = wxString::Format( "drill_%s_%s-%s", plated_name,
749 m_board->GetLayerName( layer_pair.first ),
750 m_board->GetLayerName( layer_pair.second ) );
751
752 if( ODB::GenLegalEntityName( dLayerName ) == m_matrixLayerName )
753 {
754 for( BOARD_ITEM* item : vec )
755 {
756 if( item->Type() == PCB_VIA_T && !is_npth_layer )
757 {
758 PCB_VIA* via = static_cast<PCB_VIA*>( item );
759
760 m_tools.value().AddDrillTools( "VIA",
761 ODB::SymDouble2String( via->GetDrillValue() ) );
762
763 // for drill features
764 m_layerItems[via->GetNetCode()].push_back( item );
765 }
766 else if( item->Type() == PCB_PAD_T )
767 {
768 PAD* pad = static_cast<PAD*>( item );
769
770 if( ( is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH )
771 || ( !is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
772 {
773 continue;
774 }
775
776 m_tools.value().AddDrillTools(
777 pad->GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NON_PLATED",
778 ODB::SymDouble2String( pad->GetDrillSizeX() ) );
779
780 // for drill features
781 m_layerItems[pad->GetNetCode()].push_back( item );
782 }
783 }
784
785 break;
786 }
787 }
788}
789
791{
792 auto& auxilliary_layers = m_plugin->GetAuxilliaryLayerItemsMap();
793
794 if( !m_layerItems.empty() )
795 {
796 m_layerItems.clear();
797 }
798
799 for( const auto& [layer_pair, vec] : auxilliary_layers )
800 {
801 wxString featureName = "";
802 switch( std::get<0>( layer_pair ) )
803 {
804 case ODB_AUX_LAYER_TYPE::TENTING: featureName = "tenting"; break;
805 case ODB_AUX_LAYER_TYPE::COVERING: featureName = "covering"; break;
806 case ODB_AUX_LAYER_TYPE::PLUGGING: featureName = "plugging"; break;
807 case ODB_AUX_LAYER_TYPE::FILLING: featureName = "filling"; break;
808 case ODB_AUX_LAYER_TYPE::CAPPING: featureName = "capping"; break;
809 default: return;
810 }
811
812 wxString dLayerName;
813 bool drill_value = false;
814
815 if( std::get<2>( layer_pair ) != PCB_LAYER_ID::UNDEFINED_LAYER )
816 {
817 drill_value = true;
818 dLayerName = wxString::Format( "%s_%s-%s", featureName,
819 m_board->GetLayerName( std::get<1>( layer_pair ) ),
820 m_board->GetLayerName( std::get<2>( layer_pair ) ) );
821 }
822 else
823 {
824 if( m_board->IsFrontLayer( std::get<1>( layer_pair ) ) )
825 dLayerName = wxString::Format( "%s_front", featureName );
826 else if( m_board->IsBackLayer( std::get<1>( layer_pair ) ) )
827 dLayerName = wxString::Format( "%s_back", featureName );
828 else
829 return;
830 }
831
832 if( ODB::GenLegalEntityName( dLayerName ) == m_matrixLayerName )
833 {
834 for( BOARD_ITEM* item : vec )
835 {
836 if( item->Type() == PCB_VIA_T )
837 {
838 PCB_VIA* via = static_cast<PCB_VIA*>( item );
839
840 m_layerItems[via->GetNetCode()].push_back( item );
841 }
842 }
843
844 break;
845 }
846 }
847}
848
850{
852
853 InitEdaData();
854
855 // Init Layer Entity Data
856 for( const auto& [layerName, layer_entity_ptr] : m_layerEntityMap )
857 {
858 layer_entity_ptr->InitEntityData();
859 }
860}
861
862
864{
865 GenAttrList( writer );
866
867 GenFeatures( writer );
868
869 if( m_compTop.has_value() || m_compBot.has_value() )
870 {
871 GenComponents( writer );
872 }
873
874 if( m_tools.has_value() )
875 {
876 GenTools( writer );
877 }
878}
879
880
882{
883 auto fileproxy = writer.CreateFileProxy( "components" );
884
885 if( m_compTop.has_value() )
886 {
887 m_compTop->Write( fileproxy.GetStream() );
888 }
889 else if( m_compBot.has_value() )
890 {
891 m_compBot->Write( fileproxy.GetStream() );
892 }
893}
894
895
897{
898 auto fileproxy = writer.CreateFileProxy( "features" );
899
900 m_featuresMgr->GenerateFeatureFile( fileproxy.GetStream() );
901}
902
903
905{
906 auto fileproxy = writer.CreateFileProxy( "attrlist" );
907}
908
909
911{
912 auto fileproxy = writer.CreateFileProxy( "tools" );
913
914 m_tools.value().GenerateFile( fileproxy.GetStream() );
915}
916
917
919{
920 //InitPackage
921 for( const FOOTPRINT* fp : m_board->Footprints() )
922 {
923 m_edaData.AddPackage( fp );
924 }
925
926 // for NET
927 const NETINFO_LIST& nets = m_board->GetNetInfo();
928
929 for( const NETINFO_ITEM* net : nets )
930 {
931 m_edaData.AddNET( net );
932 }
933
934 // for CMP
935 size_t j = 0;
936
937 for( const FOOTPRINT* fp : m_board->Footprints() )
938 {
939 wxString compName = ODB::GenLegalEntityName( "COMP_+_TOP" );
940 if( fp->IsFlipped() )
941 compName = ODB::GenLegalEntityName( "COMP_+_BOT" );
942
943 auto iter = m_layerEntityMap.find( compName );
944
945 if( iter == m_layerEntityMap.end() )
946 {
947 wxLogError( _( "Failed to add component data" ) );
948 return;
949 }
950
951 // ODBPP only need unique PACKAGE in PKG record in eda/data file.
952 // the PKG index can repeat to be ref in CMP record in component file.
953 std::shared_ptr<FOOTPRINT> fp_pkg = m_edaData.GetEdaFootprints().at( j );
954 ++j;
955
956 const EDA_DATA::PACKAGE& eda_pkg =
957 m_edaData.GetPackage( hash_fp_item( fp_pkg.get(), HASH_POS | REL_COORD ) );
958
959 if( fp->Pads().empty() )
960 continue;
961
962 ODB_COMPONENT& comp = iter->second->InitComponentData( fp, eda_pkg );
963
964 for( int i = 0; i < fp->Pads().size(); ++i )
965 {
966 PAD* pad = fp->Pads()[i];
967 auto& eda_net = m_edaData.GetNet( pad->GetNetCode() );
968
969 auto& subnet = eda_net.AddSubnet<EDA_DATA::SUB_NET_TOEPRINT>(
970 &m_edaData,
973 comp.m_index, comp.m_toeprints.size() );
974
975 m_plugin->GetPadSubnetMap().emplace( pad, &subnet );
976
977 const std::shared_ptr<EDA_DATA::PIN> pin = eda_pkg.GetEdaPkgPin( i );
978 const EDA_DATA::PIN& pin_ref = *pin;
979 auto& toep = comp.m_toeprints.emplace_back( pin_ref );
980
981 toep.m_net_num = eda_net.m_index;
982 toep.m_subnet_num = subnet.m_index;
983
984 toep.m_center = ODB::AddXY( pad->GetPosition() );
985
986 toep.m_rot = ODB::Double2String(
987 ( ANGLE_360 - pad->GetOrientation() ).Normalize().AsDegrees() );
988
989 if( pad->IsFlipped() )
990 toep.m_mirror = wxT( "M" );
991 else
992 toep.m_mirror = wxT( "N" );
993 }
994 }
995
996 for( PCB_TRACK* track : m_board->Tracks() )
997 {
998 auto& eda_net = m_edaData.GetNet( track->GetNetCode() );
999 EDA_DATA::SUB_NET* subnet = nullptr;
1000
1001 if( track->Type() == PCB_VIA_T )
1002 subnet = &( eda_net.AddSubnet<EDA_DATA::SUB_NET_VIA>( &m_edaData ) );
1003 else
1004 subnet = &( eda_net.AddSubnet<EDA_DATA::SUB_NET_TRACE>( &m_edaData ) );
1005
1006 m_plugin->GetViaTraceSubnetMap().emplace( track, subnet );
1007 }
1008
1009 for( ZONE* zone : m_board->Zones() )
1010 {
1011 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
1012 {
1013 auto& eda_net = m_edaData.GetNet( zone->GetNetCode() );
1014 auto& subnet = eda_net.AddSubnet<EDA_DATA::SUB_NET_PLANE>( &m_edaData,
1017 0 );
1018 m_plugin->GetPlaneSubnetMap().emplace( std::piecewise_construct,
1019 std::forward_as_tuple( layer, zone ),
1020 std::forward_as_tuple( &subnet ) );
1021 }
1022 }
1023}
1024
1025
1027{
1028 wxString step_root = writer.GetCurrentPath();
1029
1030 writer.CreateEntityDirectory( step_root, "layers" );
1031 GenerateLayerFiles( writer );
1032
1033 writer.CreateEntityDirectory( step_root, "eda" );
1034 GenerateEdaFiles( writer );
1035
1036 writer.CreateEntityDirectory( step_root, "netlists/cadnet" );
1037 GenerateNetlistsFiles( writer );
1038
1039 writer.SetCurrentPath( step_root );
1040 GenerateProfileFile( writer );
1041
1042 GenerateStepHeaderFile( writer );
1043
1044 //TODO: system attributes
1045 // GenerateAttrListFile( writer );
1046}
1047
1048
1050{
1051 auto fileproxy = writer.CreateFileProxy( "profile" );
1052
1053 m_profile = std::make_unique<FEATURES_MANAGER>( m_board, m_plugin, wxEmptyString );
1054
1055 SHAPE_POLY_SET board_outline;
1056
1057 if( !m_board->GetBoardPolygonOutlines( board_outline ) )
1058 {
1059 wxLogError( "Failed to get board outline" );
1060 }
1061
1062 if( !m_profile->AddContour( board_outline, 0 ) )
1063 {
1064 wxLogError( "Failed to add polygon to profile" );
1065 }
1066
1067 m_profile->GenerateProfileFeatures( fileproxy.GetStream() );
1068}
1069
1070
1072{
1073 auto fileproxy = writer.CreateFileProxy( "stephdr" );
1074
1075 m_stephdr = {
1077 { "X_DATUM", "0" },
1078 { "Y_DATUM", "0" },
1079 { "X_ORIGIN", "0" },
1080 { "Y_ORIGIN", "0" },
1081 { "TOP_ACTIVE", "0" },
1082 { "BOTTOM_ACTIVE", "0" },
1083 { "RIGHT_ACTIVE", "0" },
1084 { "LEFT_ACTIVE", "0" },
1085 { "AFFECTING_BOM", "" },
1086 { "AFFECTING_BOM_CHANGED", "0" },
1087 };
1088
1089 ODB_TEXT_WRITER twriter( fileproxy.GetStream() );
1090
1091 for( const auto& [key, value] : m_stephdr )
1092 {
1093 twriter.WriteEquationLine( key, value );
1094 }
1095}
1096
1097
1099{
1100 wxString layers_root = writer.GetCurrentPath();
1101
1102 for( auto& [layerName, layerEntity] : m_layerEntityMap )
1103 {
1104 writer.CreateEntityDirectory( layers_root, layerName );
1105
1106 layerEntity->GenerateFiles( writer );
1107 }
1108}
1109
1110
1112{
1113 auto fileproxy = writer.CreateFileProxy( "data" );
1114
1115 m_edaData.Write( fileproxy.GetStream() );
1116}
1117
1118
1120{
1121 auto fileproxy = writer.CreateFileProxy( "netlist" );
1122
1123 m_netlist.Write( fileproxy.GetStream() );
1124}
1125
1126
1128{
1129 try
1130 {
1131 writer.CreateEntityDirectory( writer.GetRootPath(), "steps" );
1133 return true;
1134 }
1135 catch( const std::exception& e )
1136 {
1137 std::cerr << e.what() << std::endl;
1138 return false;
1139 }
1140}
1141
1142
1144{
1145 LSET layers = m_board->GetEnabledLayers();
1146 const NETINFO_LIST& nets = m_board->GetNetInfo();
1147
1148 // To avoid the overhead of repeatedly cycling through the layers and nets,
1149 // we pre-sort the board items into a map of layer -> net -> items
1150 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>>& elements = m_plugin->GetLayerElementsMap();
1151
1152 std::for_each( m_board->Tracks().begin(), m_board->Tracks().end(),
1153 [&layers, &elements]( PCB_TRACK* aTrack )
1154 {
1155 if( aTrack->Type() == PCB_VIA_T )
1156 {
1157 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
1158
1159 for( PCB_LAYER_ID layer : layers )
1160 {
1161 if( via->FlashLayer( layer ) )
1162 elements[layer][via->GetNetCode()].push_back( via );
1163 }
1164 }
1165 else
1166 {
1167 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
1168 }
1169 } );
1170
1171 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
1172 [&elements]( ZONE* zone )
1173 {
1174 for( PCB_LAYER_ID layer : zone->GetLayerSet() )
1175 elements[layer][zone->GetNetCode()].push_back( zone );
1176 } );
1177
1178 for( BOARD_ITEM* item : m_board->Drawings() )
1179 {
1180 if( BOARD_CONNECTED_ITEM* conn_it = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
1181 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
1182 else
1183 elements[item->GetLayer()][0].push_back( item );
1184 }
1185
1186 for( FOOTPRINT* fp : m_board->Footprints() )
1187 {
1188 for( PCB_FIELD* field : fp->GetFields() )
1189 elements[field->GetLayer()][0].push_back( field );
1190
1191 for( BOARD_ITEM* item : fp->GraphicalItems() )
1192 elements[item->GetLayer()][0].push_back( item );
1193
1194 for( PAD* pad : fp->Pads() )
1195 {
1196 VECTOR2I margin;
1197
1198 for( PCB_LAYER_ID layer : pad->GetLayerSet() )
1199 {
1200 bool onCopperLayer = LSET::AllCuMask().test( layer );
1201 bool onSolderMaskLayer = LSET( { F_Mask, B_Mask } ).test( layer );
1202 bool onSolderPasteLayer = LSET( { F_Paste, B_Paste } ).test( layer );
1203
1204 if( onSolderMaskLayer )
1205 margin.x = margin.y = pad->GetSolderMaskExpansion( PADSTACK::ALL_LAYERS );
1206
1207 if( onSolderPasteLayer )
1208 margin = pad->GetSolderPasteMargin( PADSTACK::ALL_LAYERS );
1209
1210 VECTOR2I padPlotsSize = pad->GetSize( PADSTACK::ALL_LAYERS ) + margin * 2;
1211
1212 if( onCopperLayer && !pad->IsOnCopperLayer() )
1213 continue;
1214
1215 if( onCopperLayer && !pad->FlashLayer( layer ) )
1216 continue;
1217
1218 if( pad->GetShape( PADSTACK::ALL_LAYERS ) != PAD_SHAPE::CUSTOM
1219 && ( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 ) )
1220 {
1221 continue;
1222 }
1223
1224 elements[layer][pad->GetNetCode()].push_back( pad );
1225 }
1226 }
1227 }
1228
1229 for( const auto& [layerID, layerName] : m_plugin->GetLayerNameList() )
1230 {
1231 std::shared_ptr<ODB_LAYER_ENTITY> layer_entity_ptr = std::make_shared<ODB_LAYER_ENTITY>(
1232 m_board, m_plugin, elements[layerID], layerID, layerName );
1233
1234 m_layerEntityMap.emplace( layerName, layer_entity_ptr );
1235 }
1236}
@ BS_ITEM_TYPE_DIELECTRIC
wxString GetBuildVersion()
Get the full KiCad version string.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
Container for design settings for a BOARD object.
BOARD_STACKUP & GetStackupDescriptor()
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:79
Manage one layer needed to make a physical board.
wxString GetTypeName() const
int GetSublayersCount() const
wxString GetLayerName() const
PCB_LAYER_ID GetBrdLayerId() const
BOARD_STACKUP_ITEM_TYPE GetType() const
int GetDielectricLayerId() const
Manage layers needed to make a physical board.
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
int GetCount() const
bool SynchronizeWithBoard(BOARD_DESIGN_SETTINGS *aSettings)
Synchronize the BOARD_STACKUP_ITEM* list with the board.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
const std::shared_ptr< PIN > GetEdaPkgPin(size_t aPadIndex) const
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:591
Handle the data for a net.
Definition netinfo.h:54
Container for NETINFO_ITEM elements, which are the nets.
Definition netinfo.h:212
const size_t m_index
! CMP index number on board to be used in SNT(TOP), 0~n-1
std::list< TOEPRINT > m_toeprints
virtual std::string GetEntityName()=0
virtual bool CreateDirectoryTree(ODB_TREE_WRITER &writer)
BOARD * m_board
Definition odb_entity.h:59
PCB_IO_ODBPP * m_plugin
Definition odb_entity.h:61
ODB_ENTITY_BASE(BOARD *aBoard, PCB_IO_ODBPP *aPlugin)
Definition odb_entity.h:45
void GenFeatures(ODB_TREE_WRITER &writer)
PCB_LAYER_ID m_layerID
Definition odb_entity.h:209
void GenComponents(ODB_TREE_WRITER &writer)
wxString m_matrixLayerName
Definition odb_entity.h:210
void InitAuxilliaryData()
std::optional< COMPONENTS_MANAGER > m_compTop
Definition odb_entity.h:213
virtual void GenerateFiles(ODB_TREE_WRITER &writer) override
std::optional< COMPONENTS_MANAGER > m_compBot
Definition odb_entity.h:214
std::optional< ODB_DRILL_TOOLS > m_tools
Definition odb_entity.h:212
void GenTools(ODB_TREE_WRITER &writer)
std::map< int, std::vector< BOARD_ITEM * > > m_layerItems
Definition odb_entity.h:208
ODB_LAYER_ENTITY(BOARD *aBoard, PCB_IO_ODBPP *aPlugin, std::map< int, std::vector< BOARD_ITEM * > > &aMap, const PCB_LAYER_ID &aLayerID, const wxString &aLayerName)
ODB_COMPONENT & InitComponentData(const FOOTPRINT *aFp, const EDA_DATA::PACKAGE &aPkg)
virtual void InitEntityData() override
void GenAttrList(ODB_TREE_WRITER &writer)
std::unique_ptr< FEATURES_MANAGER > m_featuresMgr
Definition odb_entity.h:215
void AddStep(const wxString &aStepName)
unsigned int m_col
Definition odb_entity.h:114
std::vector< MATRIX_LAYER > m_matrixLayers
Definition odb_entity.h:112
void AddMatrixLayerField(MATRIX_LAYER &aMLayer, PCB_LAYER_ID aLayer)
virtual void GenerateFiles(ODB_TREE_WRITER &writer) override
std::map< wxString, unsigned int > m_matrixSteps
Definition odb_entity.h:111
unsigned int m_row
Definition odb_entity.h:113
void AddAuxilliaryMatrixLayer()
void EnsureUniqueLayerNames()
virtual void InitEntityData() override
void AddCOMPMatrixLayer(PCB_LAYER_ID aCompSide)
std::vector< std::pair< wxString, wxString > > m_info
Definition odb_entity.h:131
virtual void GenerateFiles(ODB_TREE_WRITER &writer) override
virtual std::string GetEntityName() override
Definition odb_entity.h:147
std::unordered_map< wxString, wxString > m_stephdr
Definition odb_entity.h:174
void GenerateProfileFile(ODB_TREE_WRITER &writer)
EDA_DATA m_edaData
Definition odb_entity.h:173
void GenerateStepHeaderFile(ODB_TREE_WRITER &writer)
void GenerateEdaFiles(ODB_TREE_WRITER &writer)
virtual void InitEntityData() override
void GenerateLayerFiles(ODB_TREE_WRITER &writer)
std::map< wxString, std::shared_ptr< ODB_LAYER_ENTITY > > m_layerEntityMap
Definition odb_entity.h:170
ODB_NET_LIST m_netlist
Definition odb_entity.h:175
std::unique_ptr< FEATURES_MANAGER > m_profile
Definition odb_entity.h:171
virtual bool CreateDirectoryTree(ODB_TREE_WRITER &writer) override
void GenerateNetlistsFiles(ODB_TREE_WRITER &writer)
virtual void GenerateFiles(ODB_TREE_WRITER &writer) override
void WriteEquationLine(const std::string &var, int value)
Definition odb_util.cpp:285
ARRAY_PROXY MakeArrayProxy(const std::string &aStr)
Definition odb_util.h:310
void write_line_enum(const std::string &var, const T &value)
Definition odb_util.h:284
const wxString GetRootPath() const
Definition odb_util.h:265
void CreateEntityDirectory(const wxString &aPareDir, const wxString &aSubDir=wxEmptyString)
Definition odb_util.cpp:206
ODB_FILE_WRITER CreateFileProxy(const wxString &aFileName)
Definition odb_util.h:252
void SetCurrentPath(const wxString &aDir)
Definition odb_util.h:261
const wxString GetCurrentPath() const
Definition odb_util.h:259
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:145
Definition pad.h:54
static std::string m_unitsStr
Represent a set of closed polygons.
Handle a list of polygons defining a copper zone.
Definition zone.h:74
#define _(s)
static constexpr EDA_ANGLE ANGLE_360
Definition eda_angle.h:417
size_t hash_fp_item(const EDA_ITEM *aItem, int aFlags)
Calculate hash of an EDA_ITEM.
Definition hash_eda.cpp:58
Hashing functions for EDA_ITEMs.
@ HASH_POS
Definition hash_eda.h:47
@ REL_COORD
Use coordinates relative to the parent object.
Definition hash_eda.h:50
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:677
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ User_16
Definition layer_ids.h:139
@ User_29
Definition layer_ids.h:152
@ User_40
Definition layer_ids.h:163
@ User_15
Definition layer_ids.h:138
@ User_8
Definition layer_ids.h:131
@ F_CrtYd
Definition layer_ids.h:116
@ User_11
Definition layer_ids.h:134
@ User_25
Definition layer_ids.h:148
@ User_34
Definition layer_ids.h:157
@ User_45
Definition layer_ids.h:168
@ B_Adhes
Definition layer_ids.h:103
@ User_36
Definition layer_ids.h:159
@ Edge_Cuts
Definition layer_ids.h:112
@ Dwgs_User
Definition layer_ids.h:107
@ F_Paste
Definition layer_ids.h:104
@ Cmts_User
Definition layer_ids.h:108
@ User_6
Definition layer_ids.h:129
@ User_7
Definition layer_ids.h:130
@ User_19
Definition layer_ids.h:142
@ User_23
Definition layer_ids.h:146
@ F_Adhes
Definition layer_ids.h:102
@ User_41
Definition layer_ids.h:164
@ B_Mask
Definition layer_ids.h:98
@ B_Cu
Definition layer_ids.h:65
@ User_14
Definition layer_ids.h:137
@ User_39
Definition layer_ids.h:162
@ User_5
Definition layer_ids.h:128
@ User_20
Definition layer_ids.h:143
@ Eco1_User
Definition layer_ids.h:109
@ F_Mask
Definition layer_ids.h:97
@ User_42
Definition layer_ids.h:165
@ User_43
Definition layer_ids.h:166
@ B_Paste
Definition layer_ids.h:105
@ User_10
Definition layer_ids.h:133
@ User_9
Definition layer_ids.h:132
@ User_27
Definition layer_ids.h:150
@ User_28
Definition layer_ids.h:151
@ 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
@ UNDEFINED_LAYER
Definition layer_ids.h:61
@ Eco2_User
Definition layer_ids.h:110
@ User_35
Definition layer_ids.h:158
@ User_31
Definition layer_ids.h:154
@ User_3
Definition layer_ids.h:126
@ User_1
Definition layer_ids.h:124
@ User_12
Definition layer_ids.h:135
@ B_SilkS
Definition layer_ids.h:101
@ User_30
Definition layer_ids.h:153
@ User_37
Definition layer_ids.h:160
@ User_22
Definition layer_ids.h:145
@ User_38
Definition layer_ids.h:161
@ User_4
Definition layer_ids.h:127
@ User_21
Definition layer_ids.h:144
@ User_24
Definition layer_ids.h:147
@ User_13
Definition layer_ids.h:136
@ User_2
Definition layer_ids.h:125
@ User_17
Definition layer_ids.h:140
@ User_33
Definition layer_ids.h:156
@ User_26
Definition layer_ids.h:149
@ User_32
Definition layer_ids.h:155
@ User_18
Definition layer_ids.h:141
@ User_44
Definition layer_ids.h:167
@ F_Cu
Definition layer_ids.h:64
@ B_Fab
Definition layer_ids.h:118
bool IsValidLayer(int aLayerId)
Test whether a given integer is a valid layer index, i.e.
Definition layer_ids.h:655
std::pair< wxString, wxString > AddXY(const VECTOR2I &aVec)
Definition odb_util.cpp:167
wxString GenLegalEntityName(const wxString &aStr)
Definition odb_util.cpp:82
wxString Double2String(double aVal)
Definition odb_util.cpp:127
wxString SymDouble2String(double aVal)
Definition odb_util.cpp:155
#define ODB_JOB_NAME
Definition odb_defines.h:27
#define ODB_UNITS
Definition odb_defines.h:28
@ UNDEFINED
Definition odb_util.h:35
@ COMPONENT
Definition odb_util.h:47
@ SOLDER_PASTE
Definition odb_util.h:42
@ SILK_SCREEN
Definition odb_util.h:43
@ DOCUMENT
Definition odb_util.h:46
@ SOLDER_MASK
Definition odb_util.h:41
@ DIELECTRIC
Definition odb_util.h:39
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:87
@ PTH
Plated through hole pad.
Definition padstack.h:82
see class PGM_BASE
#define KEY_CORE
std::optional< ODB_DIELECTRIC_TYPE > m_diType
Definition odb_entity.h:84
std::optional< std::pair< wxString, wxString > > m_span
Definition odb_entity.h:82
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:97
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:87
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695