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 (C) 2024 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" + GetMajorMinorPatchVersion() ) },
84 { wxS( "CREATION_DATE" ), wxDateTime::Now().FormatISOCombined() },
85 { wxS( "SAVE_DATE" ), wxDateTime::Now().FormatISOCombined() },
86 { wxS( "SAVE_APP" ), wxS( "Pcbnew" ) },
87 { wxS( "SAVE_USER" ), wxS( "" ) } };
88}
89
90
92{
93 auto fileproxy = writer.CreateFileProxy( "info" );
94
95 ODB_TEXT_WRITER twriter( fileproxy.GetStream() );
96
97 for( auto& info : m_info )
98 {
99 twriter.WriteEquationLine( info.first, info.second );
100 }
101}
102
103
104void ODB_MATRIX_ENTITY::AddStep( const wxString& aStepName )
105{
106 m_matrixSteps.emplace( aStepName.Upper(), m_col++ );
107}
108
109
111{
112 AddStep( "PCB" );
113
115}
116
117
119{
121 BOARD_STACKUP& stackup = dsnSettings.GetStackupDescriptor();
122 stackup.SynchronizeWithBoard( &dsnSettings );
123
124 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.GetList();
125 std::set<PCB_LAYER_ID> added_layers;
126
127 for( int i = 0; i < stackup.GetCount(); i++ )
128 {
129 BOARD_STACKUP_ITEM* stackup_item = layers.at( i );
130
131 for( int sublayer_id = 0; sublayer_id < stackup_item->GetSublayersCount(); sublayer_id++ )
132 {
133 wxString ly_name = stackup_item->GetLayerName();
134
135 if( ly_name.IsEmpty() )
136 {
137 if( IsValidLayer( stackup_item->GetBrdLayerId() ) )
138 ly_name = m_board->GetLayerName( stackup_item->GetBrdLayerId() );
139
140 if( ly_name.IsEmpty() && stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
141 ly_name = wxString::Format( "DIELECTRIC_%d",
142 stackup_item->GetDielectricLayerId() );
143 }
144
145 MATRIX_LAYER matrix( m_row++, ly_name );
146
147 if( stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
148 {
149 if( stackup_item->GetTypeName() == KEY_CORE )
150 matrix.m_diType.emplace( ODB_DIELECTRIC_TYPE::CORE );
151 else
152 matrix.m_diType.emplace( ODB_DIELECTRIC_TYPE::PREPREG );
153
154 matrix.m_type = ODB_TYPE::DIELECTRIC;
155 matrix.m_context = ODB_CONTEXT::BOARD;
156 matrix.m_polarity = ODB_POLARITY::POSITIVE;
157 m_matrixLayers.push_back( matrix );
158 m_plugin->GetLayerNameList().emplace_back(
159 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
160
161 continue;
162 }
163 else
164 {
165 added_layers.insert( stackup_item->GetBrdLayerId() );
166 AddMatrixLayerField( matrix, stackup_item->GetBrdLayerId() );
167 }
168 }
169 }
170
171 LSEQ layer_seq = m_board->GetEnabledLayers().Seq();
172
173 for( PCB_LAYER_ID layer : layer_seq )
174 {
175 if( added_layers.find( layer ) != added_layers.end() )
176 continue;
177
178 MATRIX_LAYER matrix( m_row++, m_board->GetLayerName( layer ) );
179 added_layers.insert( layer );
180 AddMatrixLayerField( matrix, layer );
181 }
182
184
186}
187
188
190{
191 aMLayer.m_polarity = ODB_POLARITY::POSITIVE;
192 aMLayer.m_context = ODB_CONTEXT::BOARD;
193 switch( aLayer )
194 {
195 case F_Paste:
196 case B_Paste: aMLayer.m_type = ODB_TYPE::SOLDER_PASTE; break;
197 case F_SilkS:
198 case B_SilkS: aMLayer.m_type = ODB_TYPE::SILK_SCREEN; break;
199 case F_Mask:
200 case B_Mask: aMLayer.m_type = ODB_TYPE::SOLDER_MASK; break;
201 case B_CrtYd:
202 case F_CrtYd:
203 case Edge_Cuts:
204 case B_Fab:
205 case F_Fab:
206 case F_Adhes:
207 case B_Adhes:
208 case Dwgs_User:
209 case Cmts_User:
210 case Eco1_User:
211 case Eco2_User:
212 case Margin:
213 case User_1:
214 case User_2:
215 case User_3:
216 case User_4:
217 case User_5:
218 case User_6:
219 case User_7:
220 case User_8:
221 case User_9:
222 aMLayer.m_context = ODB_CONTEXT::MISC;
223 aMLayer.m_type = ODB_TYPE::DOCUMENT;
224 break;
225
226 default:
227 if( IsCopperLayer( aLayer ) )
228 {
229 aMLayer.m_type = ODB_TYPE::SIGNAL;
230 }
231 else
232 {
233 // Do not handle other layers :
234 aMLayer.m_type = ODB_TYPE::UNDEFINED;
235 m_row--;
236 }
237
238 break;
239 }
240
241 if( aMLayer.m_type != ODB_TYPE::UNDEFINED )
242 {
243 m_matrixLayers.push_back( aMLayer );
244 m_plugin->GetLayerNameList().emplace_back( std::make_pair( aLayer, aMLayer.m_layerName ) );
245 }
246}
247
248
250{
251 std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& drill_layers =
253
254 std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& slot_holes =
256
257 bool has_pth_layer = false;
258 bool has_npth_layer = false;
259
260 for( BOARD_ITEM* item : m_board->Tracks() )
261 {
262 if( item->Type() == PCB_VIA_T )
263 {
264 PCB_VIA* via = static_cast<PCB_VIA*>( item );
265 drill_layers[std::make_pair( via->TopLayer(), via->BottomLayer() )].push_back( via );
266 }
267 }
268
269 for( FOOTPRINT* fp : m_board->Footprints() )
270 {
271 // std::shared_ptr<FOOTPRINT> fp( static_cast<FOOTPRINT*>( it_fp->Clone() ) );
272
273 if( fp->IsFlipped() )
274 {
275 m_hasBotComp = true;
276 }
277
278 for( PAD* pad : fp->Pads() )
279 {
280 if( !has_pth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH )
281 has_pth_layer = true;
282 if( !has_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH )
283 has_npth_layer = true;
284
285 if( pad->HasHole() && pad->GetDrillSizeX() != pad->GetDrillSizeY() )
286 slot_holes[std::make_pair( F_Cu, B_Cu )].push_back( pad );
287 else if( pad->HasHole() )
288 drill_layers[std::make_pair( F_Cu, B_Cu )].push_back( pad );
289 }
290
291 // m_plugin->GetLoadedFootprintList().push_back( std::move( fp ) );
292 }
293
294 auto InitDrillMatrix =
295 [&]( const wxString& aHasPlated, std::pair<PCB_LAYER_ID, PCB_LAYER_ID> aLayerPair )
296 {
297 wxString dLayerName = wxString::Format( "drill_%s_%s-%s", aHasPlated,
298 m_board->GetLayerName( aLayerPair.first ),
299 m_board->GetLayerName( aLayerPair.second ) );
300 MATRIX_LAYER matrix( m_row++, dLayerName );
301
302 matrix.m_type = ODB_TYPE::DRILL;
303 matrix.m_context = ODB_CONTEXT::BOARD;
304 matrix.m_polarity = ODB_POLARITY::POSITIVE;
305 matrix.m_span.emplace( std::make_pair(
306 ODB::GenLegalEntityName( m_board->GetLayerName( aLayerPair.first ) ),
307 ODB::GenLegalEntityName( m_board->GetLayerName( aLayerPair.second ) ) ) );
308 m_matrixLayers.push_back( matrix );
309 m_plugin->GetLayerNameList().emplace_back(
310 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
311 };
312
313 if( drill_layers.find( std::make_pair( F_Cu, B_Cu ) ) != drill_layers.end()
314 || !slot_holes.empty() )
315 {
316 // for pad has hole
317 if( has_pth_layer )
318 InitDrillMatrix( "plated", std::make_pair( F_Cu, B_Cu ) );
319 if( has_npth_layer )
320 InitDrillMatrix( "non-plated", std::make_pair( F_Cu, B_Cu ) );
321 }
322
323 for( const auto& [layer_pair, vec] : drill_layers )
324 {
325 if( layer_pair != std::make_pair( F_Cu, B_Cu ) ) // pad has initialized above
326 InitDrillMatrix( "plated", layer_pair ); // for via
327 }
328}
329
330
332{
333 MATRIX_LAYER matrix( m_row++, "COMP_+_TOP" );
334 matrix.m_type = ODB_TYPE::COMPONENT;
335 matrix.m_context = ODB_CONTEXT::BOARD;
336
337 m_matrixLayers.push_back( matrix );
338 m_plugin->GetLayerNameList().emplace_back(
339 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
340
341 if( m_hasBotComp )
342 {
343 matrix.m_layerName = ODB::GenLegalEntityName( "COMP_+_BOT" );
344 matrix.m_rowNumber = m_row++;
345 m_matrixLayers.push_back( matrix );
346 m_plugin->GetLayerNameList().emplace_back(
347 std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
348 }
349}
350
351
353{
354 auto fileproxy = writer.CreateFileProxy( "matrix" );
355
356 ODB_TEXT_WRITER twriter( fileproxy.GetStream() );
357
358 for( const auto& [step_name, column] : m_matrixSteps )
359 {
360 const auto array_proxy = twriter.MakeArrayProxy( "STEP" );
361 twriter.WriteEquationLine( "COL", column );
362 twriter.WriteEquationLine( "NAME", step_name );
363 }
364
365 for( const auto& layer : m_matrixLayers )
366 {
367 const auto array_proxy = twriter.MakeArrayProxy( "LAYER" );
368 twriter.WriteEquationLine( "ROW", layer.m_rowNumber );
369 twriter.write_line_enum( "CONTEXT", layer.m_context );
370 twriter.write_line_enum( "TYPE", layer.m_type );
371
372 if( layer.m_addType.has_value() )
373 {
374 twriter.write_line_enum( "ADD_TYPE", layer.m_addType.value() );
375 }
376
377 twriter.WriteEquationLine( "NAME", layer.m_layerName.Upper() );
378 twriter.WriteEquationLine( "OLD_NAME", wxEmptyString );
379 twriter.write_line_enum( "POLARITY", layer.m_polarity );
380
381 if( layer.m_diType.has_value() )
382 {
383 twriter.write_line_enum( "DIELECTRIC_TYPE", layer.m_diType.value() );
384 }
385
386 twriter.WriteEquationLine( "DIELECTRIC_NAME", wxEmptyString );
387 twriter.WriteEquationLine( "CU_TOP", wxEmptyString );
388 twriter.WriteEquationLine( "CU_BOTTOM", wxEmptyString );
389 twriter.WriteEquationLine( "REF", wxEmptyString );
390
391 if( layer.m_span.has_value() )
392 {
393 twriter.WriteEquationLine( "START_NAME", layer.m_span->first.Upper() );
394 twriter.WriteEquationLine( "END_NAME", layer.m_span->second.Upper() );
395 }
396 else
397 {
398 twriter.WriteEquationLine( "START_NAME", wxEmptyString );
399 twriter.WriteEquationLine( "END_NAME", wxEmptyString );
400 }
401 twriter.WriteEquationLine( "COLOR", "0" );
402 }
403}
404
405
407 std::map<int, std::vector<BOARD_ITEM*>>& aMap,
408 const PCB_LAYER_ID& aLayerID, const wxString& aLayerName ) :
409 ODB_ENTITY_BASE( aBoard, aPlugin ), m_layerItems( aMap ), m_layerID( aLayerID ),
410 m_matrixLayerName( aLayerName )
411{
412 m_featuresMgr = std::make_unique<FEATURES_MANAGER>( aBoard, aPlugin, aLayerName );
413}
414
415
417{
418 if( m_matrixLayerName.Contains( "drill" ) )
419 {
422 return;
423 }
424
425 if( m_layerID != PCB_LAYER_ID::UNDEFINED_LAYER )
426 {
428 }
429}
430
432{
433 if( m_layerItems.empty() )
434 return;
435
436 const NETINFO_LIST& nets = m_board->GetNetInfo();
437
438 for( const NETINFO_ITEM* net : nets )
439 {
440 std::vector<BOARD_ITEM*>& vec = m_layerItems[net->GetNetCode()];
441
442 std::stable_sort( vec.begin(), vec.end(),
443 []( BOARD_ITEM* a, BOARD_ITEM* b )
444 {
445 if( a->GetParentFootprint() == b->GetParentFootprint() )
446 return a->Type() < b->Type();
447
448 return a->GetParentFootprint() < b->GetParentFootprint();
449 } );
450
451 if( vec.empty() )
452 continue;
453
454 m_featuresMgr->InitFeatureList( m_layerID, vec );
455 }
456}
457
458
460 const EDA_DATA::PACKAGE& aPkg )
461{
462 if( m_matrixLayerName == "COMP_+_BOT" )
463 {
464 if( !m_compBot.has_value() )
465 {
466 m_compBot.emplace();
467 }
468 return m_compBot.value().AddComponent( aFp, aPkg );
469 }
470 else
471 {
472 if( !m_compTop.has_value() )
473 {
474 m_compTop.emplace();
475 }
476
477 return m_compTop.value().AddComponent( aFp, aPkg );
478 }
479}
480
481
483{
484 std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& drill_layers =
486
487 std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& slot_holes =
489
490 if( !m_layerItems.empty() )
491 {
492 m_layerItems.clear();
493 }
494
496
497 bool is_npth_layer = false;
498 wxString plated_name = "plated";
499
500 if( m_matrixLayerName.Contains( "non-plated" ) )
501 {
502 is_npth_layer = true;
503 plated_name = "non-plated";
504 }
505
506
507 for( const auto& [layer_pair, vec] : slot_holes )
508 {
509 wxString dLayerName = wxString::Format( "drill_%s_%s-%s", plated_name,
510 m_board->GetLayerName( layer_pair.first ),
511 m_board->GetLayerName( layer_pair.second ) );
512
513 if( ODB::GenLegalEntityName( dLayerName ) == m_matrixLayerName )
514 {
515 for( BOARD_ITEM* item : vec )
516 {
517 if( item->Type() == PCB_PAD_T )
518 {
519 PAD* pad = static_cast<PAD*>( item );
520
521 if( ( is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH )
522 || ( !is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
523 {
524 continue;
525 }
526
527 m_tools.value().AddDrillTools(
528 pad->GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NON_PLATED",
530 std::min( pad->GetDrillSizeX(), pad->GetDrillSizeY() ) ) );
531
532 // for drill features
533 m_layerItems[pad->GetNetCode()].push_back( item );
534 }
535 }
536
537 break;
538 }
539 }
540
541 for( const auto& [layer_pair, vec] : drill_layers )
542 {
543 wxString dLayerName = wxString::Format( "drill_%s_%s-%s", plated_name,
544 m_board->GetLayerName( layer_pair.first ),
545 m_board->GetLayerName( layer_pair.second ) );
546
547 if( ODB::GenLegalEntityName( dLayerName ) == m_matrixLayerName )
548 {
549 for( BOARD_ITEM* item : vec )
550 {
551 if( item->Type() == PCB_VIA_T && !is_npth_layer )
552 {
553 PCB_VIA* via = static_cast<PCB_VIA*>( item );
554
555 m_tools.value().AddDrillTools( "VIA",
556 ODB::SymDouble2String( via->GetDrillValue() ) );
557
558 // for drill features
559 m_layerItems[via->GetNetCode()].push_back( item );
560 }
561 else if( item->Type() == PCB_PAD_T )
562 {
563 PAD* pad = static_cast<PAD*>( item );
564
565 if( ( is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH )
566 || ( !is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
567 {
568 continue;
569 }
570
571 m_tools.value().AddDrillTools(
572 pad->GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NON_PLATED",
573 ODB::SymDouble2String( pad->GetDrillSizeX() ) );
574
575 // for drill features
576 m_layerItems[pad->GetNetCode()].push_back( item );
577 }
578 }
579
580 break;
581 }
582 }
583}
584
585
587{
589
590 InitEdaData();
591
592 // Init Layer Entity Data
593 for( const auto& [layerName, layer_entity_ptr] : m_layerEntityMap )
594 {
595 layer_entity_ptr->InitEntityData();
596 }
597}
598
599
601{
602 GenAttrList( writer );
603
604 GenFeatures( writer );
605
606 if( m_compTop.has_value() || m_compBot.has_value() )
607 {
608 GenComponents( writer );
609 }
610
611 if( m_tools.has_value() )
612 {
613 GenTools( writer );
614 }
615}
616
617
619{
620 auto fileproxy = writer.CreateFileProxy( "components" );
621
622 if( m_compTop.has_value() )
623 {
624 m_compTop->Write( fileproxy.GetStream() );
625 }
626 else if( m_compBot.has_value() )
627 {
628 m_compBot->Write( fileproxy.GetStream() );
629 }
630}
631
632
634{
635 auto fileproxy = writer.CreateFileProxy( "features" );
636
637 m_featuresMgr->GenerateFeatureFile( fileproxy.GetStream() );
638}
639
640
642{
643 auto fileproxy = writer.CreateFileProxy( "attrlist" );
644}
645
646
648{
649 auto fileproxy = writer.CreateFileProxy( "tools" );
650
651 m_tools.value().GenerateFile( fileproxy.GetStream() );
652}
653
654
656{
657 //InitPackage
658 for( const FOOTPRINT* fp : m_board->Footprints() )
659 {
660 m_edaData.AddPackage( fp );
661 }
662
663 // for NET
664 const NETINFO_LIST& nets = m_board->GetNetInfo();
665
666 for( const NETINFO_ITEM* net : nets )
667 {
668 m_edaData.AddNET( net );
669 }
670
671 // for CMP
672 size_t j = 0;
673
674 for( const FOOTPRINT* fp : m_board->Footprints() )
675 {
676 wxString compName = ODB::GenLegalEntityName( "COMP_+_TOP" );
677 if( fp->IsFlipped() )
678 compName = ODB::GenLegalEntityName( "COMP_+_BOT" );
679
680 auto iter = m_layerEntityMap.find( compName );
681
682 if( iter == m_layerEntityMap.end() )
683 {
684 wxLogError( _( "Failed to add component data" ) );
685 return;
686 }
687
688 // ODBPP only need unique PACKAGE in PKG record in eda/data file.
689 // the PKG index can repeat to be ref in CMP record in component file.
690 std::shared_ptr<FOOTPRINT> fp_pkg = m_edaData.GetEdaFootprints().at( j );
691 ++j;
692
693 const EDA_DATA::PACKAGE& eda_pkg =
694 m_edaData.GetPackage( hash_fp_item( fp_pkg.get(), HASH_POS | REL_COORD ) );
695
696 ODB_COMPONENT& comp = iter->second->InitComponentData( fp, eda_pkg );
697
698 for( int i = 0; i < fp->Pads().size(); ++i )
699 {
700 PAD* pad = fp->Pads()[i];
701 auto& eda_net = m_edaData.GetNet( pad->GetNetCode() );
702
703 auto& subnet = eda_net.AddSubnet<EDA_DATA::SUB_NET_TOEPRINT>(
704 &m_edaData,
707 comp.m_index, comp.m_toeprints.size() );
708
709 m_plugin->GetPadSubnetMap().emplace( pad, &subnet );
710
711 const std::shared_ptr<EDA_DATA::PIN> pin = eda_pkg.GetEdaPkgPin( i );
712 const EDA_DATA::PIN& pin_ref = *pin;
713 auto& toep = comp.m_toeprints.emplace_back( pin_ref );
714
715 toep.m_net_num = eda_net.m_index;
716 toep.m_subnet_num = subnet.m_index;
717
718 toep.m_center = ODB::AddXY( pad->GetPosition() );
719
720 toep.m_rot = ODB::Double2String(
721 ( ANGLE_360 - pad->GetOrientation() ).Normalize().AsDegrees() );
722
723 if( pad->IsFlipped() )
724 toep.m_mirror = wxT( "M" );
725 else
726 toep.m_mirror = wxT( "N" );
727 }
728 }
729
730 for( PCB_TRACK* track : m_board->Tracks() )
731 {
732 auto& eda_net = m_edaData.GetNet( track->GetNetCode() );
733 EDA_DATA::SUB_NET* subnet = nullptr;
734
735 if( track->Type() == PCB_VIA_T )
736 subnet = &( eda_net.AddSubnet<EDA_DATA::SUB_NET_VIA>( &m_edaData ) );
737 else
738 subnet = &( eda_net.AddSubnet<EDA_DATA::SUB_NET_TRACE>( &m_edaData ) );
739
740 m_plugin->GetViaTraceSubnetMap().emplace( track, subnet );
741 }
742
743 for( ZONE* zone : m_board->Zones() )
744 {
745 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
746 {
747 auto& eda_net = m_edaData.GetNet( zone->GetNetCode() );
748 auto& subnet = eda_net.AddSubnet<EDA_DATA::SUB_NET_PLANE>(
751 m_plugin->GetPlaneSubnetMap().emplace( std::piecewise_construct,
752 std::forward_as_tuple( layer, zone ),
753 std::forward_as_tuple( &subnet ) );
754 }
755 }
756}
757
758
760{
761 wxString step_root = writer.GetCurrentPath();
762
763 writer.CreateEntityDirectory( step_root, "layers" );
764 GenerateLayerFiles( writer );
765
766 writer.CreateEntityDirectory( step_root, "eda" );
767 GenerateEdaFiles( writer );
768
769 writer.CreateEntityDirectory( step_root, "netlists/cadnet" );
770 GenerateNetlistsFiles( writer );
771
772 writer.SetCurrentPath( step_root );
773 GenerateProfileFile( writer );
774
775 GenerateStepHeaderFile( writer );
776
777 //TODO: system attributes
778 // GenerateAttrListFile( writer );
779}
780
781
783{
784 auto fileproxy = writer.CreateFileProxy( "profile" );
785
786 m_profile = std::make_unique<FEATURES_MANAGER>( m_board, m_plugin, wxEmptyString );
787
788 SHAPE_POLY_SET board_outline;
789
790 if( !m_board->GetBoardPolygonOutlines( board_outline ) )
791 {
792 wxLogError( "Failed to get board outline" );
793 }
794
795 if( !m_profile->AddContour( board_outline, 0 ) )
796 {
797 wxLogError( "Failed to add polygon to profile" );
798 }
799
800 m_profile->GenerateProfileFeatures( fileproxy.GetStream() );
801}
802
803
805{
806 auto fileproxy = writer.CreateFileProxy( "stephdr" );
807
808 m_stephdr = {
810 { "X_DATUM", "0" },
811 { "Y_DATUM", "0" },
812 { "X_ORIGIN", "0" },
813 { "Y_ORIGIN", "0" },
814 { "TOP_ACTIVE", "0" },
815 { "BOTTOM_ACTIVE", "0" },
816 { "RIGHT_ACTIVE", "0" },
817 { "LEFT_ACTIVE", "0" },
818 { "AFFECTING_BOM", "" },
819 { "AFFECTING_BOM_CHANGED", "0" },
820 };
821
822 ODB_TEXT_WRITER twriter( fileproxy.GetStream() );
823
824 for( const auto& [key, value] : m_stephdr )
825 {
826 twriter.WriteEquationLine( key, value );
827 }
828}
829
830
832{
833 wxString layers_root = writer.GetCurrentPath();
834
835 for( auto& [layerName, layerEntity] : m_layerEntityMap )
836 {
837 writer.CreateEntityDirectory( layers_root, layerName );
838
839 layerEntity->GenerateFiles( writer );
840 }
841}
842
843
845{
846 auto fileproxy = writer.CreateFileProxy( "data" );
847
848 m_edaData.Write( fileproxy.GetStream() );
849}
850
851
853{
854 auto fileproxy = writer.CreateFileProxy( "netlist" );
855
856 m_netlist.Write( fileproxy.GetStream() );
857}
858
859
861{
862 try
863 {
864 writer.CreateEntityDirectory( writer.GetRootPath(), "steps" );
866 return true;
867 }
868 catch( const std::exception& e )
869 {
870 std::cerr << e.what() << std::endl;
871 return false;
872 }
873}
874
875
877{
878 LSEQ layers = m_board->GetEnabledLayers().Seq();
879 const NETINFO_LIST& nets = m_board->GetNetInfo();
880
881 // To avoid the overhead of repeatedly cycling through the layers and nets,
882 // we pre-sort the board items into a map of layer -> net -> items
883 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>>& elements =
885
886 std::for_each( m_board->Tracks().begin(), m_board->Tracks().end(),
887 [&layers, &elements]( PCB_TRACK* aTrack )
888 {
889 if( aTrack->Type() == PCB_VIA_T )
890 {
891 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
892
893 for( PCB_LAYER_ID layer : layers )
894 {
895 if( via->FlashLayer( layer ) )
896 elements[layer][via->GetNetCode()].push_back( via );
897 }
898 }
899 else
900 {
901 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
902 }
903 } );
904
905 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
906 [&elements]( ZONE* zone )
907 {
908 LSEQ zone_layers = zone->GetLayerSet().Seq();
909
910 for( PCB_LAYER_ID layer : zone_layers )
911 {
912 elements[layer][zone->GetNetCode()].push_back( zone );
913 }
914 } );
915
916 for( BOARD_ITEM* item : m_board->Drawings() )
917 {
918 if( BOARD_CONNECTED_ITEM* conn_it = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
919 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
920 else
921 elements[item->GetLayer()][0].push_back( item );
922 }
923
924 for( FOOTPRINT* fp : m_board->Footprints() )
925 {
926 for( PCB_FIELD* field : fp->GetFields() )
927 elements[field->GetLayer()][0].push_back( field );
928
929 for( BOARD_ITEM* item : fp->GraphicalItems() )
930 elements[item->GetLayer()][0].push_back( item );
931
932 for( PAD* pad : fp->Pads() )
933 {
934 LSEQ pad_layers = pad->GetLayerSet().Seq();
935 VECTOR2I margin;
936
937 for( PCB_LAYER_ID layer : pad_layers )
938 {
939 bool onCopperLayer = ( LSET::AllCuMask() & LSET( { layer } ) ).any();
940 bool onSolderMaskLayer = ( LSET( { F_Mask, B_Mask } ) & LSET( { layer } ) ).any();
941 bool onSolderPasteLayer =
942 ( LSET( { F_Paste, B_Paste } ) & LSET( { layer } ) ).any();
943
944 if( onSolderMaskLayer )
945 margin.x = margin.y = pad->GetSolderMaskExpansion( PADSTACK::ALL_LAYERS );
946
947 if( onSolderPasteLayer )
948 margin = pad->GetSolderPasteMargin( PADSTACK::ALL_LAYERS );
949
950 VECTOR2I padPlotsSize = pad->GetSize( PADSTACK::ALL_LAYERS ) + margin * 2;
951
952 if( onCopperLayer && !pad->IsOnCopperLayer() )
953 continue;
954
955 if( onCopperLayer && !pad->FlashLayer( layer ) )
956 continue;
957
958 if( pad->GetShape( PADSTACK::ALL_LAYERS ) != PAD_SHAPE::CUSTOM
959 && ( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 ) )
960 continue;
961
962 elements[layer][pad->GetNetCode()].push_back( pad );
963 }
964 }
965 }
966
967 for( const auto& [layerID, layerName] : m_plugin->GetLayerNameList() )
968 {
969 std::shared_ptr<ODB_LAYER_ENTITY> layer_entity_ptr = std::make_shared<ODB_LAYER_ENTITY>(
970 m_board, m_plugin, elements[layerID], layerID, layerName );
971
972 m_layerEntityMap.emplace( layerName, layer_entity_ptr );
973 }
974}
@ BS_ITEM_TYPE_DIELECTRIC
Definition: board_stackup.h:46
wxString GetMajorMinorPatchVersion()
Get the major, minor and patch version in a string major.minor.patch This is extracted by CMake from ...
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.
Definition: board_stackup.h:96
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:290
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false, bool aIncludeNPTHAsOutlines=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:2491
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:871
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:773
const ZONES & Zones() const
Definition: board.h:335
const FOOTPRINTS & Footprints() const
Definition: board.h:331
const TRACKS & Tracks() const
Definition: board.h:329
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:577
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:890
T & AddSubnet(Args &&... args)
Definition: odb_eda_data.h:160
const std::shared_ptr< PIN > GetEdaPkgPin(size_t aPadIndex) const
Definition: odb_eda_data.h:241
NET & GetNet(size_t aNetcode)
Definition: odb_eda_data.h:172
const PACKAGE & GetPackage(size_t aHash) const
Definition: odb_eda_data.h:253
void AddNET(const NETINFO_ITEM *aNet)
void AddPackage(const FOOTPRINT *aFp)
void Write(std::ostream &ost) const
std::vector< std::shared_ptr< FOOTPRINT > > GetEdaFootprints() const
Definition: odb_eda_data.h:40
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: lseq.h:47
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:36
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:410
Handle the data for a net.
Definition: netinfo.h:56
Container for NETINFO_ITEM elements, which are the nets.
Definition: netinfo.h:346
const size_t m_index
! CMP index number on board to be used in SNT(TOP), 0~n-1
Definition: odb_component.h:53
std::list< TOEPRINT > m_toeprints
Definition: odb_component.h:93
virtual bool CreateDirectiryTree(ODB_TREE_WRITER &writer)
Definition: odb_entity.cpp:62
virtual std::string GetEntityName()=0
BOARD * m_board
Definition: odb_entity.h:59
PCB_IO_ODBPP * m_plugin
Definition: odb_entity.h:61
void GenFeatures(ODB_TREE_WRITER &writer)
Definition: odb_entity.cpp:633
PCB_LAYER_ID m_layerID
Definition: odb_entity.h:204
void InitFeatureData()
Definition: odb_entity.cpp:431
void GenComponents(ODB_TREE_WRITER &writer)
Definition: odb_entity.cpp:618
wxString m_matrixLayerName
Definition: odb_entity.h:205
std::optional< COMPONENTS_MANAGER > m_compTop
Definition: odb_entity.h:208
virtual void GenerateFiles(ODB_TREE_WRITER &writer) override
Definition: odb_entity.cpp:600
std::optional< COMPONENTS_MANAGER > m_compBot
Definition: odb_entity.h:209
std::optional< ODB_DRILL_TOOLS > m_tools
Definition: odb_entity.h:207
void GenTools(ODB_TREE_WRITER &writer)
Definition: odb_entity.cpp:647
std::map< int, std::vector< BOARD_ITEM * > > m_layerItems
Definition: odb_entity.h:203
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)
Definition: odb_entity.cpp:406
ODB_COMPONENT & InitComponentData(const FOOTPRINT *aFp, const EDA_DATA::PACKAGE &aPkg)
Definition: odb_entity.cpp:459
virtual void InitEntityData() override
Definition: odb_entity.cpp:416
void GenAttrList(ODB_TREE_WRITER &writer)
Definition: odb_entity.cpp:641
std::unique_ptr< FEATURES_MANAGER > m_featuresMgr
Definition: odb_entity.h:210
void AddStep(const wxString &aStepName)
Definition: odb_entity.cpp:104
void AddCOMPMatrixLayer()
Definition: odb_entity.cpp:331
unsigned int m_col
Definition: odb_entity.h:111
void InitMatrixLayerData()
Definition: odb_entity.cpp:118
std::vector< MATRIX_LAYER > m_matrixLayers
Definition: odb_entity.h:109
void AddMatrixLayerField(MATRIX_LAYER &aMLayer, PCB_LAYER_ID aLayer)
Definition: odb_entity.cpp:189
virtual void GenerateFiles(ODB_TREE_WRITER &writer) override
Definition: odb_entity.cpp:352
std::map< wxString, unsigned int > m_matrixSteps
Definition: odb_entity.h:108
unsigned int m_row
Definition: odb_entity.h:110
void AddDrillMatrixLayer()
Definition: odb_entity.cpp:249
virtual void InitEntityData() override
Definition: odb_entity.cpp:110
std::map< wxString, wxString > m_info
Definition: odb_entity.h:128
virtual void GenerateFiles(ODB_TREE_WRITER &writer) override
Definition: odb_entity.cpp:91
void Write(std::ostream &aStream)
virtual std::string GetEntityName() override
Definition: odb_entity.h:144
std::unordered_map< wxString, wxString > m_stephdr
Definition: odb_entity.h:171
void GenerateProfileFile(ODB_TREE_WRITER &writer)
Definition: odb_entity.cpp:782
EDA_DATA m_edaData
Definition: odb_entity.h:170
void GenerateStepHeaderFile(ODB_TREE_WRITER &writer)
Definition: odb_entity.cpp:804
void GenerateEdaFiles(ODB_TREE_WRITER &writer)
Definition: odb_entity.cpp:844
virtual void InitEntityData() override
Definition: odb_entity.cpp:586
void GenerateLayerFiles(ODB_TREE_WRITER &writer)
Definition: odb_entity.cpp:831
std::map< wxString, std::shared_ptr< ODB_LAYER_ENTITY > > m_layerEntityMap
Definition: odb_entity.h:167
ODB_NET_LIST m_netlist
Definition: odb_entity.h:172
std::unique_ptr< FEATURES_MANAGER > m_profile
Definition: odb_entity.h:168
void GenerateNetlistsFiles(ODB_TREE_WRITER &writer)
Definition: odb_entity.cpp:852
void MakeLayerEntity()
Definition: odb_entity.cpp:876
virtual bool CreateDirectiryTree(ODB_TREE_WRITER &writer) override
Definition: odb_entity.cpp:860
virtual void GenerateFiles(ODB_TREE_WRITER &writer) override
Definition: odb_entity.cpp:759
void WriteEquationLine(const std::string &var, int value)
Definition: odb_util.cpp:276
ARRAY_PROXY MakeArrayProxy(const std::string &aStr)
Definition: odb_util.h:299
void write_line_enum(const std::string &var, const T &value)
Definition: odb_util.h:273
const wxString GetRootPath() const
Definition: odb_util.h:254
void CreateEntityDirectory(const wxString &aPareDir, const wxString &aSubDir=wxEmptyString)
Definition: odb_util.cpp:197
ODB_FILE_WRITER CreateFileProxy(const wxString &aFileName)
Definition: odb_util.h:241
void SetCurrentPath(const wxString &aDir)
Definition: odb_util.h:250
const wxString GetCurrentPath() const
Definition: odb_util.h:248
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition: padstack.h:138
Definition: pad.h:54
std::map< std::pair< PCB_LAYER_ID, ZONE * >, EDA_DATA::SUB_NET_PLANE * > & GetPlaneSubnetMap()
Definition: pcb_io_odbpp.h:119
std::map< PCB_TRACK *, EDA_DATA::SUB_NET * > & GetViaTraceSubnetMap()
Definition: pcb_io_odbpp.h:124
std::vector< std::pair< PCB_LAYER_ID, wxString > > & GetLayerNameList()
Definition: pcb_io_odbpp.h:87
std::map< std::pair< PCB_LAYER_ID, PCB_LAYER_ID >, std::vector< BOARD_ITEM * > > & GetSlotHolesMap()
Definition: pcb_io_odbpp.h:109
std::map< const PAD *, EDA_DATA::SUB_NET_TOEPRINT * > & GetPadSubnetMap()
Definition: pcb_io_odbpp.h:114
std::map< PCB_LAYER_ID, std::map< int, std::vector< BOARD_ITEM * > > > & GetLayerElementsMap()
Definition: pcb_io_odbpp.h:92
static std::string m_unitsStr
Definition: pcb_io_odbpp.h:144
std::map< std::pair< PCB_LAYER_ID, PCB_LAYER_ID >, std::vector< BOARD_ITEM * > > & GetDrillLayerItemsMap()
Definition: pcb_io_odbpp.h:103
Represent a set of closed polygons.
Handle a list of polygons defining a copper zone.
Definition: zone.h:73
#define _(s)
static constexpr EDA_ANGLE ANGLE_360
Definition: eda_angle.h:407
size_t hash_fp_item(const EDA_ITEM *aItem, int aFlags)
Calculate hash of an EDA_ITEM.
Definition: hash_eda.cpp:54
@ HASH_POS
use coordinates relative to the parent object
Definition: hash_eda.h:43
@ REL_COORD
use coordinates relative to the shape position
Definition: hash_eda.h:46
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:532
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ User_8
Definition: layer_ids.h:131
@ F_CrtYd
Definition: layer_ids.h:116
@ B_Adhes
Definition: layer_ids.h:103
@ 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
@ F_Adhes
Definition: layer_ids.h:102
@ B_Mask
Definition: layer_ids.h:98
@ B_Cu
Definition: layer_ids.h:65
@ User_5
Definition: layer_ids.h:128
@ Eco1_User
Definition: layer_ids.h:109
@ F_Mask
Definition: layer_ids.h:97
@ B_Paste
Definition: layer_ids.h:105
@ User_9
Definition: layer_ids.h:132
@ 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
@ Eco2_User
Definition: layer_ids.h:110
@ User_3
Definition: layer_ids.h:126
@ User_1
Definition: layer_ids.h:124
@ B_SilkS
Definition: layer_ids.h:101
@ User_4
Definition: layer_ids.h:127
@ User_2
Definition: layer_ids.h:125
@ 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:510
std::pair< wxString, wxString > AddXY(const VECTOR2I &aVec)
Definition: odb_util.cpp:158
wxString GenLegalEntityName(const wxString &aStr)
Definition: odb_util.cpp:81
wxString Double2String(double aVal)
Definition: odb_util.cpp:118
wxString SymDouble2String(double aVal)
Definition: odb_util.cpp:146
#define ODB_JOB_NAME
Definition: odb_defines.h:27
#define ODB_UNITS
Definition: odb_defines.h:28
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