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
730 if( aNode->GetChildren() )
731 {
732 if( aNode->GetChildren()->GetName() == wxT( "ORIENT" ) )
733 {
735 }
736 else
737 {
738 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
739 }
740
741 CheckNoNextNodes( aNode->GetChildren() );
742 }
744
746 Size = GetXmlAttributeIDLong( aNode, 0 );
747 break;
748 }
749}
750
751
753{
754 wxASSERT( aNode->GetName() == wxT( "PADREASSIGN" ) );
755
756 LayerID = GetXmlAttributeIDString( aNode, 0 );
757
759 Shape.Parse( aNode->GetChildren(), aContext );
760 else
761 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
762
763 CheckNoNextNodes( aNode->GetChildren() );
764}
765
766
768{
769 wxASSERT( aNode->GetName() == wxT( "PADCODE" ) );
770
771 ID = GetXmlAttributeIDString( aNode, 0 );
772 Name = GetXmlAttributeIDString( aNode, 1 );
773
774 XNODE* cNode = aNode->GetChildren();
775 wxString location = wxString::Format( wxT( "PADCODE -> %s" ), Name );
776
777 for( ; cNode; cNode = cNode->GetNext() )
778 {
779 wxString cNodeName = cNode->GetName();
780
781 if( CADSTAR_PAD_SHAPE::IsPadShape( cNode ) )
782 {
783 Shape.Parse( cNode, aContext );
784 }
785 else if( cNodeName == wxT( "CLEARANCE" ) )
786 {
788 }
789 else if( cNodeName == wxT( "RELIEFWIDTH" ) )
790 {
792 }
793 else if( cNodeName == wxT( "DRILL" ) )
794 {
796 XNODE* subNode = cNode->GetChildren();
797
798 for( ; subNode; subNode = subNode->GetNext() )
799 {
800 wxString subNodeName = subNode->GetName();
801
802 if( subNodeName == wxT( "NONPLATED" ) )
803 Plated = false;
804 else if( subNodeName == wxT( "OVERSIZE" ) )
805 DrillOversize = GetXmlAttributeIDLong( subNode, 0 );
806 else
807 THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
808 }
809 }
810 else if( cNodeName == wxT( "DRILLLENGTH" ) )
811 {
812 SlotLength = GetXmlAttributeIDLong( cNode, 0 );
813 }
814 else if( cNodeName == wxT( "DRILLORIENTATION" ) )
815 {
817 }
818 else if( cNodeName == wxT( "DRILLXOFFSET" ) )
819 {
821 }
822 else if( cNodeName == wxT( "DRILLYOFFSET" ) )
823 {
825 }
826 else if( cNodeName == wxT( "PADREASSIGN" ) )
827 {
828 PADREASSIGN reassign;
829 reassign.Parse( cNode, aContext );
830 Reassigns.insert( std::make_pair( reassign.LayerID, reassign.Shape ) );
831 }
832 else
833 {
835 }
836 }
837}
838
839
841{
842 wxASSERT( aNode->GetName() == wxT( "VIAREASSIGN" ) );
843
844 LayerID = GetXmlAttributeIDString( aNode, 0 );
845
847 Shape.Parse( aNode->GetChildren(), aContext );
848 else
849 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
850
851 CheckNoNextNodes( aNode->GetChildren() );
852}
853
854
856{
857 wxASSERT( aNode->GetName() == wxT( "VIACODE" ) );
858
859 ID = GetXmlAttributeIDString( aNode, 0 );
860 Name = GetXmlAttributeIDString( aNode, 1 );
861
862 XNODE* cNode = aNode->GetChildren();
863 wxString location = wxString::Format( wxT( "VIACODE -> %s" ), Name );
864
865 for( ; cNode; cNode = cNode->GetNext() )
866 {
867 wxString cNodeName = cNode->GetName();
868
869 if( CADSTAR_PAD_SHAPE::IsPadShape( cNode ) )
870 {
871 Shape.Parse( cNode, aContext );
872 }
873 else if( cNodeName == wxT( "CLEARANCE" ) )
874 {
876 }
877 else if( cNodeName == wxT( "RELIEFWIDTH" ) )
878 {
880 }
881 else if( cNodeName == wxT( "DRILL" ) )
882 {
884 XNODE* subNode = cNode->GetChildren();
885
886 for( ; subNode; subNode = subNode->GetNext() )
887 {
888 wxString subNodeName = subNode->GetName();
889
890 if( subNodeName == wxT( "OVERSIZE" ) )
891 DrillOversize = GetXmlAttributeIDLong( subNode, 0 );
892 else
893 THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
894 }
895 }
896 else if( cNodeName == wxT( "VIAREASSIGN" ) )
897 {
898 VIAREASSIGN reassign;
899 reassign.Parse( cNode, aContext );
900 Reassigns.insert( std::make_pair( reassign.LayerID, reassign.Shape ) );
901 }
902 else
903 {
905 }
906 }
907}
908
909
911{
912 wxASSERT( aNode->GetName() == wxT( "LAYERPAIR" ) );
913
914 ID = GetXmlAttributeIDString( aNode, 0 );
915 Name = GetXmlAttributeIDString( aNode, 1 );
916
919
920 wxString location = wxString::Format( wxT( "LAYERPAIR -> %s" ), Name );
921
922 if( aNode->GetChildren() )
923 {
924 if( aNode->GetChildren()->GetName() == wxT( "VIACODEREF" ) )
925 {
927 }
928 else
929 {
930 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), location );
931 }
932
933 CheckNoNextNodes( aNode->GetChildren() );
934 }
935}
936
937
939{
940 wxASSERT( aNode->GetName() == wxT( "SPCCLASSSPACE" ) );
941
944 LayerID = GetXmlAttributeIDString( aNode, 2 );
945 Spacing = GetXmlAttributeIDLong( aNode, 3 );
946}
947
948
950{
951 wxASSERT( aNode->GetName() == wxT( "TECHNOLOGY" ) );
952
953 XNODE* cNode = aNode->GetChildren();
954
955 for( ; cNode; cNode = cNode->GetNext() )
956 {
957 wxString cNodeName = cNode->GetName();
958
959 if( ParseSubNode( cNode, aContext ) ) //CADSTAR_ARCHIVE_PARSER::SETTINGS
960 {
961 }
962 else if( cNodeName == wxT( "MINROUTEWIDTH" ) )
963 {
965 }
966 else if( cNodeName == wxT( "MINNECKED" ) )
967 {
969 }
970 else if( cNodeName == wxT( "MINUNNECKED" ) )
971 {
973 }
974 else if( cNodeName == wxT( "MINMITER" ) )
975 {
976 MinMitre = GetXmlAttributeIDLong( cNode, 0 );
977 }
978 else if( cNodeName == wxT( "MAXMITER" ) )
979 {
980 MaxMitre = GetXmlAttributeIDLong( cNode, 0 );
981 }
982 else if( cNodeName == wxT( "MAXPHYSLAYER" ) )
983 {
985 }
986 else if( cNodeName == wxT( "TRACKGRID" ) )
987 {
988 TrackGrid = GetXmlAttributeIDLong( cNode, 0 );
989 }
990 else if( cNodeName == wxT( "VIAGRID" ) )
991 {
992 ViaGrid = GetXmlAttributeIDLong( cNode, 0 );
993 }
994 else if( cNodeName == wxT( "BACKOFFJCTS" ) )
995 {
996 BackOffJunctions = true;
997 }
998 else if( cNodeName == wxT( "BCKOFFWIDCHANGE" ) )
999 {
1000 BackOffWidthChange = true;
1001 }
1002 else
1003 {
1004 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TECHNOLOGY" ) );
1005 }
1006 }
1007}
1008
1009
1011 const wxString& aPadSideString )
1012{
1013 if( aPadSideString == wxT( "THRU" ) )
1015 else if( aPadSideString == wxT( "BOTTOM" ) )
1016 return PAD_SIDE::MAXIMUM;
1017 else if( aPadSideString == wxT( "TOP" ) )
1018 return PAD_SIDE::MINIMUM;
1019 else
1020 return PAD_SIDE::THROUGH_HOLE; // Assume through hole as default
1021}
1022
1023
1025{
1026 wxASSERT( aNode->GetName() == wxT( "COMPCOPPER" ) );
1027
1029 LayerID = GetXmlAttributeIDString( aNode, 1 );
1030
1031 XNODE* cNode = aNode->GetChildren();
1032 bool shapeIsInitialised = false; // Stop more than one Shape Object
1033 wxString location = wxT( "COMPCOPPER" );
1034
1035 if( !cNode )
1036 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1037
1038 for( ; cNode; cNode = cNode->GetNext() )
1039 {
1040 wxString cNodeName = cNode->GetName();
1041
1042 if( !shapeIsInitialised && Shape.IsShape( cNode ) )
1043 {
1044 Shape.Parse( cNode, aContext );
1045 shapeIsInitialised = true;
1046 }
1047 else if( cNodeName == wxT( "SWAPRULE" ) )
1048 {
1049 SwapRule = ParseSwapRule( cNode );
1050 }
1051 else if( cNodeName == wxT( "ASSOCPIN" ) )
1052 {
1053 wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
1054
1055 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1056 {
1057 if( !IsValidAttribute( xmlAttribute ) )
1058 continue;
1059
1060 long padId;
1061
1062 if( !xmlAttribute->GetValue().ToLong( &padId ) )
1063 THROW_PARSING_IO_ERROR( wxT( "ASSOCPIN" ), location );
1064
1065 AssociatedPadIDs.push_back( (PAD_ID) padId );
1066 }
1067
1068 CheckNoChildNodes( cNode );
1069 }
1070 else
1071 {
1073 }
1074 }
1075}
1076
1077
1079{
1080 wxASSERT( aNode->GetName() == wxT( "COMPAREA" ) );
1081
1082 ID = GetXmlAttributeIDString( aNode, 0 );
1083 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1084 LayerID = GetXmlAttributeIDString( aNode, 3 );
1085
1086 XNODE* cNode = aNode->GetChildren();
1087 bool shapeIsInitialised = false; // Stop more than one Shape Object
1088 wxString location = wxString::Format( wxT( "COMPAREA %s" ), ID );
1089
1090 if( !cNode )
1091 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1092
1093 for( ; cNode; cNode = cNode->GetNext() )
1094 {
1095 wxString cNodeName = cNode->GetName();
1096
1097 if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
1098 {
1099 Shape.Parse( cNode, aContext );
1100 shapeIsInitialised = true;
1101 }
1102 else if( cNodeName == wxT( "SWAPRULE" ) )
1103 {
1104 SwapRule = ParseSwapRule( cNode );
1105 }
1106 else if( cNodeName == wxT( "USAGE" ) )
1107 {
1108 wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
1109
1110 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1111 {
1112 if( !IsValidAttribute( xmlAttribute ) )
1113 continue;
1114
1115 if( xmlAttribute->GetValue() == wxT( "NO_TRACKS" ) )
1116 NoTracks = true;
1117 else if( xmlAttribute->GetValue() == wxT( "NO_VIAS" ) )
1118 NoVias = true;
1119 else
1120 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), location );
1121 }
1122
1123 CheckNoChildNodes( cNode );
1124 }
1125 else
1126 {
1128 }
1129 }
1130}
1131
1132
1134{
1135 wxASSERT( aNode->GetName() == wxT( "EXITS" ) );
1136
1137 wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
1138
1139 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1140 {
1141 if( !IsValidAttribute( xmlAttribute ) )
1142 continue;
1143
1144 if( xmlAttribute->GetValue() == wxT( "FREE" ) )
1145 FreeAngle = true;
1146 else if( xmlAttribute->GetValue() == wxT( "N" ) )
1147 North = true;
1148 else if( xmlAttribute->GetValue() == wxT( "S" ) )
1149 South = true;
1150 else if( xmlAttribute->GetValue() == wxT( "E" ) )
1151 East = true;
1152 else if( xmlAttribute->GetValue() == wxT( "W" ) )
1153 West = true;
1154 else if( xmlAttribute->GetValue() == wxT( "NE" ) )
1155 NorthEast = true;
1156 else if( xmlAttribute->GetValue() == wxT( "NW" ) )
1157 NorthWest = true;
1158 else if( xmlAttribute->GetValue() == wxT( "SE" ) )
1159 SouthEast = true;
1160 else if( xmlAttribute->GetValue() == wxT( "SW" ) )
1161 SouthWest = true;
1162 else
1163 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), wxT( "EXITS" ) );
1164 }
1165
1166 CheckNoChildNodes( aNode );
1167}
1168
1169
1171{
1172 wxASSERT( aNode->GetName() == wxT( "PAD" ) );
1173
1174 ID = GetXmlAttributeIDLong( aNode, 0 );
1175 PadCodeID = GetXmlAttributeIDString( aNode, 2 );
1176 Side = GetPadSide( GetXmlAttributeIDString( aNode, 3 ) );
1177
1178 XNODE* cNode = aNode->GetChildren();
1179 wxString location = wxString::Format( wxT( "PAD %ld" ), ID );
1180
1181 if( !cNode )
1182 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), location );
1183
1184 for( ; cNode; cNode = cNode->GetNext() )
1185 {
1186 wxString cNodeName = cNode->GetName();
1187
1188 if( cNodeName == wxT( "ORIENT" ) )
1189 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1190 else if( cNodeName == wxT( "FIRSTPAD" ) )
1191 FirstPad = true;
1192 else if( cNodeName == wxT( "EXITS" ) )
1193 Exits.Parse( cNode, aContext );
1194 else if( cNodeName == wxT( "PADIDENTIFIER" ) )
1195 Identifier = GetXmlAttributeIDString( cNode, 0 );
1196 else if( cNodeName == wxT( "PCBONLYPAD" ) )
1197 PCBonlyPad = true;
1198 else if( cNodeName == wxT( "PT" ) )
1199 Position.Parse( cNode, aContext );
1200 else
1202 }
1203}
1204
1205
1207{
1208 wxASSERT( aNode->GetName() == wxT( "DIMARROW" ) );
1209 bool arrowStyleInitialised = false;
1210 bool upperAngleInitialised = false;
1211 bool lowerAngleInitialised = false;
1212
1213 ArrowLength = GetXmlAttributeIDLong( aNode, 3 );
1214
1215 XNODE* cNode = aNode->GetChildren();
1216
1217
1218 for( ; cNode; cNode = cNode->GetNext() )
1219 {
1220 wxString cNodeName = cNode->GetName();
1221
1222 if( cNodeName == wxT( "ARROWSTYLE" ) )
1223 {
1224 wxString arrowStyleStr = GetXmlAttributeIDString( cNode, 0 );
1225 arrowStyleInitialised = true;
1226
1227 if( arrowStyleStr == wxT( "DIMENSION_ARROWOPEN" ) )
1229 else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLOSED" ) )
1231 else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLEAR" ) )
1233 else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLOSEDFILLED" ) )
1235 else
1236 THROW_UNKNOWN_PARAMETER_IO_ERROR( arrowStyleStr, cNodeName );
1237 }
1238 else if( cNodeName == wxT( "ARROWANGLEA" ) )
1239 {
1240 UpperAngle = GetXmlAttributeIDLong( cNode, 0 );
1241 upperAngleInitialised = true;
1242 }
1243 else if( cNodeName == wxT( "ARROWANGLEB" ) )
1244 {
1245 UpperAngle = GetXmlAttributeIDLong( cNode, 0 );
1246 lowerAngleInitialised = true;
1247 }
1248 else
1249 {
1250 THROW_UNKNOWN_PARAMETER_IO_ERROR( cNodeName, wxT( "DIMARROW" ) );
1251 }
1252 }
1253
1254 if( !arrowStyleInitialised )
1255 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWSTYLE" ), wxT( "DIMARROW" ) );
1256
1257 if( !upperAngleInitialised )
1258 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWANGLEA" ), wxT( "DIMARROW" ) );
1259
1260 if( !lowerAngleInitialised )
1261 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWANGLEB" ), wxT( "DIMARROW" ) );
1262}
1263
1264
1266 PARSER_CONTEXT* aContext )
1267{
1268 wxASSERT( aNode->GetName() == wxT( "DIMTEXT" ) );
1269
1270 TextGap = GetXmlAttributeIDLong( aNode, 1 );
1271 TextOffset = GetXmlAttributeIDLong( aNode, 2 );
1272
1273 XNODE* cNode = aNode->GetChildren();
1274
1275 if( !cNode || cNode->GetName() != wxT( "TXTSTYLE" ) )
1276 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "DIMTEXT" ) );
1277
1278 wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
1279
1280 if( styleStr == wxT( "DIMENSION_INTERNAL" ) )
1282 else if( styleStr == wxT( "DIMENSION_EXTERNAL" ) )
1284 else
1285 THROW_UNKNOWN_PARAMETER_IO_ERROR( styleStr, wxT( "TXTSTYLE" ) );
1286
1287 CheckNoNextNodes( cNode );
1288}
1289
1290
1292 PARSER_CONTEXT* aContext )
1293{
1294 wxASSERT( aNode->GetName() == wxT( "EXTLINE" ) );
1295
1296 LineCodeID = GetXmlAttributeIDString( aNode, 0 );
1297 Overshoot = GetXmlAttributeIDLong( aNode, 3 );
1298 Offset = GetXmlAttributeIDLong( aNode, 4 );
1299
1300 XNODE* cNode = aNode->GetChildren();
1301 int noOfPoints = 0;
1302
1303 for( ; cNode; cNode = cNode->GetNext() )
1304 {
1305 wxString cNodeName = cNode->GetName();
1306
1307 if( noOfPoints < 2 && cNodeName == wxT( "PT" ) )
1308 {
1309 ++noOfPoints;
1310
1311 if( noOfPoints == 1 )
1312 Start.Parse( cNode, aContext );
1313 else
1314 End.Parse( cNode, aContext );
1315 }
1316 else if( cNodeName == wxT( "SUPPRESSFIRST" ) )
1317 {
1318 SuppressFirst = true;
1319 }
1320 else
1321 {
1322 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "EXTLINE" ) );
1323 }
1324 }
1325
1326 if( noOfPoints != 2 )
1327 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), wxT( "EXTLINE" ) );
1328}
1329
1330
1332{
1333 if( aNode->GetName() == wxT( "LEADERLINE" ) || aNode->GetName() == wxT( "LINEARLINE" )
1334 || aNode->GetName() == wxT( "ANGULARLINE" ) )
1335 {
1336 return true;
1337 }
1338 else
1339 {
1340 return false;
1341 }
1342}
1343
1344
1346{
1347 wxASSERT( IsLine( aNode ) );
1348
1349 if( aNode->GetName() == wxT( "LINEARLINE" ) )
1350 Type = TYPE::LINEARLINE;
1351 else if( aNode->GetName() == wxT( "LEADERLINE" ) )
1352 Type = TYPE::LEADERLINE;
1353 else if( aNode->GetName() == wxT( "ANGULARLINE" ) )
1354 Type = TYPE::ANGULARLINE;
1355 else
1356 wxASSERT_MSG( true, wxT( "Not a valid type. What happened to the node Name?" ) );
1357
1358 LineCodeID = GetXmlAttributeIDString( aNode, 0 );
1359
1360 if( Type == TYPE::LEADERLINE )
1361 {
1364 }
1365
1366 XNODE* cNode = aNode->GetChildren();
1367 int noOfPoints = 0;
1368 int requiredNoOfPoints = 2;
1369
1370 if( Type == TYPE::ANGULARLINE )
1371 requiredNoOfPoints = 3;
1372
1373 for( ; cNode; cNode = cNode->GetNext() )
1374 {
1375 wxString cNodeName = cNode->GetName();
1376
1377 if( cNodeName == wxT( "DIMLINETYPE" ) )
1378 {
1379 wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
1380
1381 if( styleStr == wxT( "DIMENSION_INTERNAL" ) )
1383 else if( styleStr == wxT( "DIMENSION_EXTERNAL" ) )
1385 else
1386 THROW_UNKNOWN_PARAMETER_IO_ERROR( styleStr, cNodeName );
1387 }
1388 else if( noOfPoints < requiredNoOfPoints && cNodeName == wxT( "PT" ) )
1389 {
1390 ++noOfPoints;
1391
1392 if( noOfPoints == 1 )
1393 Start.Parse( cNode, aContext );
1394 else if( noOfPoints == 2 )
1395 End.Parse( cNode, aContext );
1396 else
1397 Centre.Parse( cNode, aContext );
1398 }
1399 else if( Type == TYPE::LEADERLINE && cNodeName == wxT( "LEADERANG" ) )
1400 {
1401 LeaderAngle = GetXmlAttributeIDLong( cNode, 0 );
1402 }
1403 else
1404 {
1405 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1406 }
1407 }
1408
1409 if( noOfPoints != requiredNoOfPoints )
1410 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
1411}
1412
1413
1415{
1416 if( aNode->GetName() == wxT( "LINEARDIM" ) || aNode->GetName() == wxT( "LEADERDIM" )
1417 || aNode->GetName() == wxT( "ANGLEDIM" ) )
1418 {
1419 return true;
1420 }
1421 else
1422 {
1423 return false;
1424 }
1425}
1426
1427
1429{
1430 wxASSERT( IsDimension( aNode ) );
1431
1432 std::map<wxString, TYPE> typeMap = { { wxT( "LINEARDIM" ), TYPE::LINEARDIM },
1433 { wxT( "LEADERDIM" ), TYPE::LEADERDIM }, { wxT( "ANGLEDIM" ), TYPE::ANGLEDIM } };
1434
1435 //make sure aNode is valid TYPE
1436 wxASSERT_MSG( typeMap.find( aNode->GetName() ) != typeMap.end(),
1437 wxT( "Not a valid type. What happened to the node Name?" ) );
1438
1439 Type = typeMap[aNode->GetName()];
1440 LayerID = GetXmlAttributeIDString( aNode, 1 );
1441 wxString subTypeStr = GetXmlAttributeIDString( aNode, 2 );
1442
1443 std::map<wxString, SUBTYPE> subTypeMap = {
1444 { wxT( "DIMENSION_ORTHOGONAL" ), SUBTYPE::ORTHOGONAL },
1445 { wxT( "DIMENSION_DIRECT" ), SUBTYPE::DIRECT },
1446 { wxT( "DIMENSION_ANGLED" ), SUBTYPE::ANGLED },
1447 { wxT( "DIMENSION_DIAMETER" ), SUBTYPE::DIAMETER },
1448 { wxT( "DIMENSION_RADIUS" ), SUBTYPE::RADIUS },
1449 { wxT( "DIMENSION_ANGULAR" ), SUBTYPE::ANGULAR } };
1450
1451 if( subTypeMap.find( subTypeStr ) == subTypeMap.end() )
1452 THROW_UNKNOWN_PARAMETER_IO_ERROR( subTypeStr, aNode->GetName() );
1453
1454 Subtype = subTypeMap[subTypeStr];
1455 Precision = GetXmlAttributeIDLong( aNode, 3 );
1456
1457 XNODE* cNode = aNode->GetChildren();
1458
1459 bool idParsed = false;
1460 bool unitsParsed = false; //UNITS or ANGUNITS
1461 bool arrowParsed = false;
1462 bool textFormatParsed = false;
1463 bool extLineParsed = false;
1464 bool lineParsed = false;
1465 bool textParsed = false;
1466
1467 for( ; cNode; cNode = cNode->GetNext() )
1468 {
1469 wxString cNodeName = cNode->GetName();
1470
1471 if( !idParsed && cNodeName == wxT( "DIMREF" ) )
1472 {
1473 ID = GetXmlAttributeIDString( cNode, 0 );
1474 idParsed = true;
1475 }
1476 else if( !unitsParsed && cNodeName == wxT( "UNITS" ) )
1477 {
1478 LinearUnits = ParseUnits( cNode );
1479 unitsParsed = true;
1480 }
1481 else if( !unitsParsed && cNodeName == wxT( "ANGUNITS" ) )
1482 {
1483 AngularUnits = ParseAngunits( cNode );
1484 unitsParsed = true;
1485 }
1486 else if( !arrowParsed && cNodeName == wxT( "DIMARROW" ) )
1487 {
1488 Arrow.Parse( cNode, aContext );
1489 arrowParsed = true;
1490 }
1491 else if( !textFormatParsed && cNodeName == wxT( "DIMTEXT" ) )
1492 {
1493 TextParams.Parse( cNode, aContext );
1494 textFormatParsed = true;
1495 }
1496 else if( !extLineParsed && cNodeName == wxT( "EXTLINE" ) )
1497 {
1498 ExtensionLineParams.Parse( cNode, aContext );
1499 extLineParsed = true;
1500 }
1501 else if( !lineParsed && LINE::IsLine( cNode ) )
1502 {
1503 Line.Parse( cNode, aContext );
1504 lineParsed = true;
1505 }
1506 else if( !textParsed && cNodeName == wxT( "TEXT" ) )
1507 {
1508 // Do not parse the fields in dimension text (will be done when loading, if required)
1509 Text.Parse( cNode, aContext, false );
1510 textParsed = true;
1511 }
1512 else if( cNodeName == wxT( "FIX" ) )
1513 {
1514 Fixed = true;
1515 }
1516 else if( cNodeName == wxT( "GROUPREF" ) )
1517 {
1518 GroupID = GetXmlAttributeIDString( cNode, 0 );
1519 }
1520 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1521 {
1522 ReuseBlockRef.Parse( cNode, aContext );
1523 }
1524 else
1525 {
1526 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1527 }
1528 }
1529}
1530
1531
1533{
1534 wxASSERT( aNode->GetName() == wxT( "SYMDEF" ) );
1535
1536 ParseIdentifiers( aNode, aContext );
1537
1538 wxString rest;
1539
1540 if( ReferenceName.StartsWith( wxT( "JUMPERNF" ), &rest ) )
1542 else if( ReferenceName.StartsWith( wxT( "STARPOINTNF" ), &rest ) )
1544 else if( ReferenceName == wxT( "TESTPOINT" ) )
1546 else
1548
1549 XNODE* cNode = aNode->GetChildren();
1550
1551 for( ; cNode; cNode = cNode->GetNext() )
1552 {
1553 wxString cNodeName = cNode->GetName();
1554
1555 if( ParseSubNode( cNode, aContext ) )
1556 {
1557 continue;
1558 }
1559 else if( cNodeName == wxT( "SYMHEIGHT" ) )
1560 {
1561 SymHeight = GetXmlAttributeIDLong( cNode, 0 );
1562 }
1563 else if( cNodeName == wxT( "COMPCOPPER" ) )
1564 {
1565 COMPONENT_COPPER compcopper;
1566 compcopper.Parse( cNode, aContext );
1567 ComponentCoppers.push_back( compcopper );
1568 }
1569 else if( cNodeName == wxT( "COMPAREA" ) )
1570 {
1571 COMPONENT_AREA area;
1572 area.Parse( cNode, aContext );
1573 ComponentAreas.insert( std::make_pair( area.ID, area ) );
1574 }
1575 else if( cNodeName == wxT( "PAD" ) )
1576 {
1578 pad.Parse( cNode, aContext );
1579 ComponentPads.insert( std::make_pair( pad.ID, pad ) );
1580 }
1581 else if( cNodeName == wxT( "DIMENSIONS" ) )
1582 {
1583 XNODE* dimensionNode = cNode->GetChildren();
1584
1585 for( ; dimensionNode; dimensionNode = dimensionNode->GetNext() )
1586 {
1587 if( DIMENSION::IsDimension( dimensionNode ) )
1588 {
1589 DIMENSION dim;
1590 dim.Parse( dimensionNode, aContext );
1591 Dimensions.insert( std::make_pair( dim.ID, dim ) );
1592 }
1593 else
1594 {
1595 THROW_UNKNOWN_NODE_IO_ERROR( dimensionNode->GetName(), cNodeName );
1596 }
1597 }
1598 }
1599 else
1600 {
1601 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1602 }
1603 }
1604
1605 if( !Stub && ( Origin.x == UNDEFINED_VALUE || Origin.y == UNDEFINED_VALUE ) )
1606 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
1607}
1608
1609
1611{
1612 wxASSERT( aNode->GetName() == wxT( "LIBRARY" ) );
1613
1614 XNODE* cNode = aNode->GetChildren();
1615
1616 for( ; cNode; cNode = cNode->GetNext() )
1617 {
1618 wxString cNodeName = cNode->GetName();
1619
1620 if( cNodeName == wxT( "SYMDEF" ) )
1621 {
1622 SYMDEF_PCB symdef;
1623 symdef.Parse( cNode, aContext );
1624 ComponentDefinitions.insert( std::make_pair( symdef.ID, symdef ) );
1625 }
1626 else if( cNodeName == wxT( "HIERARCHY" ) )
1627 {
1628 // Ignore for now
1629 //
1630 // This node doesn't have any equivalent in KiCad so for now we ignore it. In
1631 // future, we could parse it in detail, to obtain the tree-structure of
1632 // footprints in a cadstar library
1633 }
1634 else
1635 {
1636 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1637 }
1638
1639 aContext->CheckPointCallback();
1640 }
1641}
1642
1643
1645{
1646 wxASSERT( aNode->GetName() == wxT( "BOARD" ) );
1647
1648 ID = GetXmlAttributeIDString( aNode, 0 );
1649 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1650
1651 XNODE* cNode = aNode->GetChildren();
1652 bool shapeIsInitialised = false; // Stop more than one Shape Object
1653 wxString location = wxString::Format( wxT( "BOARD %s" ), ID );
1654
1655 if( !cNode )
1656 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1657
1658 for( ; cNode; cNode = cNode->GetNext() )
1659 {
1660 wxString cNodeName = cNode->GetName();
1661
1662 if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
1663 {
1664 Shape.Parse( cNode, aContext );
1665 shapeIsInitialised = true;
1666 }
1667 else if( cNodeName == wxT( "ATTR" ) )
1668 {
1669 ATTRIBUTE_VALUE attr;
1670 attr.Parse( cNode, aContext );
1671 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
1672 }
1673 else if( cNodeName == wxT( "FIX" ) )
1674 {
1675 Fixed = true;
1676 }
1677 else if( cNodeName == wxT( "GROUPREF" ) )
1678 {
1679 GroupID = GetXmlAttributeIDString( cNode, 0 );
1680 }
1681 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1682 {
1683 ReuseBlockRef.Parse( cNode, aContext );
1684 }
1685 else
1686 {
1688 }
1689 }
1690}
1691
1692
1694{
1695 wxASSERT( aNode->GetName() == wxT( "AREA" ) );
1696
1697 ID = GetXmlAttributeIDString( aNode, 0 );
1698 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1699 Name = GetXmlAttributeIDString( aNode, 2 );
1700 LayerID = GetXmlAttributeIDString( aNode, 4 );
1701
1702 XNODE* cNode = aNode->GetChildren();
1703 bool shapeIsInitialised = false; // Stop more than one Shape Object
1704 wxString location = wxString::Format( wxT( "AREA %s" ), ID );
1705
1706 if( !cNode )
1707 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1708
1709 for( ; cNode; cNode = cNode->GetNext() )
1710 {
1711 wxString cNodeName = cNode->GetName();
1712
1713 if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
1714 {
1715 Shape.Parse( cNode, aContext );
1716 shapeIsInitialised = true;
1717 }
1718 else if( cNodeName == wxT( "FIX" ) )
1719 {
1720 Fixed = true;
1721 }
1722 else if( cNodeName == wxT( "USAGE" ) )
1723 {
1724 wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
1725
1726 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1727 {
1728 if( !IsValidAttribute( xmlAttribute ) )
1729 continue;
1730
1731 if( xmlAttribute->GetValue() == wxT( "PLACEMENT" ) )
1732 Placement = true;
1733 else if( xmlAttribute->GetValue() == wxT( "ROUTING" ) )
1734 Routing = true;
1735 else if( xmlAttribute->GetValue() == wxT( "KEEPOUT" ) )
1736 Keepout = true;
1737 else if( xmlAttribute->GetValue() == wxT( "NO_TRACKS" ) )
1738 NoTracks = true;
1739 else if( xmlAttribute->GetValue() == wxT( "NO_VIAS" ) )
1740 NoVias = true;
1741 else
1742 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), location );
1743 }
1744
1745 CheckNoChildNodes( cNode );
1746 }
1747 else if( cNodeName == wxT( "AREAHEIGHT" ) )
1748 {
1749 AreaHeight = GetXmlAttributeIDLong( cNode, 0 );
1750 }
1751 else if( cNodeName == wxT( "GROUPREF" ) )
1752 {
1753 GroupID = GetXmlAttributeIDString( cNode, 0 );
1754 }
1755 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1756 {
1757 ReuseBlockRef.Parse( cNode, aContext );
1758 }
1759 else if( cNodeName == wxT( "ATTR" ) )
1760 {
1761 ATTRIBUTE_VALUE attr;
1762 attr.Parse( cNode, aContext );
1763 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
1764 }
1765 else
1766 {
1768 }
1769 }
1770}
1771
1772
1774{
1775 wxASSERT( aNode->GetName() == wxT( "PINATTR" ) );
1776
1777 Pin = GetXmlAttributeIDLong( aNode, 0 );
1778
1779 XNODE* cNode = aNode->GetChildren();
1780
1781 for( ; cNode; cNode = cNode->GetNext() )
1782 {
1783 wxString cNodeName = cNode->GetName();
1784
1785 if( cNodeName == wxT( "ATTR" ) )
1786 {
1787 ATTRIBUTE_VALUE attrVal;
1788 attrVal.Parse( cNode, aContext );
1789 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
1790 }
1791 else if( cNodeName == wxT( "TESTLAND" ) )
1792 {
1794 }
1795 else
1796 {
1797 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1798 }
1799 }
1800}
1801
1802
1804{
1805 wxASSERT( aNode->GetName() == wxT( "PADEXCEPTION" ) );
1806
1807 ID = GetXmlAttributeIDLong( aNode, 0 );
1808
1809 XNODE* cNode = aNode->GetChildren();
1810
1811 for( ; cNode; cNode = cNode->GetNext() )
1812 {
1813 wxString cNodeName = cNode->GetName();
1814
1815 if( cNodeName == wxT( "PADCODEREF" ) )
1816 {
1817 PadCode = GetXmlAttributeIDString( cNode, 0 );
1818 }
1819 else if( cNodeName == wxT( "EXITS" ) )
1820 {
1821 OverrideExits = true;
1822 Exits.Parse( cNode, aContext );
1823 }
1824 else if( cNodeName == wxT( "SIDE" ) )
1825 {
1826 OverrideSide = true;
1827 Side = GetPadSide( GetXmlAttributeIDString( cNode, 0 ) );
1828 }
1829 else if( cNodeName == wxT( "ORIENT" ) )
1830 {
1831 OverrideOrientation = true;
1832 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1833 }
1834 else
1835 {
1836 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1837 }
1838 }
1839}
1840
1841
1843{
1844 wxASSERT( aNode->GetName() == wxT( "COMP" ) );
1845
1846 ID = GetXmlAttributeIDString( aNode, 0 );
1847 Name = GetXmlAttributeIDString( aNode, 1 );
1848 PartID = GetXmlAttributeIDString( aNode, 2 );
1849 SymdefID = GetXmlAttributeIDString( aNode, 3 );
1850
1851 XNODE* cNode = aNode->GetChildren();
1852 bool originParsed = false;
1853
1854 for( ; cNode; cNode = cNode->GetNext() )
1855 {
1856 wxString cNodeName = cNode->GetName();
1857
1858 if( !originParsed && cNodeName == wxT( "PT" ) )
1859 {
1860 Origin.Parse( cNode, aContext );
1861 originParsed = true;
1862 }
1863 else if( cNodeName == wxT( "GROUPREF" ) )
1864 {
1865 GroupID = GetXmlAttributeIDString( cNode, 0 );
1866 }
1867 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1868 {
1869 ReuseBlockRef.Parse( cNode, aContext );
1870 }
1871 else if( cNodeName == wxT( "TESTPOINT" ) )
1872 {
1873 TestPoint = true;
1874 }
1875 else if( cNodeName == wxT( "FIX" ) )
1876 {
1877 Fixed = true;
1878 }
1879 else if( cNodeName == wxT( "MIRROR" ) )
1880 {
1881 Mirror = true;
1882 }
1883 else if( cNodeName == wxT( "READABILITY" ) )
1884 {
1885 Readability = ParseReadability( cNode );
1886 }
1887 else if( cNodeName == wxT( "ORIENT" ) )
1888 {
1889 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1890 }
1891 else if( cNodeName == wxT( "VCOMPMASTER" ) )
1892 {
1894 VariantID = GetXmlAttributeIDString( cNode, 1 );
1895 }
1896 else if( cNodeName == wxT( "TEXTLOC" ) )
1897 {
1898 TEXT_LOCATION textloc;
1899 textloc.Parse( cNode, aContext );
1900 TextLocations.insert( std::make_pair( textloc.AttributeID, textloc ) );
1901 }
1902 else if( cNodeName == wxT( "ATTR" ) )
1903 {
1904 ATTRIBUTE_VALUE attrVal;
1905 attrVal.Parse( cNode, aContext );
1906 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
1907 }
1908 else if( cNodeName == wxT( "PINATTR" ) )
1909 {
1910 PIN_ATTRIBUTE pinAttr;
1911 pinAttr.Parse( cNode, aContext );
1912 PinAttributes.insert( std::make_pair( pinAttr.Pin, pinAttr ) );
1913 }
1914 else if( cNodeName == wxT( "COMPPINLABEL" ) )
1915 {
1917 wxString pinLabel = GetXmlAttributeIDString( cNode, 1 );
1918 PinLabels.insert( std::make_pair( pinID, pinLabel ) );
1919 }
1920 else if( cNodeName == wxT( "PADEXCEPTION" ) )
1921 {
1922 PADEXCEPTION padExcept;
1923 padExcept.Parse( cNode, aContext );
1924 PadExceptions.insert( std::make_pair( padExcept.ID, padExcept ) );
1925 }
1926 else
1927 {
1928 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1929 }
1930 }
1931
1932 if( !originParsed )
1933 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
1934}
1935
1936
1938 XNODE* aNode )
1939{
1940 wxASSERT( aNode->GetName() == wxT( "TESTLAND" ) );
1941
1942 wxString side = GetXmlAttributeIDString( aNode, 0 );
1943
1944 if( side == wxT( "MIN_SIDE" ) )
1945 return TESTLAND_SIDE::MIN;
1946 else if( side == wxT( "MAX_SIDE" ) )
1947 return TESTLAND_SIDE::MAX;
1948 else if( side == wxT( "BOTH_SIDES" ) )
1949 return TESTLAND_SIDE::BOTH;
1950 else
1951 THROW_UNKNOWN_PARAMETER_IO_ERROR( side, aNode->GetName() );
1952
1953 return TESTLAND_SIDE::NONE;
1954}
1955
1956
1958{
1959 wxASSERT( aNode->GetName() == wxT( "TRUNK" ) );
1960
1961 ID = GetXmlAttributeIDString( aNode, 0 );
1962 Definition = GetXmlAttributeIDString( aNode, 1 );
1963}
1964
1965
1967{
1968 wxASSERT( aNode->GetName() == wxT( "PIN" ) );
1969
1970 ID = GetXmlAttributeIDString( aNode, 0 );
1972 PadID = GetXmlAttributeIDLong( aNode, 2 );
1973 CheckNoChildNodes( aNode );
1974}
1975
1976
1978 PARSER_CONTEXT* aContext )
1979{
1980 ParseIdentifiers( aNode, aContext );
1981 XNODE* cNode = aNode->GetChildren();
1982
1983 for( ; cNode; cNode = cNode->GetNext() )
1984 {
1985 if( ParseSubNode( cNode, aContext ) )
1986 continue;
1987 else if( cNode->GetName() == wxT( "TRUNKREF" ) )
1988 TrunkID = GetXmlAttributeIDString( cNode, 0 );
1989 else
1990 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
1991 }
1992}
1993
1994
1996{
1997 wxASSERT( aNode->GetName() == wxT( "VIA" ) );
1998
1999 ID = GetXmlAttributeIDString( aNode, 0 );
2000 ViaCodeID = GetXmlAttributeIDString( aNode, 1 );
2002
2003 XNODE* cNode = aNode->GetChildren();
2004
2005 for( ; cNode; cNode = cNode->GetNext() )
2006 {
2007 wxString cNodeName = cNode->GetName();
2008
2009 if( cNodeName == wxT( "PT" ) )
2010 Location.Parse( cNode, aContext );
2011 else if( cNodeName == wxT( "FIX" ) )
2012 Fixed = true;
2013 else if( cNodeName == wxT( "GROUPREF" ) )
2014 GroupID = GetXmlAttributeIDString( cNode, 0 );
2015 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2016 ReuseBlockRef.Parse( cNode, aContext );
2017 else if( cNodeName == wxT( "TESTLAND" ) )
2019 else if( cNode->GetName() == wxT( "TRUNKREF" ) )
2020 TrunkID = GetXmlAttributeIDString( cNode, 0 );
2021 else
2022 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2023 }
2024}
2025
2026
2028 PARSER_CONTEXT* aContext )
2029{
2030 wxASSERT( aNode->GetName() == wxT( "COPTERM" ) );
2031
2032 ID = GetXmlAttributeIDString( aNode, 0 );
2033 CopperID = GetXmlAttributeIDString( aNode, 1 );
2035}
2036
2037
2039 PARSER_CONTEXT* aContext )
2040{
2041 wxASSERT( aNode->GetName() == wxT( "ROUTEWIDTH" ) );
2042
2043 RouteWidth = GetXmlAttributeIDLong( aNode, 0 );
2044 XNODE* prevNode = aNode;
2045 XNODE* nextNode = aNode->GetNext();
2046
2047 for( ; nextNode; nextNode = nextNode->GetNext() )
2048 {
2049 if( nextNode->GetName() == wxT( "FIX" ) )
2050 {
2051 Fixed = true;
2052 }
2053 else if( nextNode->GetName() == wxT( "TDROPATSTART" ) )
2054 {
2055 TeardropAtStart = true;
2057 }
2058 else if( nextNode->GetName() == wxT( "TDROPATEND" ) )
2059 {
2060 TeardropAtEnd = true;
2062 }
2063 else if( VERTEX::IsVertex( nextNode ) )
2064 {
2065 Vertex.Parse( nextNode, aContext );
2066 }
2067 else if( nextNode->GetName() == wxT( "ROUTEWIDTH" ) )
2068 {
2069 return prevNode;
2070 }
2071 else
2072 {
2073 THROW_UNKNOWN_NODE_IO_ERROR( nextNode->GetName(), wxT( "ROUTE" ) );
2074 }
2075
2076 prevNode = nextNode;
2077 }
2078
2079 return prevNode;
2080}
2081
2082
2084{
2085 wxASSERT( aNode->GetName() == wxT( "ROUTE" ) );
2086
2087 LayerID = GetXmlAttributeIDString( aNode, 0 );
2088
2089 //Parse child nodes
2090 XNODE* cNode = aNode->GetChildren();
2091 bool startPointParsed = false;
2092
2093 for( ; cNode; cNode = cNode->GetNext() )
2094 {
2095 wxString cNodeName = cNode->GetName();
2096
2097 if( !startPointParsed && cNodeName == wxT( "PT" ) )
2098 {
2099 startPointParsed = true;
2100 StartPoint.Parse( cNode, aContext );
2101 }
2102 else if( cNodeName == wxT( "ROUTEWIDTH" ) )
2103 {
2104 ROUTE_VERTEX rtVert;
2105 cNode = rtVert.Parse( cNode, aContext );
2106 RouteVertices.push_back( rtVert );
2107
2108 assert( cNode != nullptr );
2109 }
2110 else
2111 {
2112 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "ROUTE" ) );
2113 }
2114 }
2115}
2116
2117
2119 PARSER_CONTEXT* aContext )
2120{
2121 ParseIdentifiers( aNode, aContext );
2122
2123 //Parse child nodes
2124 XNODE* cNode = aNode->GetChildren();
2125 bool routeParsed = false; //assume only one route per connection
2126
2127 for( ; cNode; cNode = cNode->GetNext() )
2128 {
2129 wxString cNodeName = cNode->GetName();
2130
2131 if( ParseSubNode( cNode, aContext ) )
2132 {
2133 continue;
2134 }
2135 else if( !Unrouted && !routeParsed && cNodeName == wxT( "ROUTE" ) )
2136 {
2137 Route.Parse( cNode, aContext );
2138 routeParsed = true;
2139 }
2140 else if( !routeParsed && cNodeName == wxT( "UNROUTE" ) )
2141 {
2142 Unrouted = true;
2144 }
2145 else if( cNode->GetName() == wxT( "TRUNKREF" ) )
2146 {
2147 TrunkID = GetXmlAttributeIDString( cNode, 0 );
2148 }
2149 else
2150 {
2151 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "CONN" ) );
2152 }
2153 }
2154}
2155
2156
2158{
2159 ParseIdentifiers( aNode, aContext );
2160
2161 //Parse child nodes
2162 XNODE* cNode = aNode->GetChildren();
2163
2164 for( ; cNode; cNode = cNode->GetNext() )
2165 {
2166 wxString cNodeName = cNode->GetName();
2167
2168 if( cNodeName == wxT( "JPT" ) )
2169 {
2170 JUNCTION_PCB jpt;
2171 jpt.Parse( cNode, aContext );
2172 Junctions.insert( std::make_pair( jpt.ID, jpt ) );
2173 }
2174 else if( ParseSubNode( cNode, aContext ) )
2175 {
2176 continue;
2177 }
2178 else if( cNodeName == wxT( "PIN" ) )
2179 {
2180 PIN pin;
2181 pin.Parse( cNode, aContext );
2182 Pins.insert( std::make_pair( pin.ID, pin ) );
2183 }
2184 else if( cNodeName == wxT( "VIA" ) )
2185 {
2186 VIA via;
2187 via.Parse( cNode, aContext );
2188 Vias.insert( std::make_pair( via.ID, via ) );
2189 }
2190 else if( cNodeName == wxT( "COPTERM" ) )
2191 {
2192 COPPER_TERMINAL cterm;
2193 cterm.Parse( cNode, aContext );
2194 CopperTerminals.insert( std::make_pair( cterm.ID, cterm ) );
2195 }
2196 else if( cNodeName == wxT( "CONN" ) )
2197 {
2198 CONNECTION_PCB conn;
2199 conn.Parse( cNode, aContext );
2200 Connections.push_back( conn );
2201 }
2202 else
2203 {
2204 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "NET" ) );
2205 }
2206 }
2207}
2208
2209
2211{
2212 wxASSERT( aNode->GetName() == wxT( "POURING" ) );
2213
2217 SliverWidth = GetXmlAttributeIDLong( aNode, 3 );
2221
2222 wxString MinIsolCopStr = GetXmlAttributeIDString( aNode, 7 );
2223
2224 if( MinIsolCopStr == wxT( "NONE" ) )
2226 else
2228
2229 wxString MinDisjCopStr = GetXmlAttributeIDString( aNode, 8 );
2230
2231 if( MinDisjCopStr == wxT( "NONE" ) )
2233 else
2235
2236 XNODE* cNode = aNode->GetChildren();
2237
2238 for( ; cNode; cNode = cNode->GetNext() )
2239 {
2240 wxString cNodeName = cNode->GetName();
2241
2242 if( cNodeName == wxT( "NOPINRELIEF" ) )
2243 {
2244 ThermalReliefOnPads = false;
2245 }
2246 else if( cNodeName == wxT( "NOVIARELIEF" ) )
2247 {
2248 ThermalReliefOnVias = false;
2249 }
2250 else if( cNodeName == wxT( "IGNORETRN" ) )
2251 {
2252 AllowInNoRouting = true;
2253 }
2254 else if( cNodeName == wxT( "BOXPINS" ) )
2255 {
2256 BoxIsolatedPins = true;
2257 }
2258 else if( cNodeName == wxT( "REGENERATE" ) )
2259 {
2260 AutomaticRepour = true;
2261 }
2262 else if( cNodeName == wxT( "AUTOROUTETARGET" ) )
2263 {
2264 TargetForAutorouting = true;
2265 }
2266 else if( cNodeName == wxT( "THERMALCUTOUT" ) )
2267 {
2269 }
2270 else if( cNodeName == wxT( "FILLED" ) )
2271 {
2273 }
2274 else if( cNodeName == wxT( "HATCHCODEREF" ) )
2275 {
2278 }
2279 else
2280 {
2281 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "POURING" ) );
2282 }
2283 }
2284}
2285
2286
2288{
2289 wxASSERT( aNode->GetName() == wxT( "TEMPLATE" ) );
2290
2291 ID = GetXmlAttributeIDString( aNode, 0 );
2292 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
2293 Name = GetXmlAttributeIDString( aNode, 2 );
2294 NetID = GetXmlAttributeIDString( aNode, 3 );
2295 LayerID = GetXmlAttributeIDString( aNode, 4 );
2296
2297 XNODE* cNode = aNode->GetChildren();
2298 bool shapeParsed = false;
2299 bool pouringParsed = false;
2300
2301 for( ; cNode; cNode = cNode->GetNext() )
2302 {
2303 wxString cNodeName = cNode->GetName();
2304
2305 if( !shapeParsed && SHAPE::IsShape( cNode ) )
2306 {
2307 Shape.Parse( cNode, aContext );
2308 shapeParsed = true;
2309 }
2310 else if( !pouringParsed && cNodeName == wxT( "POURING" ) )
2311 {
2312 Pouring.Parse( cNode, aContext );
2313 pouringParsed = true;
2314 }
2315 else if( cNodeName == wxT( "FIX" ) )
2316 {
2317 Fixed = true;
2318 }
2319 else if( cNodeName == wxT( "GROUPREF" ) )
2320 {
2321 GroupID = GetXmlAttributeIDString( cNode, 0 );
2322 }
2323 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2324 {
2325 ReuseBlockRef.Parse( cNode, aContext );
2326 }
2327 else if( cNodeName == wxT( "ATTR" ) )
2328 {
2329 ATTRIBUTE_VALUE attr;
2330 attr.Parse( cNode, aContext );
2331 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2332 }
2333 else
2334 {
2335 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEMPLATE" ) );
2336 }
2337 }
2338}
2339
2340
2342 PARSER_CONTEXT* aContext )
2343{
2344 wxASSERT( aNode->GetName() == wxT( "TERM" ) );
2345
2346 ID = GetXmlAttributeIDLong( aNode, 0 );
2347
2348 XNODE* cNode = aNode->GetChildren();
2349 bool locationParsed = false;
2350
2351 for( ; cNode; cNode = cNode->GetNext() )
2352 {
2353 wxString cNodeName = cNode->GetName();
2354
2355 if( !locationParsed && cNodeName == wxT( "PT" ) )
2356 {
2357 Location.Parse( cNode, aContext );
2358 locationParsed = true;
2359 }
2360 else if( cNodeName == wxT( "FIX" ) )
2361 {
2362 Fixed = true;
2363 }
2364 else
2365 {
2366 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2367 }
2368 }
2369}
2370
2371
2373{
2374 wxASSERT( aNode->GetName() == wxT( "NETREF" ) );
2375
2376 NetID = GetXmlAttributeIDString( aNode, 0 );
2377
2378 XNODE* cNode = aNode->GetChildren();
2379
2380 for( ; cNode; cNode = cNode->GetNext() )
2381 {
2382 wxString cNodeName = cNode->GetName();
2383
2384 if( cNodeName == wxT( "TERM" ) )
2385 {
2386 COPPER_TERM term;
2387 term.Parse( cNode, aContext );
2388 CopperTerminals.insert( std::make_pair( term.ID, term ) );
2389 }
2390 else if( cNodeName == wxT( "FIX" ) )
2391 {
2392 Fixed = true;
2393 }
2394 else
2395 {
2396 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "NETREF" ) );
2397 }
2398 }
2399}
2400
2401
2403{
2404 wxASSERT( aNode->GetName() == wxT( "COPPER" ) );
2405
2406 ID = GetXmlAttributeIDString( aNode, 0 );
2408 LayerID = GetXmlAttributeIDString( aNode, 2 );
2409
2410 XNODE* cNode = aNode->GetChildren();
2411 bool shapeParsed = false;
2412 bool netRefParsed = false;
2413
2414 for( ; cNode; cNode = cNode->GetNext() )
2415 {
2416 wxString cNodeName = cNode->GetName();
2417
2418 if( !shapeParsed && SHAPE::IsShape( cNode ) )
2419 {
2420 Shape.Parse( cNode, aContext );
2421 shapeParsed = true;
2422 }
2423 else if( !netRefParsed && cNodeName == wxT( "NETREF" ) )
2424 {
2425 NetRef.Parse( cNode, aContext );
2426 netRefParsed = true;
2427 }
2428 else if( cNodeName == wxT( "FIX" ) )
2429 {
2430 Fixed = true;
2431 }
2432 else if( cNodeName == wxT( "GROUPREF" ) )
2433 {
2434 GroupID = GetXmlAttributeIDString( cNode, 0 );
2435 }
2436 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2437 {
2438 ReuseBlockRef.Parse( cNode, aContext );
2439 }
2440 else if( cNodeName == wxT( "POURED" ) )
2441 {
2443 }
2444 else if( cNodeName == wxT( "ATTR" ) )
2445 {
2446 ATTRIBUTE_VALUE attr;
2447 attr.Parse( cNode, aContext );
2448 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2449 }
2450 else
2451 {
2452 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEMPLATE" ) );
2453 }
2454 }
2455}
2456
2457
2459{
2460 wxASSERT( aNode->GetName() == wxT( "DRILLTABLE" ) );
2461
2462 ID = GetXmlAttributeIDString( aNode, 0 );
2463 LayerID = GetXmlAttributeIDString( aNode, 1 );
2464
2465 XNODE* cNode = aNode->GetChildren();
2466 bool positionParsed = false;
2467
2468 for( ; cNode; cNode = cNode->GetNext() )
2469 {
2470 wxString cNodeName = cNode->GetName();
2471
2472 if( !positionParsed && cNodeName == wxT( "PT" ) )
2473 {
2474 Position.Parse( cNode, aContext );
2475 positionParsed = true;
2476 }
2477 else if( cNodeName == wxT( "ORIENT" ) )
2478 {
2479 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
2480 }
2481 else if( cNodeName == wxT( "MIRROR" ) )
2482 {
2483 Mirror = true;
2484 }
2485 else if( cNodeName == wxT( "FIX" ) )
2486 {
2487 Fixed = true;
2488 }
2489 else if( cNodeName == wxT( "READABILITY" ) )
2490 {
2491 Readability = ParseReadability( cNode );
2492 }
2493 else if( cNodeName == wxT( "GROUPREF" ) )
2494 {
2495 GroupID = GetXmlAttributeIDString( cNode, 0 );
2496 }
2497 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2498 {
2499 ReuseBlockRef.Parse( cNode, aContext );
2500 }
2501 else
2502 {
2503 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2504 }
2505 }
2506}
2507
2508
2510{
2511 wxASSERT( aNode->GetName() == wxT( "LAYOUT" ) );
2512
2513 XNODE* cNode = aNode->GetChildren();
2514 bool netSynchParsed = false;
2515 bool dimensionsParsed = false;
2516
2517 for( ; cNode; cNode = cNode->GetNext() )
2518 {
2519 wxString cNodeName = cNode->GetName();
2520
2521 if( !netSynchParsed && cNodeName == wxT( "NETSYNCH" ) )
2522 {
2523 std::map<wxString, NETSYNCH> netSynchMap = { { wxT( "WARNING" ), NETSYNCH::WARNING },
2524 { wxT( "FULL" ), NETSYNCH::FULL } };
2525
2526 wxString nsString = GetXmlAttributeIDString( cNode, 0 );
2527
2528 if( netSynchMap.find( nsString ) == netSynchMap.end() )
2529 THROW_UNKNOWN_PARAMETER_IO_ERROR( nsString, aNode->GetName() );
2530
2531 NetSynch = netSynchMap[nsString];
2532 netSynchParsed = true;
2533 }
2534 else if( cNodeName == wxT( "GROUP" ) )
2535 {
2536 GROUP group;
2537 group.Parse( cNode, aContext );
2538 Groups.insert( std::make_pair( group.ID, group ) );
2539 }
2540 else if( cNodeName == wxT( "REUSEBLOCK" ) )
2541 {
2542 REUSEBLOCK reuseblock;
2543 reuseblock.Parse( cNode, aContext );
2544 ReuseBlocks.insert( std::make_pair( reuseblock.ID, reuseblock ) );
2545 }
2546 else if( cNodeName == wxT( "BOARD" ) )
2547 {
2548 CADSTAR_BOARD board;
2549 board.Parse( cNode, aContext );
2550 Boards.insert( std::make_pair( board.ID, board ) );
2551 }
2552 else if( cNodeName == wxT( "FIGURE" ) )
2553 {
2554 FIGURE figure;
2555 figure.Parse( cNode, aContext );
2556 Figures.insert( std::make_pair( figure.ID, figure ) );
2557 }
2558 else if( cNodeName == wxT( "AREA" ) )
2559 {
2560 AREA area;
2561 area.Parse( cNode, aContext );
2562 Areas.insert( std::make_pair( area.ID, area ) );
2563 }
2564 else if( cNodeName == wxT( "COMP" ) )
2565 {
2566 COMPONENT comp;
2567 comp.Parse( cNode, aContext );
2568 Components.insert( std::make_pair( comp.ID, comp ) );
2569 }
2570 else if( cNodeName == wxT( "TRUNK" ) )
2571 {
2572 TRUNK trunk;
2573 trunk.Parse( cNode, aContext );
2574 Trunks.insert( std::make_pair( trunk.ID, trunk ) );
2575 }
2576 else if( cNodeName == wxT( "NET" ) )
2577 {
2578 NET_PCB net;
2579 net.Parse( cNode, aContext );
2580 Nets.insert( std::make_pair( net.ID, net ) );
2581 }
2582 else if( cNodeName == wxT( "TEMPLATE" ) )
2583 {
2584 TEMPLATE temp;
2585 temp.Parse( cNode, aContext );
2586 Templates.insert( std::make_pair( temp.ID, temp ) );
2587 }
2588 else if( cNodeName == wxT( "COPPER" ) )
2589 {
2590 COPPER copper;
2591 copper.Parse( cNode, aContext );
2592 Coppers.insert( std::make_pair( copper.ID, copper ) );
2593 }
2594 else if( cNodeName == wxT( "TEXT" ) )
2595 {
2596 TEXT txt;
2597 txt.Parse( cNode, aContext );
2598 Texts.insert( std::make_pair( txt.ID, txt ) );
2599 }
2600 else if( cNodeName == wxT( "DOCSYMBOL" ) )
2601 {
2602 DOCUMENTATION_SYMBOL docsym;
2603 docsym.Parse( cNode, aContext );
2604 DocumentationSymbols.insert( std::make_pair( docsym.ID, docsym ) );
2605 }
2606 else if( !dimensionsParsed && cNodeName == wxT( "DIMENSIONS" ) )
2607 {
2608 XNODE* dimensionNode = cNode->GetChildren();
2609
2610 for( ; dimensionNode; dimensionNode = dimensionNode->GetNext() )
2611 {
2612 if( DIMENSION::IsDimension( dimensionNode ) )
2613 {
2614 DIMENSION dim;
2615 dim.Parse( dimensionNode, aContext );
2616 Dimensions.insert( std::make_pair( dim.ID, dim ) );
2617 }
2618 else
2619 {
2620 THROW_UNKNOWN_NODE_IO_ERROR( dimensionNode->GetName(), cNodeName );
2621 }
2622 }
2623
2624 dimensionsParsed = true;
2625 }
2626 else if( cNodeName == wxT( "DRILLTABLE" ) )
2627 {
2628 DRILL_TABLE drilltable;
2629 drilltable.Parse( cNode, aContext );
2630 DrillTables.insert( std::make_pair( drilltable.ID, drilltable ) );
2631 }
2632 else if( cNodeName == wxT( "VHIERARCHY" ) )
2633 {
2634 VariantHierarchy.Parse( cNode, aContext );
2635 }
2636 else if( cNodeName == wxT( "ERRORMARK" ) )
2637 {
2638 //ignore (this is a DRC error marker in cadstar)
2639 continue;
2640 }
2641 else
2642 {
2643 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2644 }
2645
2646 aContext->CheckPointCallback();
2647 }
2648}
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.
Hold an XML or S-expression element.
Definition xnode.h:43
XNODE * GetChildren() const
Definition xnode.h:61
XNODE * GetNext() const
Definition xnode.h:66
#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
VECTOR2I location