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>
23#include <optional>
25#include <build_version.h>
26#include <callback_gal.h>
30#include <font/font.h>
31#include <footprint.h>
32#include <hash_eda.h>
33#include <pad.h>
34#include <padstack.h>
35#include <pcb_dimension.h>
36#include <pcb_shape.h>
37#include <pcb_text.h>
38#include <pcb_textbox.h>
39#include <pcb_track.h>
40#include <pcbnew_settings.h>
42#include <pgm_base.h>
43#include <progress_reporter.h>
45#include <wx_fstream_progress.h>
46
51
52#include <wx/log.h>
53#include <wx/numformatter.h>
54#include <wx/mstream.h>
55
56#include "odb_attribute.h"
57#include "odb_entity.h"
58#include "odb_defines.h"
59#include "odb_feature.h"
60#include "odb_util.h"
61#include "pcb_io_odbpp.h"
62
63
65{
66 try
67 {
69 return true;
70 }
71 catch( const std::exception& e )
72 {
73 std::cerr << e.what() << std::endl;
74 return false;
75 }
76}
77
78
80{
81 m_info = { { wxS( ODB_JOB_NAME ), wxS( "job" ) },
83 { wxS( "ODB_VERSION_MAJOR" ), wxS( "8" ) },
84 { wxS( "ODB_VERSION_MINOR" ), wxS( "1" ) },
85 { wxS( "ODB_SOURCE" ), wxS( "KiCad EDA" ) },
86 { wxS( "CREATION_DATE" ), wxDateTime::Now().Format( "%Y%m%d.%H%M%S" ) },
87 { wxS( "SAVE_DATE" ), wxDateTime::Now().Format( "%Y%m%d.%H%M%S" ) },
88 { wxS( "SAVE_APP" ), wxString::Format( wxS( "KiCad EDA %s" ), GetBuildVersion() ) } };
89}
90
91
93{
94 auto fileproxy = writer.CreateFileProxy( "info" );
95
96 ODB_TEXT_WRITER twriter( fileproxy.GetStream() );
97
98 for( auto& info : m_info )
99 {
100 twriter.WriteEquationLine( info.first, info.second );
101 }
102}
103
104
105void ODB_MATRIX_ENTITY::AddStep( const wxString& aStepName )
106{
107 m_matrixSteps.emplace( aStepName.Upper(), m_col++ );
108}
109
110
112{
113 AddStep( "PCB" );
114
116}
117
118
120{
121 BOARD_DESIGN_SETTINGS& dsnSettings = m_board->GetDesignSettings();
122 BOARD_STACKUP& stackup = dsnSettings.GetStackupDescriptor();
123 stackup.SynchronizeWithBoard( &dsnSettings );
124
125 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.GetList();
126 std::set<PCB_LAYER_ID> added_layers;
127
129
130 for( int i = 0; i < stackup.GetCount(); i++ )
131 {
132 BOARD_STACKUP_ITEM* stackup_item = layers.at( i );
133
134 for( int sublayer_id = 0; sublayer_id < stackup_item->GetSublayersCount(); sublayer_id++ )
135 {
136 wxString ly_name = stackup_item->GetLayerName();
137
138 if( ly_name.IsEmpty() )
139 {
140 if( IsValidLayer( stackup_item->GetBrdLayerId() ) )
141 ly_name = m_board->GetLayerName( stackup_item->GetBrdLayerId() );
142
143 if( ly_name.IsEmpty() && stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
144 ly_name = wxString::Format( "DIELECTRIC_%d",
145 stackup_item->GetDielectricLayerId() );
146 }
147
148 MATRIX_LAYER matrix( m_row++, ly_name );
149
150 if( stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
151 {
152 if( stackup_item->GetTypeName() == KEY_CORE )
153 matrix.m_diType.emplace( ODB_DIELECTRIC_TYPE::CORE );
154 else
155 matrix.m_diType.emplace( ODB_DIELECTRIC_TYPE::PREPREG );
156
160 m_matrixLayers.push_back( matrix );
161 m_plugin->GetLayerNameList().emplace_back(
162 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
163
164 continue;
165 }
166 else
167 {
168 added_layers.insert( stackup_item->GetBrdLayerId() );
169 AddMatrixLayerField( matrix, stackup_item->GetBrdLayerId() );
170 }
171 }
172 }
173
174 for( PCB_LAYER_ID layer : m_board->GetEnabledLayers().Seq() )
175 {
176 if( added_layers.find( layer ) != added_layers.end() )
177 continue;
178
179 MATRIX_LAYER matrix( m_row++, m_board->GetLayerName( layer ) );
180 added_layers.insert( layer );
181 AddMatrixLayerField( matrix, layer );
182 }
183
185
187
189
191}
192
193
195{
198 switch( aLayer )
199 {
200 case F_Paste:
201 case B_Paste: aMLayer.m_type = ODB_TYPE::SOLDER_PASTE; break;
202 case F_SilkS:
203 case B_SilkS: aMLayer.m_type = ODB_TYPE::SILK_SCREEN; break;
204 case F_Mask:
205 case B_Mask: aMLayer.m_type = ODB_TYPE::SOLDER_MASK; break;
206 case B_CrtYd:
207 case F_CrtYd:
208 case Edge_Cuts:
209 case B_Fab:
210 case F_Fab:
211 case F_Adhes:
212 case B_Adhes:
213 case Dwgs_User:
214 case Cmts_User:
215 case Eco1_User:
216 case Eco2_User:
217 case Margin:
218 case User_1:
219 case User_2:
220 case User_3:
221 case User_4:
222 case User_5:
223 case User_6:
224 case User_7:
225 case User_8:
226 case User_9:
227 case User_10:
228 case User_11:
229 case User_12:
230 case User_13:
231 case User_14:
232 case User_15:
233 case User_16:
234 case User_17:
235 case User_18:
236 case User_19:
237 case User_20:
238 case User_21:
239 case User_22:
240 case User_23:
241 case User_24:
242 case User_25:
243 case User_26:
244 case User_27:
245 case User_28:
246 case User_29:
247 case User_30:
248 case User_31:
249 case User_32:
250 case User_33:
251 case User_34:
252 case User_35:
253 case User_36:
254 case User_37:
255 case User_38:
256 case User_39:
257 case User_40:
258 case User_41:
259 case User_42:
260 case User_43:
261 case User_44:
262 case User_45:
264 aMLayer.m_type = ODB_TYPE::DOCUMENT;
265 break;
266
267 default:
268 if( IsCopperLayer( aLayer ) )
269 {
270 aMLayer.m_type = ODB_TYPE::SIGNAL;
271 }
272 else
273 {
274 // Do not handle other layers :
275 aMLayer.m_type = ODB_TYPE::UNDEFINED;
276 m_row--;
277 }
278
279 break;
280 }
281
282 if( aMLayer.m_type != ODB_TYPE::UNDEFINED )
283 {
284 m_matrixLayers.push_back( aMLayer );
285 m_plugin->GetLayerNameList().emplace_back( std::make_pair( aLayer, aMLayer.m_layerName ) );
286 }
287}
288
289
291{
292 std::map<ODB_DRILL_SPAN, std::vector<BOARD_ITEM*>>& drill_layers =
293 m_plugin->GetDrillLayerItemsMap();
294
295 std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& slot_holes =
296 m_plugin->GetSlotHolesMap();
297
298 drill_layers.clear();
299
300 std::map<ODB_DRILL_SPAN, wxString>& span_names = m_plugin->GetDrillSpanNameMap();
301 span_names.clear();
302
303 bool has_pth_layer = false;
304 bool has_npth_layer = false;
305
306 for( BOARD_ITEM* item : m_board->Tracks() )
307 {
308 if( item->Type() == PCB_VIA_T )
309 {
310 PCB_VIA* via = static_cast<PCB_VIA*>( item );
311 has_pth_layer = true;
312
313 ODB_DRILL_SPAN platedSpan( via->TopLayer(), via->BottomLayer(), false, false );
314 drill_layers[platedSpan].push_back( via );
315
316 const PADSTACK::DRILL_PROPS& secondary = via->Padstack().SecondaryDrill();
317
318 if( secondary.start != UNDEFINED_LAYER && secondary.end != UNDEFINED_LAYER
319 && ( secondary.size.x > 0 || secondary.size.y > 0 ) )
320 {
321 ODB_DRILL_SPAN backSpan( secondary.start, secondary.end, true, true );
322 drill_layers[backSpan].push_back( via );
323 }
324 }
325 }
326
327 for( FOOTPRINT* fp : m_board->Footprints() )
328 {
329 if( fp->IsFlipped() )
330 {
331 m_hasBotComp = true;
332 }
333
334 for( PAD* pad : fp->Pads() )
335 {
336 if( pad->GetAttribute() == PAD_ATTRIB::PTH )
337 has_pth_layer = true;
338 if( pad->GetAttribute() == PAD_ATTRIB::NPTH )
339 has_npth_layer = true;
340
341 if( pad->HasHole() && pad->GetDrillSizeX() != pad->GetDrillSizeY() )
342 slot_holes[std::make_pair( F_Cu, B_Cu )].push_back( pad );
343 else if( pad->HasHole() )
344 {
345 ODB_DRILL_SPAN padSpan( F_Cu, B_Cu, false, pad->GetAttribute() == PAD_ATTRIB::NPTH );
346 drill_layers[padSpan].push_back( pad );
347 }
348 }
349 }
350
351 if( has_npth_layer )
352 {
353 ODB_DRILL_SPAN npthSpan( F_Cu, B_Cu, false, true );
354 drill_layers[npthSpan];
355 }
356
357 if( has_pth_layer )
358 {
359 ODB_DRILL_SPAN platedSpan( F_Cu, B_Cu, false, false );
360 drill_layers[platedSpan];
361 }
362
363 int backdrillIndex = 1;
364
365 auto assignName = [&]( const ODB_DRILL_SPAN& aSpan )
366 {
367 auto it = span_names.find( aSpan );
368
369 if( it != span_names.end() )
370 return it->second;
371
372 wxString name;
373
374 if( aSpan.m_IsBackdrill )
375 {
376 name.Printf( wxT( "drill%d" ), backdrillIndex++ );
377 }
378 else
379 {
380 wxString platedLabel = aSpan.m_IsNonPlated ? wxT( "non-plated" ) : wxT( "plated" );
381 name.Printf( wxT( "drill_%s_%s-%s" ), platedLabel,
382 m_board->GetLayerName( aSpan.TopLayer() ),
383 m_board->GetLayerName( aSpan.BottomLayer() ) );
384 }
385
386 wxString legalName = ODB::GenLegalEntityName( name );
387 span_names[aSpan] = legalName;
388
389 return legalName;
390 };
391
392 auto InitDrillMatrix = [&]( const ODB_DRILL_SPAN& aSpan )
393 {
394 wxString dLayerName = assignName( aSpan );
395 MATRIX_LAYER matrix( m_row++, dLayerName );
396
397 matrix.m_type = ODB_TYPE::DRILL;
400 matrix.m_span.emplace( std::make_pair(
401 ODB::GenLegalEntityName( m_board->GetLayerName( aSpan.m_StartLayer ) ),
402 ODB::GenLegalEntityName( m_board->GetLayerName( aSpan.m_EndLayer ) ) ) );
403
404 if( aSpan.m_IsBackdrill )
405 matrix.m_addType.emplace( ODB_SUBTYPE::BACKDRILL );
406
407 m_matrixLayers.push_back( matrix );
408 m_plugin->GetLayerNameList().emplace_back(
409 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
410 };
411
412 for( const auto& entry : drill_layers )
413 {
414 InitDrillMatrix( entry.first );
415 }
416}
417
418
420{
421 MATRIX_LAYER matrix( m_row++, "COMP_+_TOP" );
424
425 if( aCompSide == F_Cu )
426 {
427 m_matrixLayers.push_back( matrix );
428 m_plugin->GetLayerNameList().emplace_back(
429 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
430 }
431
432 if( aCompSide == B_Cu && m_hasBotComp )
433 {
434 matrix.m_layerName = ODB::GenLegalEntityName( "COMP_+_BOT" );
435 m_matrixLayers.push_back( matrix );
436 m_plugin->GetLayerNameList().emplace_back(
437 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
438 }
439}
440
442{
443 auto& auxilliary_layers = m_plugin->GetAuxilliaryLayerItemsMap();
444
445 for( BOARD_ITEM* item : m_board->Tracks() )
446 {
447 if( item->Type() == PCB_VIA_T )
448 {
449 PCB_VIA* via = static_cast<PCB_VIA*>( item );
450
451 if( via->Padstack().IsFilled().value_or( false ) )
452 {
453 auxilliary_layers[std::make_tuple( ODB_AUX_LAYER_TYPE::FILLING, via->TopLayer(),
454 via->BottomLayer() )]
455 .push_back( via );
456 }
457
458 if( via->Padstack().IsCapped().value_or( false ) )
459 {
460 auxilliary_layers[std::make_tuple( ODB_AUX_LAYER_TYPE::CAPPING, via->TopLayer(),
461 via->BottomLayer() )]
462 .push_back( via );
463 }
464
465 for( PCB_LAYER_ID layer : { via->TopLayer(), via->BottomLayer() } )
466 {
467 if( via->Padstack().IsPlugged( layer ).value_or( false ) )
468 {
469 auxilliary_layers[std::make_tuple( ODB_AUX_LAYER_TYPE::PLUGGING, layer,
471 .push_back( via );
472 }
473
474 if( via->Padstack().IsCovered( layer ).value_or( false ) )
475 {
476 auxilliary_layers[std::make_tuple( ODB_AUX_LAYER_TYPE::COVERING, layer,
478 .push_back( via );
479 }
480
481 if( via->Padstack().IsTented( layer ).value_or( false ) )
482 {
483 auxilliary_layers[std::make_tuple( ODB_AUX_LAYER_TYPE::TENTING, layer,
485 .push_back( via );
486 }
487 }
488 }
489 }
490
491 auto InitAuxMatrix =
492 [&]( std::tuple<ODB_AUX_LAYER_TYPE, PCB_LAYER_ID, PCB_LAYER_ID> aLayerPair )
493 {
494 wxString featureName = "";
495 switch( std::get<0>( aLayerPair ) )
496 {
497 case ODB_AUX_LAYER_TYPE::TENTING: featureName = "tenting"; break;
498 case ODB_AUX_LAYER_TYPE::COVERING: featureName = "covering"; break;
499 case ODB_AUX_LAYER_TYPE::PLUGGING: featureName = "plugging"; break;
500 case ODB_AUX_LAYER_TYPE::FILLING: featureName = "filling"; break;
501 case ODB_AUX_LAYER_TYPE::CAPPING: featureName = "capping"; break;
502 default: return;
503 }
504
505 wxString dLayerName;
506
507 if( std::get<2>( aLayerPair ) != PCB_LAYER_ID::UNDEFINED_LAYER )
508 {
509 dLayerName = wxString::Format( "%s_%s-%s", featureName,
510 m_board->GetLayerName( std::get<1>( aLayerPair ) ),
511 m_board->GetLayerName( std::get<2>( aLayerPair ) ) );
512 }
513 else
514 {
515 if( m_board->IsFrontLayer( std::get<1>( aLayerPair ) ) )
516 dLayerName = wxString::Format( "%s_front", featureName );
517 else if( m_board->IsBackLayer( std::get<1>( aLayerPair ) ) )
518 dLayerName = wxString::Format( "%s_back", featureName );
519 else
520 return;
521 }
522 MATRIX_LAYER matrix( m_row++, dLayerName );
523
524 matrix.m_type = ODB_TYPE::DOCUMENT;
527
528 if( std::get<2>( aLayerPair ) != PCB_LAYER_ID::UNDEFINED_LAYER )
529 {
530 matrix.m_span.emplace( std::make_pair(
531 ODB::GenLegalEntityName( m_board->GetLayerName( std::get<1>( aLayerPair ) ) ),
533 m_board->GetLayerName( std::get<2>( aLayerPair ) ) ) ) );
534 }
535
536 m_matrixLayers.push_back( matrix );
537
538 if( std::get<2>( aLayerPair ) != PCB_LAYER_ID::UNDEFINED_LAYER )
539 {
540 m_plugin->GetLayerNameList().emplace_back(
541 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
542 }
543 else
544 {
545 m_plugin->GetLayerNameList().emplace_back(
546 std::make_pair( std::get<1>( aLayerPair ), matrix.m_layerName ) );
547 }
548 };
549
550 for( const auto& [layer_pair, vec] : auxilliary_layers )
551 {
552 InitAuxMatrix( layer_pair );
553 }
554}
555
556
558{
559 // Track occurrences of each layer name to detect and handle duplicates
560 std::map<wxString, std::vector<size_t>> name_to_indices;
561
562 // First pass: collect all layer names and their indices
563 for( size_t i = 0; i < m_matrixLayers.size(); ++i )
564 {
565 const wxString& layerName = m_matrixLayers[i].m_layerName;
566 name_to_indices[layerName].push_back( i );
567 }
568
569 // Second pass: for any layer names that appear more than once, add suffixes
570 for( auto& [layerName, indices] : name_to_indices )
571 {
572 if( indices.size() > 1 )
573 {
574 // Multiple layers have the same name, add suffixes to make them unique
575 for( size_t count = 0; count < indices.size(); ++count )
576 {
577 size_t idx = indices[count];
578 wxString newLayerName = wxString::Format( "%s_%zu", m_matrixLayers[idx].m_layerName, count + 1 );
579
580 // Ensure the new name doesn't exceed the 64-character limit
581 if( newLayerName.length() > 64 )
582 {
583 // Truncate the base name if necessary to fit the suffix
584 wxString baseName = m_matrixLayers[idx].m_layerName;
585 size_t suffixLen = wxString::Format( "_%zu", count + 1 ).length();
586
587 if( suffixLen < baseName.length() )
588 {
589 baseName.Truncate( 64 - suffixLen );
590 newLayerName = wxString::Format( "%s_%zu", baseName, count + 1 );
591 }
592 }
593
594 m_matrixLayers[idx].m_layerName = std::move( newLayerName );
595 }
596 }
597 }
598}
599
600
602{
603 auto fileproxy = writer.CreateFileProxy( "matrix" );
604
605 ODB_TEXT_WRITER twriter( fileproxy.GetStream() );
606
607 for( const auto& [step_name, column] : m_matrixSteps )
608 {
609 const auto array_proxy = twriter.MakeArrayProxy( "STEP" );
610 twriter.WriteEquationLine( "COL", column );
611 twriter.WriteEquationLine( "NAME", step_name );
612 }
613
614 for( const MATRIX_LAYER& layer : m_matrixLayers )
615 {
616 const auto array_proxy = twriter.MakeArrayProxy( "LAYER" );
617 twriter.WriteEquationLine( "ROW", layer.m_rowNumber );
618 twriter.write_line_enum( "CONTEXT", layer.m_context );
619 twriter.write_line_enum( "TYPE", layer.m_type );
620
621 if( layer.m_addType.has_value() )
622 {
623 twriter.write_line_enum( "ADD_TYPE", layer.m_addType.value() );
624 }
625
626 twriter.WriteEquationLine( "NAME", layer.m_layerName.Upper() );
627 twriter.WriteEquationLine( "OLD_NAME", wxEmptyString );
628 twriter.write_line_enum( "POLARITY", layer.m_polarity );
629
630 if( layer.m_diType.has_value() )
631 {
632 twriter.write_line_enum( "DIELECTRIC_TYPE", layer.m_diType.value() );
633 // twriter.WriteEquationLine( "DIELECTRIC_NAME", wxEmptyString );
634
635 // Can be used with DIELECTRIC_TYPE=CORE
636 // twriter.WriteEquationLine( "CU_TOP", wxEmptyString );
637 // twriter.WriteEquationLine( "CU_BOTTOM", wxEmptyString );
638 }
639
640 // Only applies to: soldermask, silkscreen, solderpaste and specifies the relevant cu layer
641 // twriter.WriteEquationLine( "REF", wxEmptyString );
642
643 if( layer.m_span.has_value() )
644 {
645 twriter.WriteEquationLine( "START_NAME", layer.m_span->first.Upper() );
646 twriter.WriteEquationLine( "END_NAME", layer.m_span->second.Upper() );
647 }
648
649 twriter.WriteEquationLine( "COLOR", "0" );
650 }
651}
652
653
655 std::map<int, std::vector<BOARD_ITEM*>>& aMap,
656 const PCB_LAYER_ID& aLayerID, const wxString& aLayerName ) :
657 ODB_ENTITY_BASE( aBoard, aPlugin ), m_layerItems( aMap ), m_layerID( aLayerID ),
658 m_matrixLayerName( aLayerName )
659{
660 m_featuresMgr = std::make_unique<FEATURES_MANAGER>( aBoard, aPlugin, aLayerName );
661}
662
663
665{
666 if( m_matrixLayerName.Contains( "drill" ) )
667 {
670 return;
671 }
672
673 if( m_matrixLayerName.Contains( "filling" ) || m_matrixLayerName.Contains( "capping" )
674 || m_matrixLayerName.Contains( "covering" ) || m_matrixLayerName.Contains( "plugging" )
675 || m_matrixLayerName.Contains( "tenting" ) )
676 {
679 return;
680 }
681
683 {
685 }
686}
687
689{
690 if( m_layerItems.empty() )
691 return;
692
693 const NETINFO_LIST& nets = m_board->GetNetInfo();
694
695 for( const NETINFO_ITEM* net : nets )
696 {
697 std::vector<BOARD_ITEM*>& vec = m_layerItems[net->GetNetCode()];
698
699 std::stable_sort( vec.begin(), vec.end(),
700 []( BOARD_ITEM* a, BOARD_ITEM* b )
701 {
702 if( a->GetParentFootprint() == b->GetParentFootprint() )
703 return a->Type() < b->Type();
704
705 return a->GetParentFootprint() < b->GetParentFootprint();
706 } );
707
708 if( vec.empty() )
709 continue;
710
711 m_featuresMgr->InitFeatureList( m_layerID, vec );
712 }
713}
714
715
717 const EDA_DATA::PACKAGE& aPkg )
718{
719 if( m_matrixLayerName == "COMP_+_BOT" )
720 {
721 if( !m_compBot.has_value() )
722 {
723 m_compBot.emplace();
724 }
725 return m_compBot.value().AddComponent( aFp, aPkg );
726 }
727 else
728 {
729 if( !m_compTop.has_value() )
730 {
731 m_compTop.emplace();
732 }
733
734 return m_compTop.value().AddComponent( aFp, aPkg );
735 }
736}
737
738
740{
741 std::map<ODB_DRILL_SPAN, std::vector<BOARD_ITEM*>>& drill_layers =
742 m_plugin->GetDrillLayerItemsMap();
743
744 std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& slot_holes =
745 m_plugin->GetSlotHolesMap();
746
747 std::map<ODB_DRILL_SPAN, wxString>& span_names = m_plugin->GetDrillSpanNameMap();
748
749 if( !m_layerItems.empty() )
750 {
751 m_layerItems.clear();
752 }
753
755
756 std::optional<ODB_DRILL_SPAN> matchedSpan;
757
758 for( const auto& [span, name] : span_names )
759 {
760 if( name == m_matrixLayerName )
761 {
762 matchedSpan = span;
763 break;
764 }
765 }
766
767 bool useLegacyMatching = !matchedSpan.has_value();
768 bool isBackdrillLayer = matchedSpan.has_value() && matchedSpan->m_IsBackdrill;
769 bool isNonPlatedLayer = matchedSpan.has_value() && matchedSpan->m_IsNonPlated;
770 bool isNPTHLayer = matchedSpan.has_value() && matchedSpan->m_IsNonPlated
771 && !matchedSpan->m_IsBackdrill;
772
773 if( matchedSpan.has_value() && isNPTHLayer )
774 {
775 auto slotIt = slot_holes.find( matchedSpan->Pair() );
776
777 if( slotIt != slot_holes.end() )
778 {
779 for( BOARD_ITEM* item : slotIt->second )
780 {
781 if( item->Type() != PCB_PAD_T )
782 continue;
783
784 PAD* pad = static_cast<PAD*>( item );
785
786 if( pad->GetAttribute() == PAD_ATTRIB::PTH )
787 continue;
788
789 m_tools.value().AddDrillTools( wxT( "NON_PLATED" ),
791 std::min( pad->GetDrillSizeX(),
792 pad->GetDrillSizeY() ) ) );
793
794 m_layerItems[pad->GetNetCode()].push_back( item );
795 }
796 }
797 }
798 else if( useLegacyMatching )
799 {
800 bool is_npth_layer = false;
801 wxString plated_name = wxT( "plated" );
802
803 if( m_matrixLayerName.Contains( wxT( "non-plated" ) ) )
804 {
805 is_npth_layer = true;
806 plated_name = wxT( "non-plated" );
807 }
808
809 for( const auto& [layer_pair, vec] : slot_holes )
810 {
811 wxString dLayerName = wxString::Format( wxT( "drill_%s_%s-%s" ), plated_name,
812 m_board->GetLayerName( layer_pair.first ),
813 m_board->GetLayerName( layer_pair.second ) );
814
815 if( ODB::GenLegalEntityName( dLayerName ) == m_matrixLayerName )
816 {
817 for( BOARD_ITEM* item : vec )
818 {
819 if( item->Type() != PCB_PAD_T )
820 continue;
821
822 PAD* pad = static_cast<PAD*>( item );
823
824 if( ( is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH )
825 || ( !is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
826 {
827 continue;
828 }
829
830 m_tools.value().AddDrillTools(
831 pad->GetAttribute() == PAD_ATTRIB::PTH ? wxT( "PLATED" )
832 : wxT( "NON_PLATED" ),
834 std::min( pad->GetDrillSizeX(), pad->GetDrillSizeY() ) ) );
835
836 m_layerItems[pad->GetNetCode()].push_back( item );
837 }
838
839 break;
840 }
841 }
842 }
843
844 if( matchedSpan.has_value() )
845 {
846 auto drillIt = drill_layers.find( *matchedSpan );
847
848 if( drillIt != drill_layers.end() )
849 {
850 for( BOARD_ITEM* item : drillIt->second )
851 {
852 if( item->Type() == PCB_VIA_T )
853 {
854 PCB_VIA* via = static_cast<PCB_VIA*>( item );
855
856 if( isBackdrillLayer )
857 {
858 const PADSTACK::DRILL_PROPS& secondary = via->Padstack().SecondaryDrill();
859
860 int diameter = secondary.size.x;
861
862 if( secondary.size.y > 0 )
863 {
864 diameter = ( diameter > 0 ) ? std::min( diameter, secondary.size.y )
865 : secondary.size.y;
866 }
867
868 if( diameter <= 0 )
869 continue;
870
871 m_tools.value().AddDrillTools( wxT( "NON_PLATED" ),
872 ODB::SymDouble2String( diameter ),
873 wxT( "BLIND" ) );
874 }
875 else if( isNonPlatedLayer )
876 {
877 m_tools.value().AddDrillTools( wxT( "NON_PLATED" ),
878 ODB::SymDouble2String( via->GetDrillValue() ) );
879 }
880 else
881 {
882 m_tools.value().AddDrillTools( wxT( "VIA" ),
883 ODB::SymDouble2String( via->GetDrillValue() ) );
884 }
885
886 m_layerItems[via->GetNetCode()].push_back( item );
887 }
888 else if( item->Type() == PCB_PAD_T )
889 {
890 PAD* pad = static_cast<PAD*>( item );
891
892 bool padIsNPTH = pad->GetAttribute() == PAD_ATTRIB::NPTH;
893
894 if( isNPTHLayer && !padIsNPTH )
895 continue;
896
897 if( !isNonPlatedLayer && padIsNPTH )
898 continue;
899
900 int drillSize = pad->GetDrillSizeX();
901
902 if( pad->GetDrillSizeX() != pad->GetDrillSizeY() )
903 drillSize = std::min( pad->GetDrillSizeX(), pad->GetDrillSizeY() );
904
905 wxString typeLabel = ( padIsNPTH || isNonPlatedLayer ) ? wxT( "NON_PLATED" )
906 : wxT( "PLATED" );
907 wxString type2 = isBackdrillLayer ? wxT( "BLIND" ) : wxT( "STANDARD" );
908
909 m_tools.value().AddDrillTools( typeLabel, ODB::SymDouble2String( drillSize ),
910 type2 );
911
912 m_layerItems[pad->GetNetCode()].push_back( item );
913 }
914 }
915 }
916 }
917 else
918 {
919 bool is_npth_layer = false;
920 wxString plated_name = wxT( "plated" );
921
922 if( m_matrixLayerName.Contains( wxT( "non-plated" ) ) )
923 {
924 is_npth_layer = true;
925 plated_name = wxT( "non-plated" );
926 }
927
928 for( const auto& [span, vec] : drill_layers )
929 {
930 wxString dLayerName = wxString::Format( wxT( "drill_%s_%s-%s" ), plated_name,
931 m_board->GetLayerName( span.TopLayer() ),
932 m_board->GetLayerName( span.BottomLayer() ) );
933
934 if( ODB::GenLegalEntityName( dLayerName ) == m_matrixLayerName )
935 {
936 for( BOARD_ITEM* item : vec )
937 {
938 if( item->Type() == PCB_VIA_T && !is_npth_layer )
939 {
940 PCB_VIA* via = static_cast<PCB_VIA*>( item );
941
942 m_tools.value().AddDrillTools( wxT( "VIA" ),
943 ODB::SymDouble2String( via->GetDrillValue() ) );
944
945 m_layerItems[via->GetNetCode()].push_back( item );
946 }
947 else if( item->Type() == PCB_PAD_T )
948 {
949 PAD* pad = static_cast<PAD*>( item );
950
951 if( ( is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH )
952 || ( !is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
953 {
954 continue;
955 }
956
957 m_tools.value().AddDrillTools(
958 pad->GetAttribute() == PAD_ATTRIB::PTH ? wxT( "PLATED" )
959 : wxT( "NON_PLATED" ),
960 ODB::SymDouble2String( pad->GetDrillSizeX() ) );
961
962 m_layerItems[pad->GetNetCode()].push_back( item );
963 }
964 }
965
966 break;
967 }
968 }
969 }
970}
971
973{
974 auto& auxilliary_layers = m_plugin->GetAuxilliaryLayerItemsMap();
975
976 if( !m_layerItems.empty() )
977 {
978 m_layerItems.clear();
979 }
980
981 for( const auto& [layer_pair, vec] : auxilliary_layers )
982 {
983 wxString featureName = "";
984 switch( std::get<0>( layer_pair ) )
985 {
986 case ODB_AUX_LAYER_TYPE::TENTING: featureName = "tenting"; break;
987 case ODB_AUX_LAYER_TYPE::COVERING: featureName = "covering"; break;
988 case ODB_AUX_LAYER_TYPE::PLUGGING: featureName = "plugging"; break;
989 case ODB_AUX_LAYER_TYPE::FILLING: featureName = "filling"; break;
990 case ODB_AUX_LAYER_TYPE::CAPPING: featureName = "capping"; break;
991 default: return;
992 }
993
994 wxString dLayerName;
995 bool drill_value = false;
996
997 if( std::get<2>( layer_pair ) != PCB_LAYER_ID::UNDEFINED_LAYER )
998 {
999 drill_value = true;
1000 dLayerName = wxString::Format( "%s_%s-%s", featureName,
1001 m_board->GetLayerName( std::get<1>( layer_pair ) ),
1002 m_board->GetLayerName( std::get<2>( layer_pair ) ) );
1003 }
1004 else
1005 {
1006 if( m_board->IsFrontLayer( std::get<1>( layer_pair ) ) )
1007 dLayerName = wxString::Format( "%s_front", featureName );
1008 else if( m_board->IsBackLayer( std::get<1>( layer_pair ) ) )
1009 dLayerName = wxString::Format( "%s_back", featureName );
1010 else
1011 return;
1012 }
1013
1014 if( ODB::GenLegalEntityName( dLayerName ) == m_matrixLayerName )
1015 {
1016 for( BOARD_ITEM* item : vec )
1017 {
1018 if( item->Type() == PCB_VIA_T )
1019 {
1020 PCB_VIA* via = static_cast<PCB_VIA*>( item );
1021
1022 m_layerItems[via->GetNetCode()].push_back( item );
1023 }
1024 }
1025
1026 break;
1027 }
1028 }
1029}
1030
1032{
1034
1035 InitEdaData();
1036
1037 // Init Layer Entity Data
1038 for( const auto& [layerName, layer_entity_ptr] : m_layerEntityMap )
1039 {
1040 layer_entity_ptr->InitEntityData();
1041 }
1042}
1043
1044
1046{
1047 GenAttrList( writer );
1048
1049 GenFeatures( writer );
1050
1051 if( m_compTop.has_value() || m_compBot.has_value() )
1052 {
1053 GenComponents( writer );
1054 }
1055
1056 if( m_tools.has_value() )
1057 {
1058 GenTools( writer );
1059 }
1060}
1061
1062
1064{
1065 auto fileproxy = writer.CreateFileProxy( "components" );
1066
1067 if( m_compTop.has_value() )
1068 {
1069 m_compTop->Write( fileproxy.GetStream() );
1070 }
1071 else if( m_compBot.has_value() )
1072 {
1073 m_compBot->Write( fileproxy.GetStream() );
1074 }
1075}
1076
1077
1079{
1080 auto fileproxy = writer.CreateFileProxy( "features" );
1081
1082 m_featuresMgr->GenerateFeatureFile( fileproxy.GetStream() );
1083}
1084
1085
1087{
1088 auto fileproxy = writer.CreateFileProxy( "attrlist" );
1089}
1090
1091
1093{
1094 auto fileproxy = writer.CreateFileProxy( "tools" );
1095
1096 m_tools.value().GenerateFile( fileproxy.GetStream() );
1097}
1098
1099
1101{
1102 //InitPackage
1103 for( const FOOTPRINT* fp : m_board->Footprints() )
1104 {
1105 m_edaData.AddPackage( fp );
1106 }
1107
1108 // for NET
1109 const NETINFO_LIST& nets = m_board->GetNetInfo();
1110
1111 for( const NETINFO_ITEM* net : nets )
1112 {
1113 m_edaData.AddNET( net );
1114 }
1115
1116 // for CMP
1117 size_t j = 0;
1118
1119 for( const FOOTPRINT* fp : m_board->Footprints() )
1120 {
1121 wxString compName = ODB::GenLegalEntityName( "COMP_+_TOP" );
1122 if( fp->IsFlipped() )
1123 compName = ODB::GenLegalEntityName( "COMP_+_BOT" );
1124
1125 auto iter = m_layerEntityMap.find( compName );
1126
1127 if( iter == m_layerEntityMap.end() )
1128 {
1129 wxLogError( _( "Failed to add component data" ) );
1130 return;
1131 }
1132
1133 // ODBPP only need unique PACKAGE in PKG record in eda/data file.
1134 // the PKG index can repeat to be ref in CMP record in component file.
1135 std::shared_ptr<FOOTPRINT> fp_pkg = m_edaData.GetEdaFootprints().at( j );
1136 ++j;
1137
1138 const EDA_DATA::PACKAGE& eda_pkg =
1139 m_edaData.GetPackage( hash_fp_item( fp_pkg.get(), HASH_POS | REL_COORD ) );
1140
1141 if( fp->Pads().empty() )
1142 continue;
1143
1144 ODB_COMPONENT& comp = iter->second->InitComponentData( fp, eda_pkg );
1145
1146 for( int i = 0; i < fp->Pads().size(); ++i )
1147 {
1148 PAD* pad = fp->Pads()[i];
1149 auto& eda_net = m_edaData.GetNet( pad->GetNetCode() );
1150
1151 auto& subnet = eda_net.AddSubnet<EDA_DATA::SUB_NET_TOEPRINT>(
1152 &m_edaData,
1155 comp.m_index, comp.m_toeprints.size() );
1156
1157 m_plugin->GetPadSubnetMap().emplace( pad, &subnet );
1158
1159 const std::shared_ptr<EDA_DATA::PIN> pin = eda_pkg.GetEdaPkgPin( i );
1160 const EDA_DATA::PIN& pin_ref = *pin;
1161 auto& toep = comp.m_toeprints.emplace_back( pin_ref );
1162
1163 toep.m_net_num = eda_net.m_index;
1164 toep.m_subnet_num = subnet.m_index;
1165
1166 toep.m_center = ODB::AddXY( pad->GetPosition() );
1167
1168 toep.m_rot = ODB::Double2String(
1169 ( ANGLE_360 - pad->GetOrientation() ).Normalize().AsDegrees() );
1170
1171 if( pad->IsFlipped() )
1172 toep.m_mirror = wxT( "M" );
1173 else
1174 toep.m_mirror = wxT( "N" );
1175 }
1176 }
1177
1178 for( PCB_TRACK* track : m_board->Tracks() )
1179 {
1180 auto& eda_net = m_edaData.GetNet( track->GetNetCode() );
1181 EDA_DATA::SUB_NET* subnet = nullptr;
1182
1183 if( track->Type() == PCB_VIA_T )
1184 subnet = &( eda_net.AddSubnet<EDA_DATA::SUB_NET_VIA>( &m_edaData ) );
1185 else
1186 subnet = &( eda_net.AddSubnet<EDA_DATA::SUB_NET_TRACE>( &m_edaData ) );
1187
1188 m_plugin->GetViaTraceSubnetMap().emplace( track, subnet );
1189 }
1190
1191 for( ZONE* zone : m_board->Zones() )
1192 {
1193 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
1194 {
1195 auto& eda_net = m_edaData.GetNet( zone->GetNetCode() );
1196 auto& subnet = eda_net.AddSubnet<EDA_DATA::SUB_NET_PLANE>( &m_edaData,
1199 0 );
1200 m_plugin->GetPlaneSubnetMap().emplace( std::piecewise_construct,
1201 std::forward_as_tuple( layer, zone ),
1202 std::forward_as_tuple( &subnet ) );
1203 }
1204 }
1205}
1206
1207
1209{
1210 wxString step_root = writer.GetCurrentPath();
1211
1212 writer.CreateEntityDirectory( step_root, "layers" );
1213 GenerateLayerFiles( writer );
1214
1215 writer.CreateEntityDirectory( step_root, "eda" );
1216 GenerateEdaFiles( writer );
1217
1218 writer.CreateEntityDirectory( step_root, "netlists/cadnet" );
1219 GenerateNetlistsFiles( writer );
1220
1221 writer.SetCurrentPath( step_root );
1222 GenerateProfileFile( writer );
1223
1224 GenerateStepHeaderFile( writer );
1225
1226 //TODO: system attributes
1227 // GenerateAttrListFile( writer );
1228}
1229
1230
1232{
1233 auto fileproxy = writer.CreateFileProxy( "profile" );
1234
1235 m_profile = std::make_unique<FEATURES_MANAGER>( m_board, m_plugin, wxEmptyString );
1236
1237 SHAPE_POLY_SET board_outline;
1238
1239 if( !m_board->GetBoardPolygonOutlines( board_outline, true ) )
1240 {
1241 wxLogError( "Failed to get board outline" );
1242 }
1243
1244 if( !m_profile->AddContour( board_outline, 0 ) )
1245 {
1246 wxLogError( "Failed to add polygon to profile" );
1247 }
1248
1249 m_profile->GenerateProfileFeatures( fileproxy.GetStream() );
1250}
1251
1252
1254{
1255 auto fileproxy = writer.CreateFileProxy( "stephdr" );
1256
1257 m_stephdr = {
1259 { "X_DATUM", "0" },
1260 { "Y_DATUM", "0" },
1261 { "X_ORIGIN", "0" },
1262 { "Y_ORIGIN", "0" },
1263 { "TOP_ACTIVE", "0" },
1264 { "BOTTOM_ACTIVE", "0" },
1265 { "RIGHT_ACTIVE", "0" },
1266 { "LEFT_ACTIVE", "0" },
1267 { "AFFECTING_BOM", "" },
1268 { "AFFECTING_BOM_CHANGED", "0" },
1269 };
1270
1271 ODB_TEXT_WRITER twriter( fileproxy.GetStream() );
1272
1273 for( const auto& [key, value] : m_stephdr )
1274 {
1275 twriter.WriteEquationLine( key, value );
1276 }
1277}
1278
1279
1281{
1282 wxString layers_root = writer.GetCurrentPath();
1283
1284 for( auto& [layerName, layerEntity] : m_layerEntityMap )
1285 {
1286 writer.CreateEntityDirectory( layers_root, layerName );
1287
1288 layerEntity->GenerateFiles( writer );
1289 }
1290}
1291
1292
1294{
1295 auto fileproxy = writer.CreateFileProxy( "data" );
1296
1297 m_edaData.Write( fileproxy.GetStream() );
1298}
1299
1300
1302{
1303 auto fileproxy = writer.CreateFileProxy( "netlist" );
1304
1305 m_netlist.Write( fileproxy.GetStream() );
1306}
1307
1308
1310{
1311 try
1312 {
1313 writer.CreateEntityDirectory( writer.GetRootPath(), "steps" );
1315 return true;
1316 }
1317 catch( const std::exception& e )
1318 {
1319 std::cerr << e.what() << std::endl;
1320 return false;
1321 }
1322}
1323
1324
1326{
1327 LSET layers = m_board->GetEnabledLayers();
1328 const NETINFO_LIST& nets = m_board->GetNetInfo();
1329
1330 // To avoid the overhead of repeatedly cycling through the layers and nets,
1331 // we pre-sort the board items into a map of layer -> net -> items
1332 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>>& elements = m_plugin->GetLayerElementsMap();
1333
1334 std::for_each( m_board->Tracks().begin(), m_board->Tracks().end(),
1335 [&layers, &elements]( PCB_TRACK* aTrack )
1336 {
1337 if( aTrack->Type() == PCB_VIA_T )
1338 {
1339 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
1340
1341 for( PCB_LAYER_ID layer : layers )
1342 {
1343 if( via->FlashLayer( layer ) )
1344 elements[layer][via->GetNetCode()].push_back( via );
1345 }
1346 }
1347 else
1348 {
1349 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
1350 }
1351 } );
1352
1353 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
1354 [&elements]( ZONE* zone )
1355 {
1356 for( PCB_LAYER_ID layer : zone->GetLayerSet() )
1357 elements[layer][zone->GetNetCode()].push_back( zone );
1358 } );
1359
1360 for( BOARD_ITEM* item : m_board->Drawings() )
1361 {
1362 if( BOARD_CONNECTED_ITEM* conn_it = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
1363 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
1364 else
1365 elements[item->GetLayer()][0].push_back( item );
1366 }
1367
1368 for( FOOTPRINT* fp : m_board->Footprints() )
1369 {
1370 for( PCB_FIELD* field : fp->GetFields() )
1371 elements[field->GetLayer()][0].push_back( field );
1372
1373 for( BOARD_ITEM* item : fp->GraphicalItems() )
1374 elements[item->GetLayer()][0].push_back( item );
1375
1376 for( PAD* pad : fp->Pads() )
1377 {
1378 VECTOR2I margin;
1379
1380 for( PCB_LAYER_ID layer : pad->GetLayerSet() )
1381 {
1382 bool onCopperLayer = LSET::AllCuMask().test( layer );
1383 bool onSolderMaskLayer = LSET( { F_Mask, B_Mask } ).test( layer );
1384 bool onSolderPasteLayer = LSET( { F_Paste, B_Paste } ).test( layer );
1385
1386 if( onSolderMaskLayer )
1387 margin.x = margin.y = pad->GetSolderMaskExpansion( PADSTACK::ALL_LAYERS );
1388
1389 if( onSolderPasteLayer )
1390 margin = pad->GetSolderPasteMargin( PADSTACK::ALL_LAYERS );
1391
1392 VECTOR2I padPlotsSize = pad->GetSize( PADSTACK::ALL_LAYERS ) + margin * 2;
1393
1394 if( onCopperLayer && !pad->IsOnCopperLayer() )
1395 continue;
1396
1397 if( onCopperLayer && !pad->FlashLayer( layer ) )
1398 continue;
1399
1400 if( pad->GetShape( PADSTACK::ALL_LAYERS ) != PAD_SHAPE::CUSTOM
1401 && ( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 ) )
1402 {
1403 continue;
1404 }
1405
1406 elements[layer][pad->GetNetCode()].push_back( pad );
1407 }
1408 }
1409 }
1410
1411 for( const auto& [layerID, layerName] : m_plugin->GetLayerNameList() )
1412 {
1413 std::shared_ptr<ODB_LAYER_ENTITY> layer_entity_ptr = std::make_shared<ODB_LAYER_ENTITY>(
1414 m_board, m_plugin, elements[layerID], layerID, layerName );
1415
1416 m_layerEntityMap.emplace( layerName, layer_entity_ptr );
1417 }
1418}
const char * name
@ 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:83
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
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
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
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:312
void write_line_enum(const std::string &var, const T &value)
Definition odb_util.h:286
const wxString GetRootPath() const
Definition odb_util.h:267
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:254
void SetCurrentPath(const wxString &aDir)
Definition odb_util.h:263
const wxString GetCurrentPath() const
Definition odb_util.h:261
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:177
Definition pad.h:55
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:103
@ PTH
Plated through hole pad.
Definition padstack.h:98
see class PGM_BASE
#define KEY_CORE
std::optional< ODB_SUBTYPE > m_addType
Definition odb_entity.h:83
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
! The properties of a padstack drill. Drill position is always the pad position (origin).
Definition padstack.h:261
PCB_LAYER_ID start
Definition padstack.h:264
PCB_LAYER_ID end
Definition padstack.h:265
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
Definition padstack.h:262
KIBIS_COMPONENT * comp
KIBIS_PIN * pin
@ 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