KiCad PCB EDA Suite
Loading...
Searching...
No Matches
cadstar_pcb_archive_parser.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) 2020 Roberto Fernandez Bautista <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
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
25
26#include <base_units.h>
28#include <macros.h>
29#include <progress_reporter.h>
30#include <wx/translation.h>
31
32
34{
36 m_progressReporter->BeginPhase( 0 ); // Read file
37
38 m_rootNode = LoadArchiveFile( Filename, wxT( "CADSTARPCB" ), m_progressReporter );
39
41 {
42 m_progressReporter->BeginPhase( 1 ); // Parse File
43
44 std::vector<wxString> subNodeChildrenToCount = { wxT( "LIBRARY" ), wxT( "PARTS" ),
45 wxT( "LAYOUT" ) };
46
47 long numOfSteps = GetNumberOfStepsForReporting( m_rootNode, subNodeChildrenToCount );
48 m_progressReporter->SetMaxProgress( numOfSteps );
49 }
50
51 m_context.CheckPointCallback = [&](){ checkPoint(); };
52
53 XNODE* cNode = m_rootNode->GetChildren();
54
55 if( !cNode )
56 THROW_MISSING_NODE_IO_ERROR( wxT( "HEADER" ), wxT( "CADSTARPCB" ) );
57
58 for( ; cNode; cNode = cNode->GetNext() )
59 {
60 if( cNode->GetName() == wxT( "HEADER" ) )
61 {
62 Header.Parse( cNode, &m_context );
63
64 switch( Header.Resolution )
65 {
68 break;
69
70 default:
71 wxASSERT_MSG( true, wxT( "Unknown File Resolution" ) );
72 break;
73 }
74
75 if( aLibrary && Header.Format.Type != wxT( "LIBRARY" ) )
76 {
77 THROW_IO_ERROR( wxT( "The selected file is not a valid CADSTAR library file." ) );
78 }
79 else if( !aLibrary && Header.Format.Type != wxT( "LAYOUT" ) )
80 {
81 if( Header.Format.Type == wxT( "LIBRARY" ) )
82 {
84 wxT( "The selected file is a CADSTAR library file (as opposed "
85 "to a layout file). You can import this library by adding it "
86 "to the library table." ) );
87 }
88 else
89 {
90 THROW_IO_ERROR( wxT( "The selected file is an unknown CADSTAR format so "
91 "cannot be imported into KiCad." ) );
92 }
93 }
94 }
95 else if( cNode->GetName() == wxT( "ASSIGNMENTS" ) )
96 {
97 Assignments.Parse( cNode, &m_context );
98 }
99 else if( cNode->GetName() == wxT( "LIBRARY" ) )
100 {
101 Library.Parse( cNode, &m_context );
102 }
103 else if( cNode->GetName() == wxT( "DEFAULTS" ) )
104 {
105 // No design information here (no need to parse)
106 // Only contains CADSTAR configuration data such as default shapes, text and units
107 // In future some of this could be converted to KiCad but limited value
108 }
109 else if( cNode->GetName() == wxT( "PARTS" ) )
110 {
111 Parts.Parse( cNode, &m_context );
112 }
113 else if( cNode->GetName() == wxT( "LAYOUT" ) )
114 {
115 Layout.Parse( cNode, &m_context );
116 }
117 else if( cNode->GetName() == wxT( "DISPLAY" ) )
118 {
119 // No design information here (no need to parse)
120 // Contains CADSTAR Display settings such as layer/element colours and visibility.
121 // In the future these settings could be converted to KiCad
122 }
123 else
124 {
125 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "[root]" ) );
126 }
127
128 checkPoint();
129 }
130
131 delete m_rootNode;
132 m_rootNode = nullptr;
133}
134
135
137{
138 wxASSERT( aNode->GetName() == wxT( "ASSIGNMENTS" ) );
139
140 XNODE* cNode = aNode->GetChildren();
141
142 if( !cNode )
143 THROW_MISSING_NODE_IO_ERROR( wxT( "TECHNOLOGY" ), wxT( "ASSIGNMENTS" ) );
144
145 for( ; cNode; cNode = cNode->GetNext() )
146 {
147 if( cNode->GetName() == wxT( "LAYERDEFS" ) )
148 Layerdefs.Parse( cNode, aContext );
149 else if( cNode->GetName() == wxT( "CODEDEFS" ) )
150 Codedefs.Parse( cNode, aContext );
151 else if( cNode->GetName() == wxT( "TECHNOLOGY" ) )
152 Technology.Parse( cNode, aContext );
153 else if( cNode->GetName() == wxT( "GRIDS" ) )
154 Grids.Parse( cNode, aContext );
155 else if( cNode->GetName() == wxT( "NETCLASSEDITATTRIBSETTINGS" ) )
157 else if( cNode->GetName() == wxT( "SPCCLASSEDITATTRIBSETTINGS" ) )
159 else
160 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
161 }
162}
163
164
166{
167 wxASSERT( aNode->GetName() == wxT( "LAYERDEFS" ) );
168
169 wxXmlAttribute* xmlAttribute = nullptr;
170
171 XNODE* cNode = aNode->GetChildren();
172
173 if( !cNode )
174 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "LAYERSTACK" ), wxT( "LAYERDEFS" ) );
175
176 for( ; cNode; cNode = cNode->GetNext() )
177 {
178 wxString nodeName = cNode->GetName();
179
180 if( nodeName == wxT( "LAYERSTACK" ) )
181 {
182 xmlAttribute = cNode->GetAttributes();
183
184 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
185 {
186 if( !IsValidAttribute( xmlAttribute ) )
187 continue;
188 else
189 LayerStack.push_back( (LAYER_ID) xmlAttribute->GetValue() );
190 }
191
192 CheckNoChildNodes( cNode );
193 }
194 else if( nodeName == wxT( "MATERIAL" ) )
195 {
196 MATERIAL material;
197 material.Parse( cNode, aContext );
198 Materials.insert( std::make_pair( material.ID, material ) );
199 }
200 else if( nodeName == wxT( "LAYER" ) )
201 {
202 LAYER layer;
203 layer.Parse( cNode, aContext );
204 Layers.insert( std::make_pair( layer.ID, layer ) );
205 }
206 else if( nodeName == wxT( "SWAPPAIR" ) )
207 {
208 LAYER_ID layerId = (LAYER_ID) GetXmlAttributeIDString( cNode, 0 );
209 LAYER_ID swapLayerId = (LAYER_ID) GetXmlAttributeIDString( cNode, 1 );
210
211 Layers[layerId].SwapLayerID = swapLayerId;
212 }
213 else
214 {
215 THROW_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
216 }
217 }
218}
219
220
222{
223 wxASSERT( aNode->GetName() == wxT( "RULESET" ) );
224
225 ID = GetXmlAttributeIDString( aNode, 0 );
226 Name = GetXmlAttributeIDString( aNode, 1 );
227
228 XNODE* cNode = aNode->GetChildren();
229
230 for( ; cNode; cNode = cNode->GetNext() )
231 {
232 wxString nodeName = cNode->GetName();
233
234 if( nodeName == wxT( "ROUCODEREF" ) )
235 {
237 }
238 else if( nodeName == wxT( "VIACODEREF" ) )
239 {
241 }
242 else if( nodeName == wxT( "SPACINGCODE" ) )
243 {
244 SPACINGCODE spacingcode;
245 spacingcode.Parse( cNode, aContext );
246 SpacingCodes.insert( std::make_pair( spacingcode.ID, spacingcode ) );
247 }
248 else
249 {
250 THROW_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
251 }
252 }
253}
254
255
257{
258 wxASSERT( aNode->GetName() == wxT( "CODEDEFS" ) );
259
260 XNODE* cNode = aNode->GetChildren();
261
262 for( ; cNode; cNode = cNode->GetNext() )
263 {
264 wxString nodeName = cNode->GetName();
265
266 if( ParseSubNode( cNode, aContext ) ) // in CADSTAR_ARCHIVE_PARSER::CODEDEFS
267 {
268 }
269 else if( nodeName == wxT( "COPPERCODE" ) )
270 {
271 COPPERCODE coppercode;
272 coppercode.Parse( cNode, aContext );
273 CopperCodes.insert( std::make_pair( coppercode.ID, coppercode ) );
274 }
275 else if( nodeName == wxT( "SPACINGCODE" ) )
276 {
277 SPACINGCODE spacingcode;
278 spacingcode.Parse( cNode, aContext );
279 SpacingCodes.insert( std::make_pair( spacingcode.ID, spacingcode ) );
280 }
281 else if( nodeName == wxT( "RULESET" ) )
282 {
283 RULESET ruleset;
284 ruleset.Parse( cNode, aContext );
285 Rulesets.insert( std::make_pair( ruleset.ID, ruleset ) );
286 }
287 else if( nodeName == wxT( "PADCODE" ) )
288 {
289 PADCODE padcode;
290 padcode.Parse( cNode, aContext );
291 PadCodes.insert( std::make_pair( padcode.ID, padcode ) );
292 }
293 else if( nodeName == wxT( "VIACODE" ) )
294 {
295 VIACODE viacode;
296 viacode.Parse( cNode, aContext );
297 ViaCodes.insert( std::make_pair( viacode.ID, viacode ) );
298 }
299 else if( nodeName == wxT( "LAYERPAIR" ) )
300 {
301 LAYERPAIR layerpair;
302 layerpair.Parse( cNode, aContext );
303 LayerPairs.insert( std::make_pair( layerpair.ID, layerpair ) );
304 }
305 else if( nodeName == wxT( "SPCCLASSSPACE" ) )
306 {
307 SPCCLASSSPACE spcclassspace;
308 spcclassspace.Parse( cNode, aContext );
309 SpacingClasses.push_back( spcclassspace );
310 }
311 else
312 {
313 THROW_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
314 }
315 }
316}
317
318
320{
321 wxASSERT( aNode->GetName() == wxT( "MATERIAL" ) );
322
323 ID = GetXmlAttributeIDString( aNode, 0 );
324 Name = GetXmlAttributeIDString( aNode, 1 );
325
326 wxString sType = GetXmlAttributeIDString( aNode, 2 );
327
328 if( sType == wxT( "CONSTRUCTION" ) )
329 {
331 }
332 else if( sType == wxT( "ELECTRICAL" ) )
333 {
335 }
336 else if( sType == wxT( "NONELEC" ) )
337 {
339 }
340 else
341 {
342 THROW_UNKNOWN_PARAMETER_IO_ERROR( sType, wxString::Format( wxT( "MATERIAL %s" ), Name ) );
343 }
344
345 XNODE* iNode = aNode->GetChildren();
346
347 if( !iNode )
348 {
349 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "RESISTIVITY" ),
350 wxString::Format( wxT( "MATERIAL %s" ), Name ) );
351 }
352
353 for( ; iNode; iNode = iNode->GetNext() )
354 {
355 wxString nodeName = iNode->GetName();
356
357 if( nodeName == wxT( "RELPERMIT" ) )
358 {
359 ParseChildEValue( iNode, aContext, Permittivity );
360 }
361 else if( nodeName == wxT( "LOSSTANGENT" ) )
362 {
363 ParseChildEValue( iNode, aContext, LossTangent );
364 }
365 else if( nodeName == wxT( "RESISTIVITY" ) )
366 {
367 ParseChildEValue( iNode, aContext, Resistivity );
368 }
369 else
370 {
371 THROW_UNKNOWN_NODE_IO_ERROR( nodeName, wxString::Format( wxT( "MATERIAL %s" ), Name ) );
372 }
373 }
374}
375
376
378{
379 wxASSERT( aNode->GetName() == wxT( "LAYER" ) );
380
381 ID = GetXmlAttributeIDString( aNode, 0 );
382 Name = GetXmlAttributeIDString( aNode, 1 );
383
384 XNODE* cNode = aNode->GetChildren();
385 auto processLayerMaterialDetails = [&]() {
386 XNODE* tempNode = cNode->GetChildren();
387 for( ; tempNode; tempNode = tempNode->GetNext() )
388 {
389 wxString tempNodeName = tempNode->GetName();
390
391 if( tempNodeName == wxT( "MAKE" ) || tempNodeName == wxT( "LAYERHEIGHT" ) )
392 {
393 if( tempNodeName == wxT( "LAYERHEIGHT" ) )
394 {
395 Thickness = GetXmlAttributeIDLong( tempNode, 0 );
396 }
397 else
398 {
399 MaterialId = GetXmlAttributeIDString( tempNode, 0 );
400 Thickness = GetXmlAttributeIDLong( tempNode, 1 );
401 }
402
403 XNODE* childOfTempNode = tempNode->GetChildren();
404
405 if( childOfTempNode )
406 {
407 if( childOfTempNode->GetName() == wxT( "EMBEDS" ) )
408 {
409 wxString embedsValue = GetXmlAttributeIDString( childOfTempNode, 0 );
410
411 if( embedsValue == wxT( "UPWARDS" ) )
412 {
414 }
415 else if( embedsValue == wxT( "DOWNWARDS" ) )
416 {
418 }
419 else
420 {
422 wxString::Format( wxT( "LAYER %s -> EMBEDS" ),
423 Name ) );
424 }
425 }
426 else
427 {
428 THROW_UNKNOWN_NODE_IO_ERROR( childOfTempNode->GetName(),
429 wxString::Format( wxT( "LAYER %s->MAKE" ),
430 Name ) );
431 }
432 }
433 }
434 else if( tempNodeName == wxT( "BIAS" ) )
435 {
436 wxString bias = GetXmlAttributeIDString( tempNode, 0 );
437
438 if( bias == wxT( "X_BIASED" ) )
439 {
441 }
442 else if( bias == wxT( "Y_BIASED" ) )
443 {
445 }
446 else if( bias == wxT( "ANTITRACK" ) )
447 {
449 }
450 else if( bias == wxT( "OBSTACLE" ) )
451 {
453 }
454 else if( bias == wxT( "UNBIASED" ) )
455 {
457 }
458 else
459 {
461 wxString::Format( wxT( "LAYER %s -> BIAS" ),
462 Name ) );
463 }
464 }
465 else
466 {
467 THROW_UNKNOWN_NODE_IO_ERROR( tempNodeName, wxString::Format( wxT( "LAYER %s" ),
468 Name ) );
469 }
470 }
471 };
472
473 for( ; cNode; cNode = cNode->GetNext() )
474 {
475 wxString cNodeName = cNode->GetName();
476
477 if( cNodeName == wxT( "ALLDOC" ) )
478 {
480 }
481 else if( cNodeName == wxT( "ALLELEC" ) )
482 {
484 }
485 else if( cNodeName == wxT( "ALLLAYER" ) )
486 {
488 }
489 else if( cNodeName == wxT( "ASSCOMPCOPP" ) )
490 {
492 }
493 else if( cNodeName == wxT( "JUMPERLAYER" ) )
494 {
496 }
497 else if( cNodeName == wxT( "NOLAYER" ) )
498 {
500 }
501 else if( cNodeName == wxT( "POWER" ) )
502 {
505 processLayerMaterialDetails();
506 }
507 else if( cNodeName == wxT( "DOC" ) )
508 {
510 }
511 else if( cNodeName == wxT( "CONSTRUCTION" ) )
512 {
514 processLayerMaterialDetails();
515 }
516 else if( cNodeName == wxT( "ELEC" ) )
517 {
520 processLayerMaterialDetails();
521 }
522 else if( cNodeName == wxT( "NONELEC" ) )
523 {
526 processLayerMaterialDetails();
527 }
528 else if( cNodeName == wxT( "DESCRIPTION" ) )
529 {
531 }
532 else if( cNodeName == wxT( "REFPLANE" ) )
533 {
534 ReferencePlane = true;
535 }
536 else if( cNodeName == wxT( "VLAYER" ) )
537 {
538 VariantLayer = true;
539 }
540 else if( cNodeName == wxT( "LASUBTYP" ) )
541 {
542 //Process subtype
543 wxString sSubType = GetXmlAttributeIDString( cNode, 0 );
544
545 if( sSubType == wxT( "LAYERSUBTYPE_ASSEMBLY" ) )
546 {
548 }
549 else if( sSubType == wxT( "LAYERSUBTYPE_PASTE" ) )
550 {
552 }
553 else if( sSubType == wxT( "LAYERSUBTYPE_PLACEMENT" ) )
554 {
556 }
557 else if( sSubType == wxT( "LAYERSUBTYPE_SILKSCREEN" ) )
558 {
560 }
561 else if( sSubType == wxT( "LAYERSUBTYPE_SOLDERRESIST" ) )
562 {
564 }
565 else if( sSubType == wxT( "LAYERSUBTYPE_CLEARANCE" ) )
566 {
568 }
569 else if( sSubType == wxT( "LAYERSUBTYPE_ROUT" ) )
570 {
572 }
573 else
574 {
575 THROW_UNKNOWN_PARAMETER_IO_ERROR( sSubType, wxString::Format( wxT( "LAYER %s %s" ),
576 Name, cNodeName ) );
577 }
578 }
579 else
580 {
581 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxString::Format( wxT( "LAYER %s" ), Name ) );
582 }
583 }
584}
585
586
588{
589 wxASSERT( aNode->GetName() == wxT( "COPREASSIGN" ) );
590
591 LayerID = GetXmlAttributeIDString( aNode, 0 );
592
594}
595
596
598{
599 wxASSERT( aNode->GetName() == wxT( "COPPERCODE" ) );
600
601 ID = GetXmlAttributeIDString( aNode, 0 );
602 Name = GetXmlAttributeIDString( aNode, 1 );
603
605
606 XNODE* cNode = aNode->GetChildren();
607
608 for( ; cNode; cNode = cNode->GetNext() )
609 {
610 if( cNode->GetName() == wxT( "COPREASSIGN" ) )
611 {
613 reassign.Parse( cNode, aContext );
614 Reassigns.push_back( reassign );
615 }
616 else
617 {
618 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
619 }
620 }
621}
622
623
625 PARSER_CONTEXT* aContext )
626{
627 wxASSERT( aNode->GetName() == wxT( "SPACEREASSIGN" ) );
628
629 LayerID = GetXmlAttributeIDString( aNode, 0 );
630 Spacing = GetXmlAttributeIDLong( aNode, 1 );
631
632 CheckNoChildNodes( aNode );
633}
634
635
637{
638 wxASSERT( aNode->GetName() == wxT( "SPACINGCODE" ) );
639
640 ID = GetXmlAttributeIDString( aNode, 0 );
641 Spacing = GetXmlAttributeIDLong( aNode, 1 );
642
643 XNODE* cNode = aNode->GetChildren();
644
645 for( ; cNode; cNode = cNode->GetNext() )
646 {
647 wxString cNodeName = cNode->GetName();
648
649 if( cNodeName == wxT( "SPACEREASSIGN" ) )
650 {
651 REASSIGN reassign;
652 reassign.Parse( cNode, aContext );
653 Reassigns.push_back( reassign );
654 }
655 else
656 {
657 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
658 }
659 }
660}
661
662
664{
665 wxString aNodeName = aNode->GetName();
666
667 if( aNodeName == wxT( "ANNULUS" ) || aNodeName == wxT( "BULLET" ) || aNodeName == wxT( "ROUND" )
668 || aNodeName == wxT( "DIAMOND" ) || aNodeName == wxT( "FINGER" )
669 || aNodeName == wxT( "OCTAGON" ) || aNodeName == wxT( "RECTANGLE" )
670 || aNodeName == wxT( "ROUNDED" ) || aNodeName == wxT( "SQUARE" ) )
671 {
672 return true;
673 }
674 else
675 {
676 return false;
677 }
678}
679
680
682{
683 wxASSERT( IsPadShape( aNode ) );
684
685 wxString aNodeName = aNode->GetName();
686
687 if( aNodeName == wxT( "ANNULUS" ) )
689 else if( aNodeName == wxT( "BULLET" ) )
691 else if( aNodeName == wxT( "ROUND" ) )
693 else if( aNodeName == wxT( "DIAMOND" ) )
695 else if( aNodeName == wxT( "FINGER" ) )
697 else if( aNodeName == wxT( "OCTAGON" ) )
699 else if( aNodeName == wxT( "RECTANGLE" ) )
701 else if( aNodeName == wxT( "ROUNDED" ) )
703 else if( aNodeName == wxT( "SQUARE" ) )
705 else
706 wxASSERT( true );
707
708 switch( ShapeType )
709 {
711 Size = GetXmlAttributeIDLong( aNode, 0 );
713 break;
714
718
723 LeftLength = GetXmlAttributeIDLong( aNode, 1 );
725
729 if( aNode->GetChildren() )
730 {
731 if( aNode->GetChildren()->GetName() == wxT( "ORIENT" ) )
732 {
734 }
735 else
736 {
737 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
738 }
739
740 CheckNoNextNodes( aNode->GetChildren() );
741 }
743
745 Size = GetXmlAttributeIDLong( aNode, 0 );
746 break;
747 }
748}
749
750
752{
753 wxASSERT( aNode->GetName() == wxT( "PADREASSIGN" ) );
754
755 LayerID = GetXmlAttributeIDString( aNode, 0 );
756
758 Shape.Parse( aNode->GetChildren(), aContext );
759 else
760 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
761
762 CheckNoNextNodes( aNode->GetChildren() );
763}
764
765
767{
768 wxASSERT( aNode->GetName() == wxT( "PADCODE" ) );
769
770 ID = GetXmlAttributeIDString( aNode, 0 );
771 Name = GetXmlAttributeIDString( aNode, 1 );
772
773 XNODE* cNode = aNode->GetChildren();
774 wxString location = wxString::Format( wxT( "PADCODE -> %s" ), Name );
775
776 for( ; cNode; cNode = cNode->GetNext() )
777 {
778 wxString cNodeName = cNode->GetName();
779
780 if( CADSTAR_PAD_SHAPE::IsPadShape( cNode ) )
781 {
782 Shape.Parse( cNode, aContext );
783 }
784 else if( cNodeName == wxT( "CLEARANCE" ) )
785 {
787 }
788 else if( cNodeName == wxT( "RELIEFWIDTH" ) )
789 {
791 }
792 else if( cNodeName == wxT( "DRILL" ) )
793 {
795 XNODE* subNode = cNode->GetChildren();
796
797 for( ; subNode; subNode = subNode->GetNext() )
798 {
799 wxString subNodeName = subNode->GetName();
800
801 if( subNodeName == wxT( "NONPLATED" ) )
802 Plated = false;
803 else if( subNodeName == wxT( "OVERSIZE" ) )
804 DrillOversize = GetXmlAttributeIDLong( subNode, 0 );
805 else
806 THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
807 }
808 }
809 else if( cNodeName == wxT( "DRILLLENGTH" ) )
810 {
811 SlotLength = GetXmlAttributeIDLong( cNode, 0 );
812 }
813 else if( cNodeName == wxT( "DRILLORIENTATION" ) )
814 {
816 }
817 else if( cNodeName == wxT( "DRILLXOFFSET" ) )
818 {
820 }
821 else if( cNodeName == wxT( "DRILLYOFFSET" ) )
822 {
824 }
825 else if( cNodeName == wxT( "PADREASSIGN" ) )
826 {
827 PADREASSIGN reassign;
828 reassign.Parse( cNode, aContext );
829 Reassigns.insert( std::make_pair( reassign.LayerID, reassign.Shape ) );
830 }
831 else
832 {
834 }
835 }
836}
837
838
840{
841 wxASSERT( aNode->GetName() == wxT( "VIAREASSIGN" ) );
842
843 LayerID = GetXmlAttributeIDString( aNode, 0 );
844
846 Shape.Parse( aNode->GetChildren(), aContext );
847 else
848 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
849
850 CheckNoNextNodes( aNode->GetChildren() );
851}
852
853
855{
856 wxASSERT( aNode->GetName() == wxT( "VIACODE" ) );
857
858 ID = GetXmlAttributeIDString( aNode, 0 );
859 Name = GetXmlAttributeIDString( aNode, 1 );
860
861 XNODE* cNode = aNode->GetChildren();
862 wxString location = wxString::Format( wxT( "VIACODE -> %s" ), Name );
863
864 for( ; cNode; cNode = cNode->GetNext() )
865 {
866 wxString cNodeName = cNode->GetName();
867
868 if( CADSTAR_PAD_SHAPE::IsPadShape( cNode ) )
869 {
870 Shape.Parse( cNode, aContext );
871 }
872 else if( cNodeName == wxT( "CLEARANCE" ) )
873 {
875 }
876 else if( cNodeName == wxT( "RELIEFWIDTH" ) )
877 {
879 }
880 else if( cNodeName == wxT( "DRILL" ) )
881 {
883 XNODE* subNode = cNode->GetChildren();
884
885 for( ; subNode; subNode = subNode->GetNext() )
886 {
887 wxString subNodeName = subNode->GetName();
888
889 if( subNodeName == wxT( "OVERSIZE" ) )
890 DrillOversize = GetXmlAttributeIDLong( subNode, 0 );
891 else
892 THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
893 }
894 }
895 else if( cNodeName == wxT( "VIAREASSIGN" ) )
896 {
897 VIAREASSIGN reassign;
898 reassign.Parse( cNode, aContext );
899 Reassigns.insert( std::make_pair( reassign.LayerID, reassign.Shape ) );
900 }
901 else
902 {
904 }
905 }
906}
907
908
910{
911 wxASSERT( aNode->GetName() == wxT( "LAYERPAIR" ) );
912
913 ID = GetXmlAttributeIDString( aNode, 0 );
914 Name = GetXmlAttributeIDString( aNode, 1 );
915
918
919 wxString location = wxString::Format( wxT( "LAYERPAIR -> %s" ), Name );
920
921 if( aNode->GetChildren() )
922 {
923 if( aNode->GetChildren()->GetName() == wxT( "VIACODEREF" ) )
924 {
926 }
927 else
928 {
929 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), location );
930 }
931
932 CheckNoNextNodes( aNode->GetChildren() );
933 }
934}
935
936
938{
939 wxASSERT( aNode->GetName() == wxT( "SPCCLASSSPACE" ) );
940
943 LayerID = GetXmlAttributeIDString( aNode, 2 );
944 Spacing = GetXmlAttributeIDLong( aNode, 3 );
945}
946
947
949{
950 wxASSERT( aNode->GetName() == wxT( "TECHNOLOGY" ) );
951
952 XNODE* cNode = aNode->GetChildren();
953
954 for( ; cNode; cNode = cNode->GetNext() )
955 {
956 wxString cNodeName = cNode->GetName();
957
958 if( ParseSubNode( cNode, aContext ) ) //CADSTAR_ARCHIVE_PARSER::SETTINGS
959 {
960 }
961 else if( cNodeName == wxT( "MINROUTEWIDTH" ) )
962 {
964 }
965 else if( cNodeName == wxT( "MINNECKED" ) )
966 {
968 }
969 else if( cNodeName == wxT( "MINUNNECKED" ) )
970 {
972 }
973 else if( cNodeName == wxT( "MINMITER" ) )
974 {
975 MinMitre = GetXmlAttributeIDLong( cNode, 0 );
976 }
977 else if( cNodeName == wxT( "MAXMITER" ) )
978 {
979 MaxMitre = GetXmlAttributeIDLong( cNode, 0 );
980 }
981 else if( cNodeName == wxT( "MAXPHYSLAYER" ) )
982 {
984 }
985 else if( cNodeName == wxT( "TRACKGRID" ) )
986 {
987 TrackGrid = GetXmlAttributeIDLong( cNode, 0 );
988 }
989 else if( cNodeName == wxT( "VIAGRID" ) )
990 {
991 ViaGrid = GetXmlAttributeIDLong( cNode, 0 );
992 }
993 else if( cNodeName == wxT( "BACKOFFJCTS" ) )
994 {
995 BackOffJunctions = true;
996 }
997 else if( cNodeName == wxT( "BCKOFFWIDCHANGE" ) )
998 {
999 BackOffWidthChange = true;
1000 }
1001 else
1002 {
1003 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TECHNOLOGY" ) );
1004 }
1005 }
1006}
1007
1008
1010 const wxString& aPadSideString )
1011{
1012 if( aPadSideString == wxT( "THRU" ) )
1014 else if( aPadSideString == wxT( "BOTTOM" ) )
1015 return PAD_SIDE::MAXIMUM;
1016 else if( aPadSideString == wxT( "TOP" ) )
1017 return PAD_SIDE::MINIMUM;
1018 else
1019 return PAD_SIDE::THROUGH_HOLE; // Assume through hole as default
1020}
1021
1022
1024{
1025 wxASSERT( aNode->GetName() == wxT( "COMPCOPPER" ) );
1026
1028 LayerID = GetXmlAttributeIDString( aNode, 1 );
1029
1030 XNODE* cNode = aNode->GetChildren();
1031 bool shapeIsInitialised = false; // Stop more than one Shape Object
1032 wxString location = wxT( "COMPCOPPER" );
1033
1034 if( !cNode )
1035 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1036
1037 for( ; cNode; cNode = cNode->GetNext() )
1038 {
1039 wxString cNodeName = cNode->GetName();
1040
1041 if( !shapeIsInitialised && Shape.IsShape( cNode ) )
1042 {
1043 Shape.Parse( cNode, aContext );
1044 shapeIsInitialised = true;
1045 }
1046 else if( cNodeName == wxT( "SWAPRULE" ) )
1047 {
1048 SwapRule = ParseSwapRule( cNode );
1049 }
1050 else if( cNodeName == wxT( "ASSOCPIN" ) )
1051 {
1052 wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
1053
1054 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1055 {
1056 if( !IsValidAttribute( xmlAttribute ) )
1057 continue;
1058
1059 long padId;
1060
1061 if( !xmlAttribute->GetValue().ToLong( &padId ) )
1062 THROW_PARSING_IO_ERROR( wxT( "ASSOCPIN" ), location );
1063
1064 AssociatedPadIDs.push_back( (PAD_ID) padId );
1065 }
1066
1067 CheckNoChildNodes( cNode );
1068 }
1069 else
1070 {
1072 }
1073 }
1074}
1075
1076
1078{
1079 wxASSERT( aNode->GetName() == wxT( "COMPAREA" ) );
1080
1081 ID = GetXmlAttributeIDString( aNode, 0 );
1082 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1083 LayerID = GetXmlAttributeIDString( aNode, 3 );
1084
1085 XNODE* cNode = aNode->GetChildren();
1086 bool shapeIsInitialised = false; // Stop more than one Shape Object
1087 wxString location = wxString::Format( wxT( "COMPAREA %s" ), ID );
1088
1089 if( !cNode )
1090 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1091
1092 for( ; cNode; cNode = cNode->GetNext() )
1093 {
1094 wxString cNodeName = cNode->GetName();
1095
1096 if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
1097 {
1098 Shape.Parse( cNode, aContext );
1099 shapeIsInitialised = true;
1100 }
1101 else if( cNodeName == wxT( "SWAPRULE" ) )
1102 {
1103 SwapRule = ParseSwapRule( cNode );
1104 }
1105 else if( cNodeName == wxT( "USAGE" ) )
1106 {
1107 wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
1108
1109 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1110 {
1111 if( !IsValidAttribute( xmlAttribute ) )
1112 continue;
1113
1114 if( xmlAttribute->GetValue() == wxT( "NO_TRACKS" ) )
1115 NoTracks = true;
1116 else if( xmlAttribute->GetValue() == wxT( "NO_VIAS" ) )
1117 NoVias = true;
1118 else
1119 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), location );
1120 }
1121
1122 CheckNoChildNodes( cNode );
1123 }
1124 else
1125 {
1127 }
1128 }
1129}
1130
1131
1133{
1134 wxASSERT( aNode->GetName() == wxT( "EXITS" ) );
1135
1136 wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
1137
1138 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1139 {
1140 if( !IsValidAttribute( xmlAttribute ) )
1141 continue;
1142
1143 if( xmlAttribute->GetValue() == wxT( "FREE" ) )
1144 FreeAngle = true;
1145 else if( xmlAttribute->GetValue() == wxT( "N" ) )
1146 North = true;
1147 else if( xmlAttribute->GetValue() == wxT( "S" ) )
1148 South = true;
1149 else if( xmlAttribute->GetValue() == wxT( "E" ) )
1150 East = true;
1151 else if( xmlAttribute->GetValue() == wxT( "W" ) )
1152 West = true;
1153 else if( xmlAttribute->GetValue() == wxT( "NE" ) )
1154 NorthEast = true;
1155 else if( xmlAttribute->GetValue() == wxT( "NW" ) )
1156 NorthWest = true;
1157 else if( xmlAttribute->GetValue() == wxT( "SE" ) )
1158 SouthEast = true;
1159 else if( xmlAttribute->GetValue() == wxT( "SW" ) )
1160 SouthWest = true;
1161 else
1162 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), wxT( "EXITS" ) );
1163 }
1164
1165 CheckNoChildNodes( aNode );
1166}
1167
1168
1170{
1171 wxASSERT( aNode->GetName() == wxT( "PAD" ) );
1172
1173 ID = GetXmlAttributeIDLong( aNode, 0 );
1174 PadCodeID = GetXmlAttributeIDString( aNode, 2 );
1175 Side = GetPadSide( GetXmlAttributeIDString( aNode, 3 ) );
1176
1177 XNODE* cNode = aNode->GetChildren();
1178 wxString location = wxString::Format( wxT( "PAD %ld" ), ID );
1179
1180 if( !cNode )
1181 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), location );
1182
1183 for( ; cNode; cNode = cNode->GetNext() )
1184 {
1185 wxString cNodeName = cNode->GetName();
1186
1187 if( cNodeName == wxT( "ORIENT" ) )
1188 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1189 else if( cNodeName == wxT( "FIRSTPAD" ) )
1190 FirstPad = true;
1191 else if( cNodeName == wxT( "EXITS" ) )
1192 Exits.Parse( cNode, aContext );
1193 else if( cNodeName == wxT( "PADIDENTIFIER" ) )
1194 Identifier = GetXmlAttributeIDString( cNode, 0 );
1195 else if( cNodeName == wxT( "PCBONLYPAD" ) )
1196 PCBonlyPad = true;
1197 else if( cNodeName == wxT( "PT" ) )
1198 Position.Parse( cNode, aContext );
1199 else
1201 }
1202}
1203
1204
1206{
1207 wxASSERT( aNode->GetName() == wxT( "DIMARROW" ) );
1208 bool arrowStyleInitialised = false;
1209 bool upperAngleInitialised = false;
1210 bool lowerAngleInitialised = false;
1211
1212 ArrowLength = GetXmlAttributeIDLong( aNode, 3 );
1213
1214 XNODE* cNode = aNode->GetChildren();
1215
1216
1217 for( ; cNode; cNode = cNode->GetNext() )
1218 {
1219 wxString cNodeName = cNode->GetName();
1220
1221 if( cNodeName == wxT( "ARROWSTYLE" ) )
1222 {
1223 wxString arrowStyleStr = GetXmlAttributeIDString( cNode, 0 );
1224 arrowStyleInitialised = true;
1225
1226 if( arrowStyleStr == wxT( "DIMENSION_ARROWOPEN" ) )
1228 else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLOSED" ) )
1230 else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLEAR" ) )
1232 else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLOSEDFILLED" ) )
1234 else
1235 THROW_UNKNOWN_PARAMETER_IO_ERROR( arrowStyleStr, cNodeName );
1236 }
1237 else if( cNodeName == wxT( "ARROWANGLEA" ) )
1238 {
1239 UpperAngle = GetXmlAttributeIDLong( cNode, 0 );
1240 upperAngleInitialised = true;
1241 }
1242 else if( cNodeName == wxT( "ARROWANGLEB" ) )
1243 {
1244 UpperAngle = GetXmlAttributeIDLong( cNode, 0 );
1245 lowerAngleInitialised = true;
1246 }
1247 else
1248 {
1249 THROW_UNKNOWN_PARAMETER_IO_ERROR( cNodeName, wxT( "DIMARROW" ) );
1250 }
1251 }
1252
1253 if( !arrowStyleInitialised )
1254 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWSTYLE" ), wxT( "DIMARROW" ) );
1255
1256 if( !upperAngleInitialised )
1257 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWANGLEA" ), wxT( "DIMARROW" ) );
1258
1259 if( !lowerAngleInitialised )
1260 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWANGLEB" ), wxT( "DIMARROW" ) );
1261}
1262
1263
1265 PARSER_CONTEXT* aContext )
1266{
1267 wxASSERT( aNode->GetName() == wxT( "DIMTEXT" ) );
1268
1269 TextGap = GetXmlAttributeIDLong( aNode, 1 );
1270 TextOffset = GetXmlAttributeIDLong( aNode, 2 );
1271
1272 XNODE* cNode = aNode->GetChildren();
1273
1274 if( !cNode || cNode->GetName() != wxT( "TXTSTYLE" ) )
1275 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "DIMTEXT" ) );
1276
1277 wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
1278
1279 if( styleStr == wxT( "DIMENSION_INTERNAL" ) )
1281 else if( styleStr == wxT( "DIMENSION_EXTERNAL" ) )
1283 else
1284 THROW_UNKNOWN_PARAMETER_IO_ERROR( styleStr, wxT( "TXTSTYLE" ) );
1285
1286 CheckNoNextNodes( cNode );
1287}
1288
1289
1291 PARSER_CONTEXT* aContext )
1292{
1293 wxASSERT( aNode->GetName() == wxT( "EXTLINE" ) );
1294
1295 LineCodeID = GetXmlAttributeIDString( aNode, 0 );
1296 Overshoot = GetXmlAttributeIDLong( aNode, 3 );
1297 Offset = GetXmlAttributeIDLong( aNode, 4 );
1298
1299 XNODE* cNode = aNode->GetChildren();
1300 int noOfPoints = 0;
1301
1302 for( ; cNode; cNode = cNode->GetNext() )
1303 {
1304 wxString cNodeName = cNode->GetName();
1305
1306 if( noOfPoints < 2 && cNodeName == wxT( "PT" ) )
1307 {
1308 ++noOfPoints;
1309
1310 if( noOfPoints == 1 )
1311 Start.Parse( cNode, aContext );
1312 else
1313 End.Parse( cNode, aContext );
1314 }
1315 else if( cNodeName == wxT( "SUPPRESSFIRST" ) )
1316 {
1317 SuppressFirst = true;
1318 }
1319 else
1320 {
1321 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "EXTLINE" ) );
1322 }
1323 }
1324
1325 if( noOfPoints != 2 )
1326 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), wxT( "EXTLINE" ) );
1327}
1328
1329
1331{
1332 if( aNode->GetName() == wxT( "LEADERLINE" ) || aNode->GetName() == wxT( "LINEARLINE" )
1333 || aNode->GetName() == wxT( "ANGULARLINE" ) )
1334 {
1335 return true;
1336 }
1337 else
1338 {
1339 return false;
1340 }
1341}
1342
1343
1345{
1346 wxASSERT( IsLine( aNode ) );
1347
1348 if( aNode->GetName() == wxT( "LINEARLINE" ) )
1349 Type = TYPE::LINEARLINE;
1350 else if( aNode->GetName() == wxT( "LEADERLINE" ) )
1351 Type = TYPE::LEADERLINE;
1352 else if( aNode->GetName() == wxT( "ANGULARLINE" ) )
1353 Type = TYPE::ANGULARLINE;
1354 else
1355 wxASSERT_MSG( true, wxT( "Not a valid type. What happened to the node Name?" ) );
1356
1357 LineCodeID = GetXmlAttributeIDString( aNode, 0 );
1358
1359 if( Type == TYPE::LEADERLINE )
1360 {
1363 }
1364
1365 XNODE* cNode = aNode->GetChildren();
1366 int noOfPoints = 0;
1367 int requiredNoOfPoints = 2;
1368
1369 if( Type == TYPE::ANGULARLINE )
1370 requiredNoOfPoints = 3;
1371
1372 for( ; cNode; cNode = cNode->GetNext() )
1373 {
1374 wxString cNodeName = cNode->GetName();
1375
1376 if( cNodeName == wxT( "DIMLINETYPE" ) )
1377 {
1378 wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
1379
1380 if( styleStr == wxT( "DIMENSION_INTERNAL" ) )
1382 else if( styleStr == wxT( "DIMENSION_EXTERNAL" ) )
1384 else
1385 THROW_UNKNOWN_PARAMETER_IO_ERROR( styleStr, cNodeName );
1386 }
1387 else if( noOfPoints < requiredNoOfPoints && cNodeName == wxT( "PT" ) )
1388 {
1389 ++noOfPoints;
1390
1391 if( noOfPoints == 1 )
1392 Start.Parse( cNode, aContext );
1393 else if( noOfPoints == 2 )
1394 End.Parse( cNode, aContext );
1395 else
1396 Centre.Parse( cNode, aContext );
1397 }
1398 else if( Type == TYPE::LEADERLINE && cNodeName == wxT( "LEADERANG" ) )
1399 {
1400 LeaderAngle = GetXmlAttributeIDLong( cNode, 0 );
1401 }
1402 else
1403 {
1404 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1405 }
1406 }
1407
1408 if( noOfPoints != requiredNoOfPoints )
1409 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
1410}
1411
1412
1414{
1415 if( aNode->GetName() == wxT( "LINEARDIM" ) || aNode->GetName() == wxT( "LEADERDIM" )
1416 || aNode->GetName() == wxT( "ANGLEDIM" ) )
1417 {
1418 return true;
1419 }
1420 else
1421 {
1422 return false;
1423 }
1424}
1425
1426
1428{
1429 wxASSERT( IsDimension( aNode ) );
1430
1431 std::map<wxString, TYPE> typeMap = { { wxT( "LINEARDIM" ), TYPE::LINEARDIM },
1432 { wxT( "LEADERDIM" ), TYPE::LEADERDIM }, { wxT( "ANGLEDIM" ), TYPE::ANGLEDIM } };
1433
1434 //make sure aNode is valid TYPE
1435 wxASSERT_MSG( typeMap.find( aNode->GetName() ) != typeMap.end(),
1436 wxT( "Not a valid type. What happened to the node Name?" ) );
1437
1438 Type = typeMap[aNode->GetName()];
1439 LayerID = GetXmlAttributeIDString( aNode, 1 );
1440 wxString subTypeStr = GetXmlAttributeIDString( aNode, 2 );
1441
1442 std::map<wxString, SUBTYPE> subTypeMap = {
1443 { wxT( "DIMENSION_ORTHOGONAL" ), SUBTYPE::ORTHOGONAL },
1444 { wxT( "DIMENSION_DIRECT" ), SUBTYPE::DIRECT },
1445 { wxT( "DIMENSION_ANGLED" ), SUBTYPE::ANGLED },
1446 { wxT( "DIMENSION_DIAMETER" ), SUBTYPE::DIAMETER },
1447 { wxT( "DIMENSION_RADIUS" ), SUBTYPE::RADIUS },
1448 { wxT( "DIMENSION_ANGULAR" ), SUBTYPE::ANGULAR } };
1449
1450 if( subTypeMap.find( subTypeStr ) == subTypeMap.end() )
1451 THROW_UNKNOWN_PARAMETER_IO_ERROR( subTypeStr, aNode->GetName() );
1452
1453 Subtype = subTypeMap[subTypeStr];
1454 Precision = GetXmlAttributeIDLong( aNode, 3 );
1455
1456 XNODE* cNode = aNode->GetChildren();
1457
1458 bool idParsed = false;
1459 bool unitsParsed = false; //UNITS or ANGUNITS
1460 bool arrowParsed = false;
1461 bool textFormatParsed = false;
1462 bool extLineParsed = false;
1463 bool lineParsed = false;
1464 bool textParsed = false;
1465
1466 for( ; cNode; cNode = cNode->GetNext() )
1467 {
1468 wxString cNodeName = cNode->GetName();
1469
1470 if( !idParsed && cNodeName == wxT( "DIMREF" ) )
1471 {
1472 ID = GetXmlAttributeIDString( cNode, 0 );
1473 idParsed = true;
1474 }
1475 else if( !unitsParsed && cNodeName == wxT( "UNITS" ) )
1476 {
1477 LinearUnits = ParseUnits( cNode );
1478 unitsParsed = true;
1479 }
1480 else if( !unitsParsed && cNodeName == wxT( "ANGUNITS" ) )
1481 {
1482 AngularUnits = ParseAngunits( cNode );
1483 unitsParsed = true;
1484 }
1485 else if( !arrowParsed && cNodeName == wxT( "DIMARROW" ) )
1486 {
1487 Arrow.Parse( cNode, aContext );
1488 arrowParsed = true;
1489 }
1490 else if( !textFormatParsed && cNodeName == wxT( "DIMTEXT" ) )
1491 {
1492 TextParams.Parse( cNode, aContext );
1493 textFormatParsed = true;
1494 }
1495 else if( !extLineParsed && cNodeName == wxT( "EXTLINE" ) )
1496 {
1497 ExtensionLineParams.Parse( cNode, aContext );
1498 extLineParsed = true;
1499 }
1500 else if( !lineParsed && LINE::IsLine( cNode ) )
1501 {
1502 Line.Parse( cNode, aContext );
1503 lineParsed = true;
1504 }
1505 else if( !textParsed && cNodeName == wxT( "TEXT" ) )
1506 {
1507 // Do not parse the fields in dimension text (will be done when loading, if required)
1508 Text.Parse( cNode, aContext, false );
1509 textParsed = true;
1510 }
1511 else if( cNodeName == wxT( "FIX" ) )
1512 {
1513 Fixed = true;
1514 }
1515 else if( cNodeName == wxT( "GROUPREF" ) )
1516 {
1517 GroupID = GetXmlAttributeIDString( cNode, 0 );
1518 }
1519 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1520 {
1521 ReuseBlockRef.Parse( cNode, aContext );
1522 }
1523 else
1524 {
1525 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1526 }
1527 }
1528}
1529
1530
1532{
1533 wxASSERT( aNode->GetName() == wxT( "SYMDEF" ) );
1534
1535 ParseIdentifiers( aNode, aContext );
1536
1537 wxString rest;
1538
1539 if( ReferenceName.StartsWith( wxT( "JUMPERNF" ), &rest ) )
1541 else if( ReferenceName.StartsWith( wxT( "STARPOINTNF" ), &rest ) )
1543 else if( ReferenceName == wxT( "TESTPOINT" ) )
1545 else
1547
1548 XNODE* cNode = aNode->GetChildren();
1549
1550 for( ; cNode; cNode = cNode->GetNext() )
1551 {
1552 wxString cNodeName = cNode->GetName();
1553
1554 if( ParseSubNode( cNode, aContext ) )
1555 {
1556 continue;
1557 }
1558 else if( cNodeName == wxT( "SYMHEIGHT" ) )
1559 {
1560 SymHeight = GetXmlAttributeIDLong( cNode, 0 );
1561 }
1562 else if( cNodeName == wxT( "COMPCOPPER" ) )
1563 {
1564 COMPONENT_COPPER compcopper;
1565 compcopper.Parse( cNode, aContext );
1566 ComponentCoppers.push_back( compcopper );
1567 }
1568 else if( cNodeName == wxT( "COMPAREA" ) )
1569 {
1570 COMPONENT_AREA area;
1571 area.Parse( cNode, aContext );
1572 ComponentAreas.insert( std::make_pair( area.ID, area ) );
1573 }
1574 else if( cNodeName == wxT( "PAD" ) )
1575 {
1577 pad.Parse( cNode, aContext );
1578 ComponentPads.insert( std::make_pair( pad.ID, pad ) );
1579 }
1580 else if( cNodeName == wxT( "DIMENSIONS" ) )
1581 {
1582 XNODE* dimensionNode = cNode->GetChildren();
1583
1584 for( ; dimensionNode; dimensionNode = dimensionNode->GetNext() )
1585 {
1586 if( DIMENSION::IsDimension( dimensionNode ) )
1587 {
1588 DIMENSION dim;
1589 dim.Parse( dimensionNode, aContext );
1590 Dimensions.insert( std::make_pair( dim.ID, dim ) );
1591 }
1592 else
1593 {
1594 THROW_UNKNOWN_NODE_IO_ERROR( dimensionNode->GetName(), cNodeName );
1595 }
1596 }
1597 }
1598 else
1599 {
1600 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1601 }
1602 }
1603
1604 if( !Stub && ( Origin.x == UNDEFINED_VALUE || Origin.y == UNDEFINED_VALUE ) )
1605 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
1606}
1607
1608
1610{
1611 wxASSERT( aNode->GetName() == wxT( "LIBRARY" ) );
1612
1613 XNODE* cNode = aNode->GetChildren();
1614
1615 for( ; cNode; cNode = cNode->GetNext() )
1616 {
1617 wxString cNodeName = cNode->GetName();
1618
1619 if( cNodeName == wxT( "SYMDEF" ) )
1620 {
1621 SYMDEF_PCB symdef;
1622 symdef.Parse( cNode, aContext );
1623 ComponentDefinitions.insert( std::make_pair( symdef.ID, symdef ) );
1624 }
1625 else if( cNodeName == wxT( "HIERARCHY" ) )
1626 {
1627 // Ignore for now
1628 //
1629 // This node doesn't have any equivalent in KiCad so for now we ignore it. In
1630 // future, we could parse it in detail, to obtain the tree-structure of
1631 // footprints in a cadstar library
1632 }
1633 else
1634 {
1635 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1636 }
1637
1638 aContext->CheckPointCallback();
1639 }
1640}
1641
1642
1644{
1645 wxASSERT( aNode->GetName() == wxT( "BOARD" ) );
1646
1647 ID = GetXmlAttributeIDString( aNode, 0 );
1648 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1649
1650 XNODE* cNode = aNode->GetChildren();
1651 bool shapeIsInitialised = false; // Stop more than one Shape Object
1652 wxString location = wxString::Format( wxT( "BOARD %s" ), ID );
1653
1654 if( !cNode )
1655 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1656
1657 for( ; cNode; cNode = cNode->GetNext() )
1658 {
1659 wxString cNodeName = cNode->GetName();
1660
1661 if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
1662 {
1663 Shape.Parse( cNode, aContext );
1664 shapeIsInitialised = true;
1665 }
1666 else if( cNodeName == wxT( "ATTR" ) )
1667 {
1668 ATTRIBUTE_VALUE attr;
1669 attr.Parse( cNode, aContext );
1670 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
1671 }
1672 else if( cNodeName == wxT( "FIX" ) )
1673 {
1674 Fixed = true;
1675 }
1676 else if( cNodeName == wxT( "GROUPREF" ) )
1677 {
1678 GroupID = GetXmlAttributeIDString( cNode, 0 );
1679 }
1680 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1681 {
1682 ReuseBlockRef.Parse( cNode, aContext );
1683 }
1684 else
1685 {
1687 }
1688 }
1689}
1690
1691
1693{
1694 wxASSERT( aNode->GetName() == wxT( "AREA" ) );
1695
1696 ID = GetXmlAttributeIDString( aNode, 0 );
1697 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1698 Name = GetXmlAttributeIDString( aNode, 2 );
1699 LayerID = GetXmlAttributeIDString( aNode, 4 );
1700
1701 XNODE* cNode = aNode->GetChildren();
1702 bool shapeIsInitialised = false; // Stop more than one Shape Object
1703 wxString location = wxString::Format( wxT( "AREA %s" ), ID );
1704
1705 if( !cNode )
1706 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1707
1708 for( ; cNode; cNode = cNode->GetNext() )
1709 {
1710 wxString cNodeName = cNode->GetName();
1711
1712 if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
1713 {
1714 Shape.Parse( cNode, aContext );
1715 shapeIsInitialised = true;
1716 }
1717 else if( cNodeName == wxT( "FIX" ) )
1718 {
1719 Fixed = true;
1720 }
1721 else if( cNodeName == wxT( "USAGE" ) )
1722 {
1723 wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
1724
1725 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1726 {
1727 if( !IsValidAttribute( xmlAttribute ) )
1728 continue;
1729
1730 if( xmlAttribute->GetValue() == wxT( "PLACEMENT" ) )
1731 Placement = true;
1732 else if( xmlAttribute->GetValue() == wxT( "ROUTING" ) )
1733 Routing = true;
1734 else if( xmlAttribute->GetValue() == wxT( "KEEPOUT" ) )
1735 Keepout = true;
1736 else if( xmlAttribute->GetValue() == wxT( "NO_TRACKS" ) )
1737 NoTracks = true;
1738 else if( xmlAttribute->GetValue() == wxT( "NO_VIAS" ) )
1739 NoVias = true;
1740 else
1741 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), location );
1742 }
1743
1744 CheckNoChildNodes( cNode );
1745 }
1746 else if( cNodeName == wxT( "AREAHEIGHT" ) )
1747 {
1748 AreaHeight = GetXmlAttributeIDLong( cNode, 0 );
1749 }
1750 else if( cNodeName == wxT( "GROUPREF" ) )
1751 {
1752 GroupID = GetXmlAttributeIDString( cNode, 0 );
1753 }
1754 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1755 {
1756 ReuseBlockRef.Parse( cNode, aContext );
1757 }
1758 else if( cNodeName == wxT( "ATTR" ) )
1759 {
1760 ATTRIBUTE_VALUE attr;
1761 attr.Parse( cNode, aContext );
1762 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
1763 }
1764 else
1765 {
1767 }
1768 }
1769}
1770
1771
1773{
1774 wxASSERT( aNode->GetName() == wxT( "PINATTR" ) );
1775
1776 Pin = GetXmlAttributeIDLong( aNode, 0 );
1777
1778 XNODE* cNode = aNode->GetChildren();
1779
1780 for( ; cNode; cNode = cNode->GetNext() )
1781 {
1782 wxString cNodeName = cNode->GetName();
1783
1784 if( cNodeName == wxT( "ATTR" ) )
1785 {
1786 ATTRIBUTE_VALUE attrVal;
1787 attrVal.Parse( cNode, aContext );
1788 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
1789 }
1790 else if( cNodeName == wxT( "TESTLAND" ) )
1791 {
1793 }
1794 else
1795 {
1796 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1797 }
1798 }
1799}
1800
1801
1803{
1804 wxASSERT( aNode->GetName() == wxT( "PADEXCEPTION" ) );
1805
1806 ID = GetXmlAttributeIDLong( aNode, 0 );
1807
1808 XNODE* cNode = aNode->GetChildren();
1809
1810 for( ; cNode; cNode = cNode->GetNext() )
1811 {
1812 wxString cNodeName = cNode->GetName();
1813
1814 if( cNodeName == wxT( "PADCODEREF" ) )
1815 {
1816 PadCode = GetXmlAttributeIDString( cNode, 0 );
1817 }
1818 else if( cNodeName == wxT( "EXITS" ) )
1819 {
1820 OverrideExits = true;
1821 Exits.Parse( cNode, aContext );
1822 }
1823 else if( cNodeName == wxT( "SIDE" ) )
1824 {
1825 OverrideSide = true;
1826 Side = GetPadSide( GetXmlAttributeIDString( cNode, 0 ) );
1827 }
1828 else if( cNodeName == wxT( "ORIENT" ) )
1829 {
1830 OverrideOrientation = true;
1831 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1832 }
1833 else
1834 {
1835 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1836 }
1837 }
1838}
1839
1840
1842{
1843 wxASSERT( aNode->GetName() == wxT( "COMP" ) );
1844
1845 ID = GetXmlAttributeIDString( aNode, 0 );
1846 Name = GetXmlAttributeIDString( aNode, 1 );
1847 PartID = GetXmlAttributeIDString( aNode, 2 );
1848 SymdefID = GetXmlAttributeIDString( aNode, 3 );
1849
1850 XNODE* cNode = aNode->GetChildren();
1851 bool originParsed = false;
1852
1853 for( ; cNode; cNode = cNode->GetNext() )
1854 {
1855 wxString cNodeName = cNode->GetName();
1856
1857 if( !originParsed && cNodeName == wxT( "PT" ) )
1858 {
1859 Origin.Parse( cNode, aContext );
1860 originParsed = true;
1861 }
1862 else if( cNodeName == wxT( "GROUPREF" ) )
1863 {
1864 GroupID = GetXmlAttributeIDString( cNode, 0 );
1865 }
1866 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1867 {
1868 ReuseBlockRef.Parse( cNode, aContext );
1869 }
1870 else if( cNodeName == wxT( "TESTPOINT" ) )
1871 {
1872 TestPoint = true;
1873 }
1874 else if( cNodeName == wxT( "FIX" ) )
1875 {
1876 Fixed = true;
1877 }
1878 else if( cNodeName == wxT( "MIRROR" ) )
1879 {
1880 Mirror = true;
1881 }
1882 else if( cNodeName == wxT( "READABILITY" ) )
1883 {
1884 Readability = ParseReadability( cNode );
1885 }
1886 else if( cNodeName == wxT( "ORIENT" ) )
1887 {
1888 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1889 }
1890 else if( cNodeName == wxT( "VCOMPMASTER" ) )
1891 {
1893 VariantID = GetXmlAttributeIDString( cNode, 1 );
1894 }
1895 else if( cNodeName == wxT( "TEXTLOC" ) )
1896 {
1897 TEXT_LOCATION textloc;
1898 textloc.Parse( cNode, aContext );
1899 TextLocations.insert( std::make_pair( textloc.AttributeID, textloc ) );
1900 }
1901 else if( cNodeName == wxT( "ATTR" ) )
1902 {
1903 ATTRIBUTE_VALUE attrVal;
1904 attrVal.Parse( cNode, aContext );
1905 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
1906 }
1907 else if( cNodeName == wxT( "PINATTR" ) )
1908 {
1909 PIN_ATTRIBUTE pinAttr;
1910 pinAttr.Parse( cNode, aContext );
1911 PinAttributes.insert( std::make_pair( pinAttr.Pin, pinAttr ) );
1912 }
1913 else if( cNodeName == wxT( "COMPPINLABEL" ) )
1914 {
1916 wxString pinLabel = GetXmlAttributeIDString( cNode, 1 );
1917 PinLabels.insert( std::make_pair( pinID, pinLabel ) );
1918 }
1919 else if( cNodeName == wxT( "PADEXCEPTION" ) )
1920 {
1921 PADEXCEPTION padExcept;
1922 padExcept.Parse( cNode, aContext );
1923 PadExceptions.insert( std::make_pair( padExcept.ID, padExcept ) );
1924 }
1925 else
1926 {
1927 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1928 }
1929 }
1930
1931 if( !originParsed )
1932 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
1933}
1934
1935
1937 XNODE* aNode )
1938{
1939 wxASSERT( aNode->GetName() == wxT( "TESTLAND" ) );
1940
1941 wxString side = GetXmlAttributeIDString( aNode, 0 );
1942
1943 if( side == wxT( "MIN_SIDE" ) )
1944 return TESTLAND_SIDE::MIN;
1945 else if( side == wxT( "MAX_SIDE" ) )
1946 return TESTLAND_SIDE::MAX;
1947 else if( side == wxT( "BOTH_SIDES" ) )
1948 return TESTLAND_SIDE::BOTH;
1949 else
1950 THROW_UNKNOWN_PARAMETER_IO_ERROR( side, aNode->GetName() );
1951
1952 return TESTLAND_SIDE::NONE;
1953}
1954
1955
1957{
1958 wxASSERT( aNode->GetName() == wxT( "TRUNK" ) );
1959
1960 ID = GetXmlAttributeIDString( aNode, 0 );
1961 Definition = GetXmlAttributeIDString( aNode, 1 );
1962}
1963
1964
1966{
1967 wxASSERT( aNode->GetName() == wxT( "PIN" ) );
1968
1969 ID = GetXmlAttributeIDString( aNode, 0 );
1971 PadID = GetXmlAttributeIDLong( aNode, 2 );
1972 CheckNoChildNodes( aNode );
1973}
1974
1975
1977 PARSER_CONTEXT* aContext )
1978{
1979 ParseIdentifiers( aNode, aContext );
1980 XNODE* cNode = aNode->GetChildren();
1981
1982 for( ; cNode; cNode = cNode->GetNext() )
1983 {
1984 if( ParseSubNode( cNode, aContext ) )
1985 continue;
1986 else if( cNode->GetName() == wxT( "TRUNKREF" ) )
1987 TrunkID = GetXmlAttributeIDString( cNode, 0 );
1988 else
1989 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
1990 }
1991}
1992
1993
1995{
1996 wxASSERT( aNode->GetName() == wxT( "VIA" ) );
1997
1998 ID = GetXmlAttributeIDString( aNode, 0 );
1999 ViaCodeID = GetXmlAttributeIDString( aNode, 1 );
2001
2002 XNODE* cNode = aNode->GetChildren();
2003
2004 for( ; cNode; cNode = cNode->GetNext() )
2005 {
2006 wxString cNodeName = cNode->GetName();
2007
2008 if( cNodeName == wxT( "PT" ) )
2009 Location.Parse( cNode, aContext );
2010 else if( cNodeName == wxT( "FIX" ) )
2011 Fixed = true;
2012 else if( cNodeName == wxT( "GROUPREF" ) )
2013 GroupID = GetXmlAttributeIDString( cNode, 0 );
2014 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2015 ReuseBlockRef.Parse( cNode, aContext );
2016 else if( cNodeName == wxT( "TESTLAND" ) )
2018 else if( cNode->GetName() == wxT( "TRUNKREF" ) )
2019 TrunkID = GetXmlAttributeIDString( cNode, 0 );
2020 else
2021 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2022 }
2023}
2024
2025
2027 PARSER_CONTEXT* aContext )
2028{
2029 wxASSERT( aNode->GetName() == wxT( "COPTERM" ) );
2030
2031 ID = GetXmlAttributeIDString( aNode, 0 );
2032 CopperID = GetXmlAttributeIDString( aNode, 1 );
2034}
2035
2036
2038 PARSER_CONTEXT* aContext )
2039{
2040 wxASSERT( aNode->GetName() == wxT( "ROUTEWIDTH" ) );
2041
2042 RouteWidth = GetXmlAttributeIDLong( aNode, 0 );
2043 XNODE* prevNode = aNode;
2044 XNODE* nextNode = aNode->GetNext();
2045
2046 for( ; nextNode; nextNode = nextNode->GetNext() )
2047 {
2048 if( nextNode->GetName() == wxT( "FIX" ) )
2049 {
2050 Fixed = true;
2051 }
2052 else if( nextNode->GetName() == wxT( "TDROPATSTART" ) )
2053 {
2054 TeardropAtStart = true;
2056 }
2057 else if( nextNode->GetName() == wxT( "TDROPATEND" ) )
2058 {
2059 TeardropAtEnd = true;
2061 }
2062 else if( VERTEX::IsVertex( nextNode ) )
2063 {
2064 Vertex.Parse( nextNode, aContext );
2065 }
2066 else if( nextNode->GetName() == wxT( "ROUTEWIDTH" ) )
2067 {
2068 return prevNode;
2069 }
2070 else
2071 {
2072 THROW_UNKNOWN_NODE_IO_ERROR( nextNode->GetName(), wxT( "ROUTE" ) );
2073 }
2074
2075 prevNode = nextNode;
2076 }
2077
2078 return prevNode;
2079}
2080
2081
2083{
2084 wxASSERT( aNode->GetName() == wxT( "ROUTE" ) );
2085
2086 LayerID = GetXmlAttributeIDString( aNode, 0 );
2087
2088 //Parse child nodes
2089 XNODE* cNode = aNode->GetChildren();
2090 bool startPointParsed = false;
2091
2092 for( ; cNode; cNode = cNode->GetNext() )
2093 {
2094 wxString cNodeName = cNode->GetName();
2095
2096 if( !startPointParsed && cNodeName == wxT( "PT" ) )
2097 {
2098 startPointParsed = true;
2099 StartPoint.Parse( cNode, aContext );
2100 }
2101 else if( cNodeName == wxT( "ROUTEWIDTH" ) )
2102 {
2103 ROUTE_VERTEX rtVert;
2104 cNode = rtVert.Parse( cNode, aContext );
2105 RouteVertices.push_back( rtVert );
2106
2107 assert( cNode != nullptr );
2108 }
2109 else
2110 {
2111 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "ROUTE" ) );
2112 }
2113 }
2114}
2115
2116
2118 PARSER_CONTEXT* aContext )
2119{
2120 ParseIdentifiers( aNode, aContext );
2121
2122 //Parse child nodes
2123 XNODE* cNode = aNode->GetChildren();
2124 bool routeParsed = false; //assume only one route per connection
2125
2126 for( ; cNode; cNode = cNode->GetNext() )
2127 {
2128 wxString cNodeName = cNode->GetName();
2129
2130 if( ParseSubNode( cNode, aContext ) )
2131 {
2132 continue;
2133 }
2134 else if( !Unrouted && !routeParsed && cNodeName == wxT( "ROUTE" ) )
2135 {
2136 Route.Parse( cNode, aContext );
2137 routeParsed = true;
2138 }
2139 else if( !routeParsed && cNodeName == wxT( "UNROUTE" ) )
2140 {
2141 Unrouted = true;
2143 }
2144 else if( cNode->GetName() == wxT( "TRUNKREF" ) )
2145 {
2146 TrunkID = GetXmlAttributeIDString( cNode, 0 );
2147 }
2148 else
2149 {
2150 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "CONN" ) );
2151 }
2152 }
2153}
2154
2155
2157{
2158 ParseIdentifiers( aNode, aContext );
2159
2160 //Parse child nodes
2161 XNODE* cNode = aNode->GetChildren();
2162
2163 for( ; cNode; cNode = cNode->GetNext() )
2164 {
2165 wxString cNodeName = cNode->GetName();
2166
2167 if( cNodeName == wxT( "JPT" ) )
2168 {
2169 JUNCTION_PCB jpt;
2170 jpt.Parse( cNode, aContext );
2171 Junctions.insert( std::make_pair( jpt.ID, jpt ) );
2172 }
2173 else if( ParseSubNode( cNode, aContext ) )
2174 {
2175 continue;
2176 }
2177 else if( cNodeName == wxT( "PIN" ) )
2178 {
2179 PIN pin;
2180 pin.Parse( cNode, aContext );
2181 Pins.insert( std::make_pair( pin.ID, pin ) );
2182 }
2183 else if( cNodeName == wxT( "VIA" ) )
2184 {
2185 VIA via;
2186 via.Parse( cNode, aContext );
2187 Vias.insert( std::make_pair( via.ID, via ) );
2188 }
2189 else if( cNodeName == wxT( "COPTERM" ) )
2190 {
2191 COPPER_TERMINAL cterm;
2192 cterm.Parse( cNode, aContext );
2193 CopperTerminals.insert( std::make_pair( cterm.ID, cterm ) );
2194 }
2195 else if( cNodeName == wxT( "CONN" ) )
2196 {
2197 CONNECTION_PCB conn;
2198 conn.Parse( cNode, aContext );
2199 Connections.push_back( conn );
2200 }
2201 else
2202 {
2203 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "NET" ) );
2204 }
2205 }
2206}
2207
2208
2210{
2211 wxASSERT( aNode->GetName() == wxT( "POURING" ) );
2212
2216 SliverWidth = GetXmlAttributeIDLong( aNode, 3 );
2220
2221 wxString MinIsolCopStr = GetXmlAttributeIDString( aNode, 7 );
2222
2223 if( MinIsolCopStr == wxT( "NONE" ) )
2225 else
2227
2228 wxString MinDisjCopStr = GetXmlAttributeIDString( aNode, 8 );
2229
2230 if( MinDisjCopStr == wxT( "NONE" ) )
2232 else
2234
2235 XNODE* cNode = aNode->GetChildren();
2236
2237 for( ; cNode; cNode = cNode->GetNext() )
2238 {
2239 wxString cNodeName = cNode->GetName();
2240
2241 if( cNodeName == wxT( "NOPINRELIEF" ) )
2242 {
2243 ThermalReliefOnPads = false;
2244 }
2245 else if( cNodeName == wxT( "NOVIARELIEF" ) )
2246 {
2247 ThermalReliefOnVias = false;
2248 }
2249 else if( cNodeName == wxT( "IGNORETRN" ) )
2250 {
2251 AllowInNoRouting = true;
2252 }
2253 else if( cNodeName == wxT( "BOXPINS" ) )
2254 {
2255 BoxIsolatedPins = true;
2256 }
2257 else if( cNodeName == wxT( "REGENERATE" ) )
2258 {
2259 AutomaticRepour = true;
2260 }
2261 else if( cNodeName == wxT( "AUTOROUTETARGET" ) )
2262 {
2263 TargetForAutorouting = true;
2264 }
2265 else if( cNodeName == wxT( "THERMALCUTOUT" ) )
2266 {
2268 }
2269 else if( cNodeName == wxT( "FILLED" ) )
2270 {
2272 }
2273 else if( cNodeName == wxT( "HATCHCODEREF" ) )
2274 {
2277 }
2278 else
2279 {
2280 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "POURING" ) );
2281 }
2282 }
2283}
2284
2285
2287{
2288 wxASSERT( aNode->GetName() == wxT( "TEMPLATE" ) );
2289
2290 ID = GetXmlAttributeIDString( aNode, 0 );
2291 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
2292 Name = GetXmlAttributeIDString( aNode, 2 );
2293 NetID = GetXmlAttributeIDString( aNode, 3 );
2294 LayerID = GetXmlAttributeIDString( aNode, 4 );
2295
2296 XNODE* cNode = aNode->GetChildren();
2297 bool shapeParsed = false;
2298 bool pouringParsed = false;
2299
2300 for( ; cNode; cNode = cNode->GetNext() )
2301 {
2302 wxString cNodeName = cNode->GetName();
2303
2304 if( !shapeParsed && SHAPE::IsShape( cNode ) )
2305 {
2306 Shape.Parse( cNode, aContext );
2307 shapeParsed = true;
2308 }
2309 else if( !pouringParsed && cNodeName == wxT( "POURING" ) )
2310 {
2311 Pouring.Parse( cNode, aContext );
2312 pouringParsed = true;
2313 }
2314 else if( cNodeName == wxT( "FIX" ) )
2315 {
2316 Fixed = true;
2317 }
2318 else if( cNodeName == wxT( "GROUPREF" ) )
2319 {
2320 GroupID = GetXmlAttributeIDString( cNode, 0 );
2321 }
2322 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2323 {
2324 ReuseBlockRef.Parse( cNode, aContext );
2325 }
2326 else if( cNodeName == wxT( "ATTR" ) )
2327 {
2328 ATTRIBUTE_VALUE attr;
2329 attr.Parse( cNode, aContext );
2330 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2331 }
2332 else
2333 {
2334 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEMPLATE" ) );
2335 }
2336 }
2337}
2338
2339
2341 PARSER_CONTEXT* aContext )
2342{
2343 wxASSERT( aNode->GetName() == wxT( "TERM" ) );
2344
2345 ID = GetXmlAttributeIDLong( aNode, 0 );
2346
2347 XNODE* cNode = aNode->GetChildren();
2348 bool locationParsed = false;
2349
2350 for( ; cNode; cNode = cNode->GetNext() )
2351 {
2352 wxString cNodeName = cNode->GetName();
2353
2354 if( !locationParsed && cNodeName == wxT( "PT" ) )
2355 {
2356 Location.Parse( cNode, aContext );
2357 locationParsed = true;
2358 }
2359 else if( cNodeName == wxT( "FIX" ) )
2360 {
2361 Fixed = true;
2362 }
2363 else
2364 {
2365 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2366 }
2367 }
2368}
2369
2370
2372{
2373 wxASSERT( aNode->GetName() == wxT( "NETREF" ) );
2374
2375 NetID = GetXmlAttributeIDString( aNode, 0 );
2376
2377 XNODE* cNode = aNode->GetChildren();
2378
2379 for( ; cNode; cNode = cNode->GetNext() )
2380 {
2381 wxString cNodeName = cNode->GetName();
2382
2383 if( cNodeName == wxT( "TERM" ) )
2384 {
2385 COPPER_TERM term;
2386 term.Parse( cNode, aContext );
2387 CopperTerminals.insert( std::make_pair( term.ID, term ) );
2388 }
2389 else if( cNodeName == wxT( "FIX" ) )
2390 {
2391 Fixed = true;
2392 }
2393 else
2394 {
2395 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "NETREF" ) );
2396 }
2397 }
2398}
2399
2400
2402{
2403 wxASSERT( aNode->GetName() == wxT( "COPPER" ) );
2404
2405 ID = GetXmlAttributeIDString( aNode, 0 );
2407 LayerID = GetXmlAttributeIDString( aNode, 2 );
2408
2409 XNODE* cNode = aNode->GetChildren();
2410 bool shapeParsed = false;
2411 bool netRefParsed = false;
2412
2413 for( ; cNode; cNode = cNode->GetNext() )
2414 {
2415 wxString cNodeName = cNode->GetName();
2416
2417 if( !shapeParsed && SHAPE::IsShape( cNode ) )
2418 {
2419 Shape.Parse( cNode, aContext );
2420 shapeParsed = true;
2421 }
2422 else if( !netRefParsed && cNodeName == wxT( "NETREF" ) )
2423 {
2424 NetRef.Parse( cNode, aContext );
2425 netRefParsed = true;
2426 }
2427 else if( cNodeName == wxT( "FIX" ) )
2428 {
2429 Fixed = true;
2430 }
2431 else if( cNodeName == wxT( "GROUPREF" ) )
2432 {
2433 GroupID = GetXmlAttributeIDString( cNode, 0 );
2434 }
2435 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2436 {
2437 ReuseBlockRef.Parse( cNode, aContext );
2438 }
2439 else if( cNodeName == wxT( "POURED" ) )
2440 {
2442 }
2443 else if( cNodeName == wxT( "ATTR" ) )
2444 {
2445 ATTRIBUTE_VALUE attr;
2446 attr.Parse( cNode, aContext );
2447 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2448 }
2449 else
2450 {
2451 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEMPLATE" ) );
2452 }
2453 }
2454}
2455
2456
2458{
2459 wxASSERT( aNode->GetName() == wxT( "DRILLTABLE" ) );
2460
2461 ID = GetXmlAttributeIDString( aNode, 0 );
2462 LayerID = GetXmlAttributeIDString( aNode, 1 );
2463
2464 XNODE* cNode = aNode->GetChildren();
2465 bool positionParsed = false;
2466
2467 for( ; cNode; cNode = cNode->GetNext() )
2468 {
2469 wxString cNodeName = cNode->GetName();
2470
2471 if( !positionParsed && cNodeName == wxT( "PT" ) )
2472 {
2473 Position.Parse( cNode, aContext );
2474 positionParsed = true;
2475 }
2476 else if( cNodeName == wxT( "ORIENT" ) )
2477 {
2478 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
2479 }
2480 else if( cNodeName == wxT( "MIRROR" ) )
2481 {
2482 Mirror = true;
2483 }
2484 else if( cNodeName == wxT( "FIX" ) )
2485 {
2486 Fixed = true;
2487 }
2488 else if( cNodeName == wxT( "READABILITY" ) )
2489 {
2490 Readability = ParseReadability( cNode );
2491 }
2492 else if( cNodeName == wxT( "GROUPREF" ) )
2493 {
2494 GroupID = GetXmlAttributeIDString( cNode, 0 );
2495 }
2496 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2497 {
2498 ReuseBlockRef.Parse( cNode, aContext );
2499 }
2500 else
2501 {
2502 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2503 }
2504 }
2505}
2506
2507
2509{
2510 wxASSERT( aNode->GetName() == wxT( "LAYOUT" ) );
2511
2512 XNODE* cNode = aNode->GetChildren();
2513 bool netSynchParsed = false;
2514 bool dimensionsParsed = false;
2515
2516 for( ; cNode; cNode = cNode->GetNext() )
2517 {
2518 wxString cNodeName = cNode->GetName();
2519
2520 if( !netSynchParsed && cNodeName == wxT( "NETSYNCH" ) )
2521 {
2522 std::map<wxString, NETSYNCH> netSynchMap = { { wxT( "WARNING" ), NETSYNCH::WARNING },
2523 { wxT( "FULL" ), NETSYNCH::FULL } };
2524
2525 wxString nsString = GetXmlAttributeIDString( cNode, 0 );
2526
2527 if( netSynchMap.find( nsString ) == netSynchMap.end() )
2528 THROW_UNKNOWN_PARAMETER_IO_ERROR( nsString, aNode->GetName() );
2529
2530 NetSynch = netSynchMap[nsString];
2531 netSynchParsed = true;
2532 }
2533 else if( cNodeName == wxT( "GROUP" ) )
2534 {
2535 GROUP group;
2536 group.Parse( cNode, aContext );
2537 Groups.insert( std::make_pair( group.ID, group ) );
2538 }
2539 else if( cNodeName == wxT( "REUSEBLOCK" ) )
2540 {
2541 REUSEBLOCK reuseblock;
2542 reuseblock.Parse( cNode, aContext );
2543 ReuseBlocks.insert( std::make_pair( reuseblock.ID, reuseblock ) );
2544 }
2545 else if( cNodeName == wxT( "BOARD" ) )
2546 {
2547 CADSTAR_BOARD board;
2548 board.Parse( cNode, aContext );
2549 Boards.insert( std::make_pair( board.ID, board ) );
2550 }
2551 else if( cNodeName == wxT( "FIGURE" ) )
2552 {
2553 FIGURE figure;
2554 figure.Parse( cNode, aContext );
2555 Figures.insert( std::make_pair( figure.ID, figure ) );
2556 }
2557 else if( cNodeName == wxT( "AREA" ) )
2558 {
2559 AREA area;
2560 area.Parse( cNode, aContext );
2561 Areas.insert( std::make_pair( area.ID, area ) );
2562 }
2563 else if( cNodeName == wxT( "COMP" ) )
2564 {
2566 comp.Parse( cNode, aContext );
2567 Components.insert( std::make_pair( comp.ID, comp ) );
2568 }
2569 else if( cNodeName == wxT( "TRUNK" ) )
2570 {
2571 TRUNK trunk;
2572 trunk.Parse( cNode, aContext );
2573 Trunks.insert( std::make_pair( trunk.ID, trunk ) );
2574 }
2575 else if( cNodeName == wxT( "NET" ) )
2576 {
2577 NET_PCB net;
2578 net.Parse( cNode, aContext );
2579 Nets.insert( std::make_pair( net.ID, net ) );
2580 }
2581 else if( cNodeName == wxT( "TEMPLATE" ) )
2582 {
2583 TEMPLATE temp;
2584 temp.Parse( cNode, aContext );
2585 Templates.insert( std::make_pair( temp.ID, temp ) );
2586 }
2587 else if( cNodeName == wxT( "COPPER" ) )
2588 {
2589 COPPER copper;
2590 copper.Parse( cNode, aContext );
2591 Coppers.insert( std::make_pair( copper.ID, copper ) );
2592 }
2593 else if( cNodeName == wxT( "TEXT" ) )
2594 {
2595 TEXT txt;
2596 txt.Parse( cNode, aContext );
2597 Texts.insert( std::make_pair( txt.ID, txt ) );
2598 }
2599 else if( cNodeName == wxT( "DOCSYMBOL" ) )
2600 {
2601 DOCUMENTATION_SYMBOL docsym;
2602 docsym.Parse( cNode, aContext );
2603 DocumentationSymbols.insert( std::make_pair( docsym.ID, docsym ) );
2604 }
2605 else if( !dimensionsParsed && cNodeName == wxT( "DIMENSIONS" ) )
2606 {
2607 XNODE* dimensionNode = cNode->GetChildren();
2608
2609 for( ; dimensionNode; dimensionNode = dimensionNode->GetNext() )
2610 {
2611 if( DIMENSION::IsDimension( dimensionNode ) )
2612 {
2613 DIMENSION dim;
2614 dim.Parse( dimensionNode, aContext );
2615 Dimensions.insert( std::make_pair( dim.ID, dim ) );
2616 }
2617 else
2618 {
2619 THROW_UNKNOWN_NODE_IO_ERROR( dimensionNode->GetName(), cNodeName );
2620 }
2621 }
2622
2623 dimensionsParsed = true;
2624 }
2625 else if( cNodeName == wxT( "DRILLTABLE" ) )
2626 {
2627 DRILL_TABLE drilltable;
2628 drilltable.Parse( cNode, aContext );
2629 DrillTables.insert( std::make_pair( drilltable.ID, drilltable ) );
2630 }
2631 else if( cNodeName == wxT( "VHIERARCHY" ) )
2632 {
2633 VariantHierarchy.Parse( cNode, aContext );
2634 }
2635 else if( cNodeName == wxT( "ERRORMARK" ) )
2636 {
2637 //ignore (this is a DRC error marker in cadstar)
2638 continue;
2639 }
2640 else
2641 {
2642 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2643 }
2644
2645 aContext->CheckPointCallback();
2646 }
2647}
constexpr double PCB_IU_PER_MM
Pcbnew IU is 1 nanometer.
Definition base_units.h:70
#define THROW_MISSING_NODE_IO_ERROR(nodename, location)
#define THROW_UNKNOWN_NODE_IO_ERROR(nodename, location)
#define THROW_UNKNOWN_PARAMETER_IO_ERROR(param, location)
#define THROW_MISSING_PARAMETER_IO_ERROR(param, location)
#define THROW_PARSING_IO_ERROR(param, location)
static UNITS ParseUnits(XNODE *aNode)
static SWAP_RULE ParseSwapRule(XNODE *aNode)
static void CheckNoNextNodes(XNODE *aNode)
static XNODE * LoadArchiveFile(const wxString &aFileName, const wxString &aFileTypeIdentifier, PROGRESS_REPORTER *aProgressReporter=nullptr)
Reads a CADSTAR Archive file (S-parameter format).
wxString LAYER_ID
ID of a Sheet (if schematic) or board Layer (if PCB)
static ANGUNITS ParseAngunits(XNODE *aNode)
long PART_DEFINITION_PIN_ID
Pin identifier in the part definition.
static wxString GetXmlAttributeIDString(XNODE *aNode, unsigned int aID, bool aIsRequired=true)
void checkPoint()
Updates m_progressReporter or throws if user canceled.
static bool IsValidAttribute(wxXmlAttribute *aAttribute)
static READABILITY ParseReadability(XNODE *aNode)
static void CheckNoChildNodes(XNODE *aNode)
static long GetXmlAttributeIDLong(XNODE *aNode, unsigned int aID, bool aIsRequired=true)
static void ParseChildEValue(XNODE *aNode, PARSER_CONTEXT *aContext, EVALUE &aValueToParse)
static long GetNumberOfStepsForReporting(XNODE *aRootNode, std::vector< wxString > aSubNodeChildrenToCount)
PROGRESS_REPORTER * m_progressReporter
static TESTLAND_SIDE ParseTestlandSide(XNODE *aNode)
@ STARPOINT
From CADSTAR Help: "Starpoints are special symbols/components that can be used to electrically connec...
@ JUMPER
From CADSTAR Help: "Jumpers are components used primarily for the purpose of routing.
@ COMPONENT
Standard PCB Component definition.
@ TESTPOINT
From CADSTAR Help: "A testpoint is an area of copper connected to a net.
long PAD_ID
Pad identifier (pin) in the PCB.
void Parse(bool aLibrary=false)
Parses the file.
int KiCadUnitMultiplier
Use this value to convert units in this CPA file to KiCad units.
@ ALLELEC
Inbuilt layer type (cannot be assigned to user layers)
@ ALLDOC
Inbuilt layer type (cannot be assigned to user layers)
@ NOLAYER
Inbuilt layer type (cannot be assigned to user layers)
@ JUMPERLAYER
Inbuilt layer type (cannot be assigned to user layers)
@ ALLLAYER
Inbuilt layer type (cannot be assigned to user layers)
@ ASSCOMPCOPP
Inbuilt layer type (cannot be assigned to user layers)
@ MAX
The highest PHYSICAL_LAYER_ID currently defined (i.e. back / bottom side).
@ MIN
The lowest PHYSICAL_LAYER_ID currently defined (i.e. front / top side).
static PAD_SIDE GetPadSide(const wxString &aPadSideString)
PAD_SIDE
From CADSTAR Help: "This parameter indicates the physical layers on which the selected pad is placed.
@ MAXIMUM
The highest PHYSICAL_LAYER_ID currently defined (i.e.
@ THROUGH_HOLE
All physical layers currently defined.
An extension of wxXmlNode that can format its contents as KiCad-style s-expressions.
Definition xnode.h:71
XNODE * GetChildren() const
Definition xnode.h:101
XNODE * GetNext() const
Definition xnode.h:106
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition macros.h:83
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
NETELEMENT_ID ID
First character is "J".
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
std::function< void()> CheckPointCallback
Callback function to report progress.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
POINT Origin
Origin of the component (this is used as the reference point when placing the component in the design...
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
bool Stub
When the CADSTAR Archive file is exported without the component library, if components on the board a...
wxString ReferenceName
This is the name which identifies the symbol in the library Multiple components may exist with the sa...
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
From CADSTAR Help: "Area is for creating areas within which, and nowhere else, certain operations are...
GROUP_ID GroupID
If not empty, this AREA is part of a group.
bool Keepout
From CADSTAR Help: "Auto Placement cannot place components within this area.
bool Placement
From CADSTAR Help: "Auto Placement can place components within this area.
bool NoVias
From CADSTAR Help: "No vias will be placed within this area by the automatic router.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
long AreaHeight
From CADSTAR Help: "The Height value specified for the PCB component is checked against the Height va...
bool Routing
From CADSTAR Help: "Area can be used to place routes during Automatic Routing.
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
bool NoTracks
From CADSTAR Help: "Area cannot be used to place routes during automatic routing.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
GROUP_ID GroupID
Normally CADSTAR_BOARD cannot be part of a reuseblock, but included for completeness.
bool Fixed
If not empty, this CADSTAR_BOARD is part of a group.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< COPPERCODE_ID, COPPERCODE > CopperCodes
std::map< RULESET_ID, RULESET > Rulesets
Used for area design rules.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< SPACINGCODE_ID, SPACINGCODE > SpacingCodes
Spacing Design Rules.
std::map< LAYERPAIR_ID, LAYERPAIR > LayerPairs
Default vias to use between pairs of layers.
From CADSTAR Help: "Area is for creating areas within which, and nowhere else, certain operations are...
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool NoVias
From CADSTAR Help: "Check this button to specify that any area created by the Rectangle,...
bool NoTracks
From CADSTAR Help: "Check this button to specify that any area created by the Rectangle,...
A shape of copper in the component footprint.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool PCBonlyPad
From CADSTAR Help: "The PCB Only Pad property can be used to stop ECO Update, Back Annotation,...
POINT Position
Pad position within the component's coordinate frame.
wxString Identifier
This is an identifier that is displayed to the user.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool FirstPad
From CADSTAR Help: "Only one pad can have this property; if an existing pad in the design already has...
wxString Name
Designator e.g. "C1", "R1", etc.
POINT Origin
Origin of the component (this is used as the reference point when placing the component in the design...
bool TestPoint
Indicates whether this component should be treated as a testpoint.
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
std::map< PAD_ID, PADEXCEPTION > PadExceptions
Override pad definitions for this instance.
std::map< ATTRIBUTE_ID, TEXT_LOCATION > TextLocations
This contains location of any attributes, including designator position.
std::map< PART_DEFINITION_PIN_ID, PIN_ATTRIBUTE > PinAttributes
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
GROUP_ID GroupID
If not empty, this component is part of a group.
std::map< PART_DEFINITION_PIN_ID, wxString > PinLabels
This is inherited from the PARTS library but is allowed to be out of sync.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< COPPER_TERM_ID, COPPER_TERM > CopperTerminals
GROUP_ID GroupID
If not empty, this COPPER is part of a group.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
TEMPLATE_ID PouredTemplateID
If not empty, it means this COPPER is part of a poured template.
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
@ CLOSED
The arrow head is made up of two angled lines either side of main line plus two other lines perpendic...
@ CLEAR
Same as closed but the main line finishes at the start of the perpendicular lines.
@ CLOSED_FILLED
The same as CLOSED or CLEAR arrows, but with a solid fill "DIMENSION_ARROWCLOSEDFILLED".
@ OPEN
The arrow head is made up of two angled lines either side of main line.
long ArrowLength
The length of the angled lines that make up the arrow head.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool SuppressFirst
If true, excludes the first extension line (only shows extension line at end)
long Overshoot
Overshoot of the extension line past the arrow line.
@ INTERNAL
The lines are placed inside the measurement token=DIMENSION_INTERNAL.
@ EXTERNAL
The lines are placed outside the measurement (typically used when limited space) token=DIMENSION_EXTE...
long LeaderLineExtensionLength
Only for TYPE=LEADERLINE Length of the horizontal part of the leader line [param6].
long LeaderLineLength
Only for TYPE=LEADERLINE Length of the angled part of the leader line [param5].
long LeaderAngle
Only for TYPE=LEADERLINE subnode "LEADERANG".
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
POINT Centre
Only for TYPE=ANGULARLINE [point3].
long TextGap
Specifies the gap between the text and the end of the line.
long TextOffset
Specifies how far above the line the text is (doesn't have an effect on actual position!...
@ INSIDE
Embedded with the line (the Gap parameter specifies the gap between the text and the end of the line)...
@ OUTSIDE
Above the line (the Offset parameter specifies how far above the line the text is) DIMENSION_EXTERNAL...
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
Linear, leader (radius/diameter) or angular dimension.
LAYER_ID LayerID
ID on which to draw this [param1].
@ DIRECT
A linear dimension parallel to measurement with perpendicular extension lines token=DIMENSION_DIRECT.
@ ORTHOGONAL
An orthogonal dimension (either x or y measurement) token=DIMENSION_ORTHOGONAL.
@ ANGLED
A linear dimension parallel to measurement but with orthogonal extension lines (i....
GROUP_ID GroupID
If not empty, this DIMENSION is part of a group.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
EXTENSION_LINE ExtensionLineParams
Not applicable to TYPE=LEADERDIM.
DIMENSION_ID ID
Some ID (doesn't seem to be used) subnode="DIMREF".
long Precision
Number of decimal points to display in the measurement [param3].
ANGUNITS AngularUnits
Only Applicable to TYPE=ANGLEDIM.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
GROUP_ID GroupID
If not empty, this DRILL_TABLE is part of a group.
std::map< MATERIAL_ID, MATERIAL > Materials
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
PHYSICAL_LAYER_ID PhysicalLayer
If UNDEFINED, no physical layer is assigned (e.g.
long Thickness
Note: Units of length are defined in file header.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< TEMPLATE_ID, TEMPLATE > Templates
std::map< BOARD_ID, CADSTAR_BOARD > Boards
Normally CADSTAR only allows one board but.
std::map< NET_ID, NET_PCB > Nets
Contains tracks and vias.
std::map< COMPONENT_ID, COMPONENT > Components
std::map< DOCUMENTATION_SYMBOL_ID, DOCUMENTATION_SYMBOL > DocumentationSymbols
std::map< DIMENSION_ID, DIMENSION > Dimensions
std::map< REUSEBLOCK_ID, REUSEBLOCK > ReuseBlocks
std::map< DRILL_TABLE_ID, DRILL_TABLE > DrillTables
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< SYMDEF_ID, SYMDEF_PCB > ComponentDefinitions
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool Unrouted
Instead of a ROUTE, the CONNECTION might have an "UNROUTE" token.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
< "PIN" nodename (represents a PAD in a PCB component)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
< Two sibbling nodes: first node being "ROUTEWIDTH" and next node being a VERTEX (e....
XNODE * Parse(XNODE *aNode, PARSER_CONTEXT *aContext)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
GROUP_ID GroupID
If not empty, this VIA is part of a group.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< NETELEMENT_ID, COPPER_TERMINAL > CopperTerminals
std::map< NETELEMENT_ID, JUNCTION_PCB > Junctions
long ReliefWidth
if undefined inherits from design
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< LAYER_ID, CADSTAR_PAD_SHAPE > Reassigns
long ReliefClearance
if undefined inherits from design
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
PADCODE_ID PadCode
If not empty, override padcode.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
ROUTECODE_ID AreaRouteCodeID
For assigning a net route code to a rule set.
VIACODE_ID AreaViaCodeID
For assigning a via code to a rule set.
std::map< SPACINGCODE_ID, SPACINGCODE > SpacingCodes
Overrides these spacing rules in the specific area.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::vector< REASSIGN > Reassigns
Can have different spacings on different layers.
SPACINGCODE_ID ID
Possible spacing rules:
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
LAYER_ID LayerID
Normally LAY0, which corresponds to (All Layers)
std::map< PAD_ID, COMPONENT_PAD > ComponentPads
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< DIMENSION_ID, DIMENSION > Dimensions
inside "DIMENSIONS" subnode
std::vector< COMPONENT_COPPER > ComponentCoppers
long SymHeight
The Height of the component (3D height in z direction)
std::map< COMP_AREA_ID, COMPONENT_AREA > ComponentAreas
long MinRouteWidth
Manufacturing Design Rule. Corresponds to "Thin Route Width".
long TrackGrid
Grid for Routes (equal X and Y steps)
long MaxPhysicalLayer
Should equal number of copper layers.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
long MaxMitre
Manufacturing Design Rule. Corresponds to "Maximum Mitre".
long ViaGrid
Grid for Vias (equal X and Y steps)
long MinMitre
Manufacturing Design Rule. Corresponds to "Minimum Mitre".
long AdditionalIsolation
This is the gap to apply in routes and pads in addition to the existing pad-to-copper or route-to-cop...
bool TargetForAutorouting
true when subnode "AUTOROUTETARGET" is present
bool ThermalReliefOnVias
false when subnode "NOVIARELIEF" is present
@ CUTOUTS
This method uses four cutouts in the copper to leave the reliefs required.
HATCHCODE_ID HatchCodeID
Only for FillType = HATCHED.
bool ThermalReliefOnPads
false when subnode "NOPINRELIEF" is present
long ThermalReliefPadsAngle
Orientation for the thermal reliefs.
long MinDisjointCopper
The value is the length of one side of a notional square.
bool AutomaticRepour
true when subnode "REGENERATE" is present
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool AllowInNoRouting
true when subnode "IGNORETRN" is present
bool BoxIsolatedPins
true when subnode "BOXPINS" is present
long ClearanceWidth
Specifies the space around pads when pouring (i.e.
COPPERCODE_ID ReliefCopperCodeID
From CADSTAR Help: "Relief Copper Code is forselecting the width of line used to draw thethermal reli...
COPPERCODE_ID CopperCodeID
From CADSTAR Help: "Copper Code is for selecting the width of the line used to draw the outline and f...
long ThermalReliefViasAngle
Disabled when !ThermalReliefOnVias (param6)
long MinIsolatedCopper
The value is the length of one side of a notional square.
long SliverWidth
Minimum width of copper that may be created.
Templates are CADSTAR's equivalent to a "filled zone".
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
POURING Pouring
Copper pour settings (e.g. relief / hatching /etc.)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
GROUP_ID GroupID
If not empty, this TEMPLATE is part of a group.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
long ReliefClearance
if undefined inherits from design
long ReliefWidth
if undefined inherits from design
std::map< LAYER_ID, CADSTAR_PAD_SHAPE > Reassigns
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
KIBIS_COMPONENT * comp
KIBIS_PIN * pin
VECTOR2I location