KiCad PCB EDA Suite
Loading...
Searching...
No Matches
ltspice_schematic.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) 2022 Chetan Subhash Shinde<[email protected]>
5 * Copyright (C) 2023 CERN
6 * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
27
29#include <sch_screen.h>
30#include <wx/log.h>
31#include <wx/dir.h>
33#include <sch_sheet.h>
34#include <schematic.h>
35#include <project.h>
36#include <richio.h>
37
38
39void LTSPICE_SCHEMATIC::Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet,
40 const wxFileName& aLibraryFileName, REPORTER* aReporter )
41{
42 std::map<wxString, wxString> mapOfAscFiles;
43 std::map<wxString, wxString> mapOfAsyFiles;
44
45 // Library paths to search (Give highest priority to files contained in same directory)
46 GetAscAndAsyFilePaths( aLibraryFileName.GetPath(), false, mapOfAscFiles, mapOfAsyFiles );
47
48 // TODO: Custom paths go here (non-recursive)
49
50 // Default LTspice libs
51 GetAscAndAsyFilePaths( m_ltspiceDataDir.GetPathWithSep() + wxS( "sub" ), true, mapOfAscFiles,
52 mapOfAsyFiles );
53
54 GetAscAndAsyFilePaths( m_ltspiceDataDir.GetPathWithSep() + wxS( "sym" ), true, mapOfAscFiles,
55 mapOfAsyFiles );
56
57 m_schematic = aSchematic;
58
59 std::queue<wxString> ascFileQueue;
60 ascFileQueue.push( aLibraryFileName.GetName().Lower() );
61
62 LTSPICE_FILE rootAscFile( ascFileQueue.front(), { 0, 0 } );
63
64 rootAscFile.Sheet = aRootSheet;
65 rootAscFile.Screen = new SCH_SCREEN();
66
67 int parentSheetIndex = 0;
68
69 // Asc files who are subschematic in nature
70 std::vector<LTSPICE_FILE> ascFiles;
71
72 ascFiles.push_back( rootAscFile );
73
74 while( !ascFileQueue.empty() )
75 {
76 SCH_SCREEN* screen = nullptr;
77
78 // Reading the .asc file
79 wxString ascFilePath = mapOfAscFiles[ ascFileQueue.front() ];
80 wxString buffer = SafeReadFile( ascFilePath, "r" );
81
82 std::vector<LTSPICE_FILE> newSubSchematicElements = GetSchematicElements( buffer );
83
84 alg::delete_if( newSubSchematicElements,
85 [&mapOfAscFiles]( const LTSPICE_FILE& ii )
86 {
87 return mapOfAscFiles[ii.ElementName].IsEmpty();
88 } );
89
90 for( LTSPICE_FILE& newSubSchematicElement : newSubSchematicElements )
91 {
92 wxString asyName = newSubSchematicElement.ElementName;
93 auto it = mapOfAsyFiles.find( asyName );
94
95 if( it == mapOfAsyFiles.end() )
96 continue;
97
98 wxString asyBuffer = SafeReadFile( it->second, "r" );
99
100 if( IsAsySubsheet( asyBuffer ) )
101 {
102 if( !screen )
103 screen = new SCH_SCREEN( m_schematic );
104
105 newSubSchematicElement.ParentIndex = parentSheetIndex;
106 newSubSchematicElement.Screen = screen;
107 newSubSchematicElement.Sheet = new SCH_SHEET();
108
109 ascFileQueue.push( newSubSchematicElement.ElementName );
110 ascFiles.push_back( newSubSchematicElement );
111 }
112 }
113
114 ascFileQueue.pop();
115
116 parentSheetIndex++;
117 }
118
119 for( unsigned int i = 0; i < ascFiles.size(); i++ )
120 {
121 // Reading the .asc file
122 wxString buffer = SafeReadFile( mapOfAscFiles[ascFiles[i].ElementName], wxS( "r" ) );
123
124 // Getting the keywords to read
125 {
126 std::vector<LTSPICE_FILE> sourceFiles = GetSchematicElements( buffer );
127
128 m_fileCache[ wxS( "asyFiles" ) ] = ReadAsyFiles( sourceFiles, mapOfAsyFiles );
129 m_fileCache[ wxS( "ascFiles" ) ][ wxS( "parentFile" ) ] = buffer;
130
131 for( const LTSPICE_FILE& file : sourceFiles )
132 wxASSERT( file.Sheet == nullptr && file.Screen == nullptr );
133 }
134
135 SCH_SHEET_PATH curSheetPath;
136 SCH_IO_LTSPICE_PARSER parser( this );
137
138 if( i > 0 )
139 {
140 SCH_SHEET* curSheet = ascFiles[i].Sheet;
141 std::map tempAsyMap = ReadAsyFile( ascFiles[i], mapOfAsyFiles );
142 wxString ascFileName = ascFiles[i].ElementName;
143 LT_ASC dummyAsc;
144 LT_SYMBOL tempSymbol = SymbolBuilder( ascFileName, tempAsyMap[ascFileName], dummyAsc );
145 LIB_SYMBOL tempLibSymbol( ascFiles[i].ElementName );
146
147 parser.CreateSymbol( tempSymbol, &tempLibSymbol );
148
149 BOX2I bbox = tempLibSymbol.GetBoundingBox();
150
151 curSheet->SetSize( bbox.GetSize() );
152 curSheet->SetPosition( parser.ToKicadCoords( ascFiles[i].Offset ) + bbox.GetOrigin() );
153 curSheet->SetParent( ascFiles[ascFiles[i].ParentIndex].Sheet );
154
155 SCH_FIELD& sheetNameField = curSheet->GetFields()[SHEETNAME];
156 SCH_FIELD& fileNameSheet = curSheet->GetFields()[SHEETFILENAME];
157 wxString sheetName = wxString::Format( wxS( "%s-subsheet-%d" ),
158 ascFiles[i].ElementName,
159 i );
160
161 sheetNameField.SetText( sheetName );
162 fileNameSheet.SetText( sheetName + ".kicad_sch" );
163
164 curSheet->SetScreen( ascFiles[i].Screen );
165
166 curSheetPath = ascFiles[ascFiles[i].ParentIndex].SheetPath;
167 curSheetPath.push_back( curSheet );
168
169 ascFiles[i].SheetPath = curSheetPath;
170
171 ascFiles[ascFiles[i].ParentIndex].Sheet->GetScreen()->Append( curSheet );
172
173 curSheet->GetScreen()->SetFileName( m_schematic->Prj().GetProjectPath() + sheetName
174 + ".kicad_sch" );
175 }
176 else
177 {
178 SCH_SHEET* curSheet = ascFiles[i].Sheet;
179
180 ascFiles[i].SheetPath.push_back( curSheet );
181 curSheetPath = ascFiles[i].SheetPath;
182 }
183
184 std::vector<wxString> subSchematicAsyFiles;
185
186 for( const LTSPICE_FILE& ascFile : ascFiles )
187 subSchematicAsyFiles.push_back( ascFile.ElementName );
188
189 try
190 {
191 std::vector<LTSPICE_SCHEMATIC::LT_ASC> lt_ascs = StructureBuilder();
192 parser.Parse( &curSheetPath, lt_ascs, subSchematicAsyFiles );
193 }
194 catch( IO_ERROR& e )
195 {
196 aReporter->Report( e.What(), RPT_SEVERITY_ERROR );
197 }
198 }
199}
200
201
202void LTSPICE_SCHEMATIC::GetAscAndAsyFilePaths( const wxDir& aDir, bool aRecursive,
203 std::map<wxString, wxString>& aMapOfAscFiles,
204 std::map<wxString, wxString>& aMapOfAsyFiles,
205 const wxString& aBase )
206{
207 wxString filename;
208
209 {
210 bool cont = aDir.GetFirst( &filename, wxEmptyString, wxDIR_FILES | wxDIR_HIDDEN );
211
212 while( cont )
213 {
214 wxFileName path( aDir.GetName(), filename );
215
216 auto logToMap = [&]( std::map<wxString, wxString>& aMapToLogTo, const wxString& aKey )
217 {
218 if( aMapToLogTo.count( aKey ) )
219 {
220 if( m_reporter )
221 {
222 m_reporter->Report( wxString::Format(
223 _( "File at '%s' was ignored. Using previously found "
224 "file at '%s' instead." ),
225 path.GetFullPath(), aMapToLogTo.at( aKey ) ) );
226 }
227 }
228 else
229 {
230 aMapToLogTo.emplace( aKey, path.GetFullPath() );
231 }
232 };
233
234 wxString elementName1 = ( aBase + path.GetName() ).Lower();
235 wxString elementName2 = path.GetName().Lower();
236 wxString extension = path.GetExt().Lower();
237
238 if( extension == wxS( "asc" ) )
239 {
240 logToMap( aMapOfAscFiles, elementName1 );
241
242 if( !aBase.IsEmpty() )
243 logToMap( aMapOfAscFiles, elementName2 );
244 }
245 else if( extension == wxS( "asy" ) )
246 {
247 logToMap( aMapOfAsyFiles, elementName1 );
248
249 if( !aBase.IsEmpty() )
250 logToMap( aMapOfAsyFiles, elementName2 );
251 }
252
253 cont = aDir.GetNext( &filename );
254 }
255 }
256
257 if( aRecursive )
258 {
259 bool cont = aDir.GetFirst( &filename, wxEmptyString, wxDIR_DIRS | wxDIR_HIDDEN );
260
261 while( cont )
262 {
263 wxFileName path( aDir.GetName(), filename );
264 wxDir subDir( path.GetFullPath() );
265
266 GetAscAndAsyFilePaths( subDir, true, aMapOfAscFiles, aMapOfAsyFiles,
267 filename + wxS( "/" ) );
268
269 cont = aDir.GetNext( &filename );
270 }
271 }
272}
273
274
275std::map<wxString, wxString>
277 const std::map<wxString, wxString>& aAsyFileMap )
278{
279 std::map<wxString, wxString> resultantMap;
280
281 wxString fileName = aSourceFile.ElementName;
282
283 if( aAsyFileMap.count( fileName ) )
284 resultantMap[fileName] = SafeReadFile( aAsyFileMap.at( fileName ), wxS( "r" ) );
285
286 return resultantMap;
287}
288
289
290std::map<wxString, wxString>
291LTSPICE_SCHEMATIC::ReadAsyFiles( const std::vector<LTSPICE_FILE>& aSourceFiles,
292 const std::map<wxString, wxString>& aAsyFileMap )
293{
294 std::map<wxString, wxString> resultantMap;
295
296 for( const LTSPICE_FILE& source : aSourceFiles )
297 {
298 wxString fileName = source.ElementName;
299
300 if( aAsyFileMap.count( fileName ) )
301 resultantMap[fileName] = SafeReadFile( aAsyFileMap.at( fileName ), wxS( "r" ) );
302 }
303
304 return resultantMap;
305}
306
307
308std::vector<LTSPICE_FILE> LTSPICE_SCHEMATIC::GetSchematicElements( const wxString& aAscFile )
309{
310 std::vector<LTSPICE_FILE> resultantArray;
311 wxArrayString lines = wxSplit( aAscFile, '\n' );
312
313 for( const wxString& line : lines )
314 {
315 wxArrayString tokens = wxSplit( line, ' ' );
316
317 if( !tokens.IsEmpty() && tokens[0].Upper() == wxS( "SYMBOL" ) )
318 {
319 wxString elementName( tokens[1] );
320 long posX, posY;
321
322 tokens[2].ToLong( &posX );
323 tokens[3].ToLong( &posY );
324
325 elementName.Replace( '\\', '/' );
326
327 LTSPICE_FILE asyFile( elementName, VECTOR2I( (int) posX, (int) posY ) );
328
329 resultantArray.push_back( asyFile );
330 }
331 }
332
333 return resultantArray;
334}
335
336
337bool LTSPICE_SCHEMATIC::IsAsySubsheet( const wxString& aAsyFile )
338{
339 wxStringTokenizer lines( aAsyFile, "\n" );
340
341 while( lines.HasMoreTokens() )
342 {
343 wxStringTokenizer parts( lines.GetNextToken(), " " );
344
345 if( parts.GetNextToken().IsSameAs( wxS( "SYMATTR" ), false )
346 && parts.GetNextToken().IsSameAs( wxS( "Prefix" ), false ) )
347 {
348 return false;
349 }
350 }
351
352 return true;
353}
354
355
356int LTSPICE_SCHEMATIC::integerCheck( const wxString& aToken, int aLineNumber,
357 const wxString& aFileName )
358{
359 long result;
360
361 if( !aToken.ToLong( &result ) )
362 {
363 THROW_IO_ERROR( wxString::Format( _( "Expecting integer at line %d in file %s" ),
364 aLineNumber,
365 aFileName ) );
366 }
367
368 return (int) result;
369}
370
371
372VECTOR2I LTSPICE_SCHEMATIC::pointCheck( const wxString& aTokenX, const wxString& aTokenY,
373 int aLineNumber, const wxString& aFileName )
374{
375 return VECTOR2I( integerCheck( aTokenX, aLineNumber, aFileName ),
376 integerCheck( aTokenY, aLineNumber, aFileName ) );
377}
378
379
380void LTSPICE_SCHEMATIC::tokensSizeRangeCheck( size_t aActualSize, int aExpectedMin,
381 int aExpectedMax, int aLineNumber,
382 const wxString& aFileName )
383{
384 if( (int) aActualSize < aExpectedMin )
385 {
386 THROW_IO_ERROR( wxString::Format( _( "Expected data missing on line %d in file %s" ),
387 aLineNumber,
388 aFileName ) );
389 }
390 else if( (int) aActualSize > aExpectedMax )
391 {
392 THROW_IO_ERROR( wxString::Format( _( "Extra data found on line %d in file %s" ),
393 aLineNumber,
394 aFileName ) );
395 }
396}
397
398
399void LTSPICE_SCHEMATIC::aggregateAttributeValue( wxArrayString& aTokens, int aIndex )
400{
401 // Merges a value which is across multiple tokens into one token with spaces in between.
402 for( int i = aIndex + 1; i < (int) aTokens.GetCount(); i++ )
403 aTokens[ aIndex ] += " " + aTokens[i];
404}
405
406
408{
409 std::map<int, LINESTYLE> lineStyleMap;
410
411 lineStyleMap[0] = LINESTYLE::SOLID;
412 lineStyleMap[1] = LINESTYLE::DASH;
413 lineStyleMap[2] = LINESTYLE::DOT;
414 lineStyleMap[3] = LINESTYLE::DASHDOT;
415 lineStyleMap[4] = LINESTYLE::DASHDOTDOT;
416
417 if( lineStyleMap.find( aValue ) == lineStyleMap.end() )
418 THROW_IO_ERROR( _( "Expecting 0, 1, 2, 3 or 4" ) );
419
420 return lineStyleMap[ aValue ];
421}
422
423
425{
426 std::map<wxString, LINEWIDTH> lineWidthMap;
427
428 lineWidthMap["NORMAL"] = LINEWIDTH::Normal;
429 lineWidthMap["WIDE"] = LINEWIDTH::Wide;
430
431 if( lineWidthMap.find( aValue.Upper() ) == lineWidthMap.end() )
432 THROW_IO_ERROR( _( "Expecting NORMAL or WIDE" ) );
433
434 return lineWidthMap[ aValue.Upper() ];
435}
436
437
439{
440 std::map<wxString, POLARITY> polarityMap;
441
442 polarityMap["I"] = POLARITY::INPUT;
443 polarityMap["O"] = POLARITY::OUTPUT;
444 polarityMap["B"] = POLARITY::BIDIR;
445 polarityMap["IN"] = POLARITY::INPUT;
446 polarityMap["OUT"] = POLARITY::OUTPUT;
447 polarityMap["BIDIR"] = POLARITY::BIDIR;
448
449 if( polarityMap.find( aValue.Upper() ) == polarityMap.end() )
450 THROW_IO_ERROR( _( "Expecting I, O, B, IN, OUT or BIDIR" ) );
451
452 return polarityMap[ aValue.Upper() ];
453}
454
455
457{
458 std::map<wxString, ORIENTATION> rotationMirrorMap;
459
460 rotationMirrorMap["R0"] = ORIENTATION::R0;
461 rotationMirrorMap["R90"] = ORIENTATION::R90;
462 rotationMirrorMap["R180"] = ORIENTATION::R180;
463 rotationMirrorMap["R270"] = ORIENTATION::R270;
464
465 rotationMirrorMap["M0"] = ORIENTATION::M0;
466 rotationMirrorMap["M90"] = ORIENTATION::M90;
467 rotationMirrorMap["M180"] = ORIENTATION::M180;
468 rotationMirrorMap["M270"] = ORIENTATION::M270;
469
470 if( rotationMirrorMap.find( aValue.Upper() ) == rotationMirrorMap.end() )
471 THROW_IO_ERROR( _( "Expecting R0, R90, R18, R270, M0, M90, M180 or M270" ) );
472
473 return rotationMirrorMap[ aValue.Upper() ];
474}
475
476
478{
479 std::map<wxString, JUSTIFICATION> justificationMap;
480
481 justificationMap["LEFT"] = JUSTIFICATION::LEFT;
482 justificationMap["CENTER"] = JUSTIFICATION::CENTER;
483 justificationMap["RIGHT"] = JUSTIFICATION::RIGHT;
484 justificationMap["VLEFT"] = JUSTIFICATION::VLEFT;
485 justificationMap["VRIGHT"] = JUSTIFICATION::VRIGHT;
486 justificationMap["VCENTER"] = JUSTIFICATION::VCENTER;
487 justificationMap["BOTTOM"] = JUSTIFICATION::BOTTOM;
488 justificationMap["TOP"] = JUSTIFICATION::TOP;
489 justificationMap["VBOTTOM"] = JUSTIFICATION::VBOTTOM;
490 justificationMap["VTOP"] = JUSTIFICATION::VTOP;
491
492 if( justificationMap.find( aValue.Upper() ) == justificationMap.end() )
493 THROW_IO_ERROR( _( "Expecting LEFT, CENTER, RIGHT, TOP, BOTTOM, VLEFT, VRIGHT, VCENTER, VTOP or VBOTTOM" ) );
494
495 return justificationMap[ aValue.Upper() ];
496}
497
498
500{
501 std::map<wxString, JUSTIFICATION> pinJustificationMap;
502
503 pinJustificationMap["BOTTOM"] = JUSTIFICATION::BOTTOM;
504 pinJustificationMap["NONE"] = JUSTIFICATION::NONE;
505 pinJustificationMap["LEFT"] = JUSTIFICATION::LEFT;
506 pinJustificationMap["RIGHT"] = JUSTIFICATION::RIGHT;
507 pinJustificationMap["TOP"] = JUSTIFICATION::TOP;
508 pinJustificationMap["VBOTTOM"] = JUSTIFICATION::VBOTTOM;
509 pinJustificationMap["VLEFT"] = JUSTIFICATION::VLEFT;
510 pinJustificationMap["VRIGHT"] = JUSTIFICATION::VRIGHT;
511 pinJustificationMap["VCENTER"] = JUSTIFICATION::VCENTER;
512 pinJustificationMap["VTOP"] = JUSTIFICATION::VTOP;
513
514 if( pinJustificationMap.find( aValue.Upper() ) == pinJustificationMap.end() )
515 THROW_IO_ERROR( _( "Expecting NONE, BOTTOM, TOP, LEFT, RIGHT, VBOTTOM, VTOP, VCENTER, VLEFT or VRIGHT" ) );
516
517 return pinJustificationMap[ aValue.Upper() ];
518}
519
520
522{
523 std::map<wxString, SYMBOLTYPE> symbolTypeMap;
524
525 symbolTypeMap["CELL"] = SYMBOLTYPE::CELL;
526 symbolTypeMap["BLOCK"] = SYMBOLTYPE::BLOCK;
527
528 if( symbolTypeMap.find( aValue.Upper() ) == symbolTypeMap.end() )
529 THROW_IO_ERROR( _( "Expecting CELL or BLOCK" ) );
530
531 return symbolTypeMap[ aValue.Upper() ];
532}
533
534
535void LTSPICE_SCHEMATIC::removeCarriageReturn( wxString& elementFromLine )
536{
537 if( elementFromLine.EndsWith( '\r' ) )
538 elementFromLine = elementFromLine.BeforeLast( '\r' );
539}
540
541
543 LT_ASC& aAscFile )
544{
545 const std::map<wxString, wxString>& asyFiles = m_fileCache[ wxS( "asyFiles" ) ];
546
547 if( !asyFiles.count( aAscFileName.Lower() ) )
548 THROW_IO_ERROR( wxString::Format( _( "Symbol '%s.asy' not found" ), aAscFileName ) );
549
550 return SymbolBuilder( aAscFileName, asyFiles.at( aAscFileName.Lower() ), aAscFile );
551}
552
554 const wxString& aAsyFileContent,
555 LT_ASC& aAscFile )
556{
557 LT_SYMBOL lt_symbol;
558 int lineNumber = 1;
559
560 lt_symbol.Name = aAscFileName;
563
564 for( wxString line : wxSplit( aAsyFileContent, '\n' ) )
565 {
566 removeCarriageReturn( line );
567
568 wxArrayString tokens = wxSplit( line, ' ' );
569
570 if( tokens.IsEmpty() )
571 continue;
572
573 wxString element = tokens[0].Upper();
574
575 if( element == "LINE" )
576 {
577 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, aAscFileName );
578
579 wxString lineWidth = tokens[1];
580 wxString startPointX = tokens[2];
581 wxString startPointY = tokens[3];
582 wxString endPointX = tokens[4];
583 wxString endPointY = tokens[5];
584
585 LINE lt_line;
586 lt_line.LineWidth = getLineWidth( lineWidth );
587 lt_line.Start = pointCheck( startPointX, startPointY, lineNumber, aAscFileName );
588 lt_line.End = pointCheck( endPointX, endPointY, lineNumber, aAscFileName );
589
590 int lineStyleNumber = 0; // default
591
592 if( tokens.size() == 7 )
593 {
594 wxString lineStyle = tokens[6];
595 lineStyleNumber = integerCheck( lineStyle, lineNumber, aAscFileName );
596 }
597
598 lt_line.LineStyle = getLineStyle( lineStyleNumber );
599
600 lt_symbol.Lines.push_back( lt_line );
601 }
602 else if( element == "RECTANGLE" )
603 {
604 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, aAscFileName );
605
606 wxString lineWidth = tokens[1];
607 wxString botRightX = tokens[2];
608 wxString botRightY = tokens[3];
609 wxString topLeftX = tokens[4];
610 wxString topRightY = tokens[5];
611
612 RECTANGLE rect;
613 rect.LineWidth = getLineWidth( lineWidth );
614 rect.BotRight = pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
615 rect.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
616
617 int lineStyleNumber = 0; // default
618
619 if( tokens.size() == 7 )
620 {
621 wxString lineStyle = tokens[6];
622 lineStyleNumber = integerCheck( lineStyle, lineNumber, aAscFileName );
623 }
624
625 rect.LineStyle = getLineStyle( lineStyleNumber );
626
627 lt_symbol.Rectangles.push_back( rect );
628 }
629 else if( element == "CIRCLE" )
630 {
635 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, aAscFileName );
636
637 wxString lineWidth = tokens[1];
638 wxString botRightX = tokens[2];
639 wxString botRightY = tokens[3];
640 wxString topLeftX = tokens[4];
641 wxString topRightY = tokens[5];
642
643 CIRCLE circle;
644 circle.LineWidth = getLineWidth( lineWidth );
645 circle.BotRight = pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
646 circle.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
647
648 int lineStyleNumber = 0; // default
649
650 if( tokens.size() == 7 )
651 {
652 wxString lineStyle = tokens[6];
653 lineStyleNumber = integerCheck( lineStyle, lineNumber, aAscFileName );
654 }
655
656 circle.LineStyle = getLineStyle( lineStyleNumber );
657
658 lt_symbol.Circles.push_back( circle );
659 }
660 else if( element == "ARC" )
661 {
667 tokensSizeRangeCheck( tokens.size(), 10, 11, lineNumber, aAscFileName );
668
669 wxString lineWidth = tokens[1];
670 wxString botRightX = tokens[2];
671 wxString botRightY = tokens[3];
672 wxString topLeftX = tokens[4];
673 wxString topRightY = tokens[5];
674 wxString arcStartPointX = tokens[6];
675 wxString arcStartPointY = tokens[7];
676 wxString arcEndPointX = tokens[8];
677 wxString arcEndPointY = tokens[9];
678
679 ARC arc;
680 arc.LineWidth = getLineWidth( lineWidth );
681 arc.BotRight = pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
682 arc.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
683 arc.ArcStart = pointCheck( arcStartPointX, arcStartPointY, lineNumber, aAscFileName );
684 arc.ArcEnd = pointCheck( arcEndPointX, arcEndPointY, lineNumber, aAscFileName );
685
686 int lineStyleNumber = 0; // default
687
688 if( tokens.size() == 11 )
689 {
690 wxString lineStyle = tokens[10];
691 lineStyleNumber = integerCheck( lineStyle, lineNumber, aAscFileName );
692 }
693
694 arc.LineStyle = getLineStyle( lineStyleNumber );
695
696 lt_symbol.Arcs.push_back( arc );
697 }
698 else if( element == "WINDOW" )
699 {
700 tokensSizeRangeCheck( tokens.size(), 6, 6, lineNumber, aAscFileName );
701
702 wxString number = tokens[1];
703 wxString windowPosX = tokens[2];
704 wxString windowPosY = tokens[3];
705 wxString justification = tokens[4];
706 wxString fontSize = tokens[5];
707
708 LT_WINDOW window;
709 window.WindowNumber = integerCheck( number, lineNumber, aAscFileName );
710 window.Position = pointCheck( windowPosX, windowPosY, lineNumber, aAscFileName );
711 window.Justification = getTextJustification( justification );
712 window.FontSize = integerCheck( fontSize, lineNumber, aAscFileName );
713
714 // LTSpice appears to ignore hidden property from .asy files
715 if( window.FontSize == 0 )
716 window.FontSize = 2;
717
718 lt_symbol.Windows.push_back( window );
719 }
720 else if( element == "SYMATTR" )
721 {
722 aggregateAttributeValue( tokens, 2 );
723
724 tokensSizeRangeCheck( tokens.size(), 3, INT_MAX, lineNumber, aAscFileName );
725
726 wxString key = tokens[1];
727 wxString value = tokens[2];
728
729 if( value == wxS( "\"\"" ) )
730 value = wxEmptyString;
731
732 lt_symbol.SymAttributes[ key.Upper() ] = value;
733 }
734 else if( element == "PIN" )
735 {
736 tokensSizeRangeCheck( tokens.size(), 5, 5, lineNumber, aAscFileName );
737
738 wxString pinLocationX = tokens[1];
739 wxString pinLocationY = tokens[2];
740 wxString Justification = tokens[3];
741 wxString nameOffSet = tokens[4];
742
743 LT_PIN pin;
744 pin.PinLocation = pointCheck( pinLocationX, pinLocationY, lineNumber,aAscFileName );
745 pin.PinJustification = getPinJustification( Justification );
746 pin.NameOffSet = integerCheck( nameOffSet, lineNumber, aAscFileName );
747
748 lt_symbol.Pins.push_back( pin );
749 }
750 else if( element == "PINATTR" )
751 {
752 aggregateAttributeValue( tokens, 2 );
753
754 tokensSizeRangeCheck( tokens.size(), 3, INT_MAX, lineNumber, aAscFileName );
755
756 wxString name = tokens[1];
757 wxString Value = tokens[2];
758
759 lt_symbol.Pins.back().PinAttribute.insert( { name, Value } );
760 }
761 else if( element == "SYMBOLTYPE" )
762 {
763 tokensSizeRangeCheck( tokens.size(), 2, 2, lineNumber, aAscFileName );
764
765 wxString symbolType = tokens[1];
766
767 lt_symbol.SymbolType = getSymbolType( symbolType );
768 }
769
770 lineNumber++;
771 }
772
773 return lt_symbol;
774}
775
776
777std::vector<LTSPICE_SCHEMATIC::LT_ASC> LTSPICE_SCHEMATIC::StructureBuilder()
778{
779 // Initialising Symbol Struct
780
781 std::vector<LT_ASC> ascFiles;
782
783 for( const auto& [ fileName, contents ] : m_fileCache[ wxS( "ascFiles" ) ] )
784 {
785 LT_ASC ascFile;
786 std::vector<LT_SYMBOL> symbolArray;
787
788 ascFile.SheetSize = VECTOR2I( 0, 0 );
789 ascFile.Symbols = symbolArray;
790 ascFile.Version = 0;
791 ascFile.SheetNumber = 0;
792
793 int lineNumber = 1;
794
795 for( wxString line : wxSplit( contents, '\n' ) )
796 {
797 removeCarriageReturn( line );
798
799 wxArrayString tokens = wxSplit( line, ' ' );
800
801 if( tokens.IsEmpty() )
802 continue;
803
804 wxString element = tokens[0].Upper();
805
806 if( element == "SHEET" )
807 {
808 tokensSizeRangeCheck( tokens.size(), 4, 4, lineNumber, fileName );
809
810 wxString sheetNumber = tokens[1];
811 wxString sheetWidth = tokens[2];
812 wxString sheetHeight = tokens[3];
813
814 ascFile.SheetNumber = integerCheck( sheetNumber, lineNumber, fileName );
815 ascFile.SheetSize = pointCheck( sheetWidth, sheetHeight, lineNumber, fileName );
816 }
817 else if( element == "SYMBOL" )
818 {
819 tokensSizeRangeCheck( tokens.size(), 5, 5, lineNumber, fileName );
820
821 wxString symbolName = tokens[1];
822 wxString posX = tokens[2];
823 wxString posY = tokens[3];
824 wxString rotate_mirror_option = tokens[4];
825
826 symbolName.Replace( '\\', '/' );
827
828 LT_SYMBOL lt_symbol = SymbolBuilder( symbolName, ascFile );
829 lt_symbol.Offset = pointCheck( posX, posY, lineNumber, fileName );
830 lt_symbol.SymbolOrientation = getSymbolRotationOrMirror( rotate_mirror_option );
831
832 ascFile.Symbols.push_back( lt_symbol );
833 ascFile.BoundingBox.Merge( lt_symbol.Offset );
834 }
835 else if( element == "WIRE" )
836 {
837 tokensSizeRangeCheck( tokens.size(), 5, 5, lineNumber, fileName );
838
839 wxString startPointX = tokens[1];
840 wxString startPointY = tokens[2];
841 wxString endPointX = tokens[3];
842 wxString endPointY = tokens[4];
843
844 WIRE wire;
845 wire.Start = pointCheck( startPointX, startPointY, lineNumber, fileName );
846 wire.End = pointCheck( endPointX, endPointY, lineNumber, fileName );
847
848 ascFile.Wires.push_back( wire );
849 ascFile.BoundingBox.Merge( wire.Start );
850 ascFile.BoundingBox.Merge( wire.End );
851 }
852 else if( element == "FLAG" )
853 {
854 tokensSizeRangeCheck( tokens.size(), 4, 4, lineNumber, fileName );
855
856 wxString posX = tokens[1];
857 wxString posY = tokens[2];
858 wxString name = tokens[3];
859
860 FLAG flag;
861 flag.Offset = pointCheck( posX, posY, lineNumber, fileName );
862 flag.Value = name;
863 flag.FontSize = 2;
864
865 ascFile.Flags.push_back( flag );
866 ascFile.BoundingBox.Merge( flag.Offset );
867 }
868 else if( element == "DATAFLAG" )
869 {
870 tokensSizeRangeCheck( tokens.size(), 4, 4, lineNumber, fileName );
871
872 wxString posX = tokens[1];
873 wxString posY = tokens[2];
874 wxString expression = tokens[3];
875
877 flag.Offset = pointCheck( posX, posY, lineNumber, fileName );
878 flag.Expression = expression;
879 flag.FontSize = 2;
880
881 ascFile.DataFlags.push_back( flag );
882 ascFile.BoundingBox.Merge( flag.Offset );
883 }
884 else if( element == "WINDOW" )
885 {
886 tokensSizeRangeCheck( tokens.size(), 6, 6, lineNumber, fileName );
887
888 wxString number = tokens[1];
889 wxString windowPosX = tokens[2];
890 wxString windowPosY = tokens[3];
891 wxString justification = tokens[4];
892 wxString fontSize = tokens[5];
893
894 int windowNumber = integerCheck( number, lineNumber, fileName );
895 LT_WINDOW* window = nullptr;
896
897 // Overwrite an existing window from the symbol definition
898 for( LT_WINDOW& candidate : ascFile.Symbols.back().Windows )
899 {
900 if( candidate.WindowNumber == windowNumber )
901 {
902 window = &candidate;
903 break;
904 }
905 }
906
907 if( !window )
908 {
909 ascFile.Symbols.back().Windows.emplace_back( LT_WINDOW() );
910 window = &ascFile.Symbols.back().Windows.back();
911 }
912
913 window->WindowNumber = windowNumber;
914 window->Position = pointCheck( windowPosX, windowPosY, lineNumber, fileName );
915 window->Justification = getTextJustification( justification );
916 window->FontSize = integerCheck( fontSize, lineNumber, fileName );
917
918 ascFile.BoundingBox.Merge( window->Position );
919 }
920 else if( element == "SYMATTR" )
921 {
922 tokensSizeRangeCheck( tokens.size(), 3, INT_MAX, lineNumber, fileName );
923
924 aggregateAttributeValue( tokens, 2 );
925
926 wxString name = tokens[1];
927 wxString value = tokens[2];
928
929 if( value == wxS( "\"\"" ) )
930 value = wxEmptyString;
931
932 ascFile.Symbols.back().SymAttributes[ name.Upper() ] = value;
933 }
934 else if( element == "LINE" )
935 {
936 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, fileName );
937
938 wxString lineWidth = tokens[1];
939 wxString startPointX = tokens[2];
940 wxString startPointY = tokens[3];
941 wxString endPointX = tokens[4];
942 wxString endPointY = tokens[5];
943
944 LINE lt_line;
945 lt_line.LineWidth = getLineWidth( lineWidth );
946 lt_line.Start = pointCheck( startPointX, startPointY, lineNumber, fileName );
947 lt_line.End = pointCheck( endPointX, endPointY, lineNumber, fileName );
948
949 int lineStyleNumber = 0; // default
950
951 if( tokens.size() == 7 )
952 {
953 wxString lineStyle = tokens[6];
954 lineStyleNumber = integerCheck( lineStyle, lineNumber, fileName );
955 }
956
957 lt_line.LineStyle = getLineStyle( lineStyleNumber );
958
959 ascFile.Lines.push_back( lt_line );
960 ascFile.BoundingBox.Merge( lt_line.Start );
961 ascFile.BoundingBox.Merge( lt_line.End );
962 }
963 else if( element == "RECTANGLE" )
964 {
965 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, fileName );
966
967 wxString lineWidth = tokens[1];
968 wxString botRightX = tokens[2];
969 wxString botRightY = tokens[3];
970 wxString topLeftX = tokens[4];
971 wxString topRightY = tokens[5];
972
973 RECTANGLE rect;
974 rect.LineWidth = getLineWidth( tokens[1] );
975 rect.BotRight = pointCheck( botRightX, botRightY, lineNumber, fileName );
976 rect.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, fileName );
977
978 int lineStyleNumber = 0; // default
979
980 if( tokens.size() == 7 )
981 {
982 wxString lineStyle = tokens[6];
983 lineStyleNumber = integerCheck( lineStyle, lineNumber, fileName );
984 }
985
986 rect.LineStyle = getLineStyle( lineStyleNumber );
987
988 ascFile.Rectangles.push_back( rect );
989 ascFile.BoundingBox.Merge( rect.TopLeft );
990 ascFile.BoundingBox.Merge( rect.BotRight );
991 }
992 else if( element == "CIRCLE" )
993 {
994 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, fileName );
995
996 wxString lineWidth = tokens[1];
997 wxString botRightX = tokens[2];
998 wxString botRightY = tokens[3];
999 wxString topLeftX = tokens[4];
1000 wxString topRightY = tokens[5];
1001
1002 CIRCLE circle;
1003 circle.LineWidth = getLineWidth( lineWidth );
1004 circle.BotRight = pointCheck( botRightX, botRightY, lineNumber, fileName );
1005 circle.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, fileName );
1006
1007 int lineStyleNumber = 0; // default
1008
1009 if( tokens.size() == 7 )
1010 {
1011 wxString lineStyle = tokens[6];
1012 lineStyleNumber = integerCheck( lineStyle, lineNumber, fileName );
1013 }
1014
1015 circle.LineStyle = getLineStyle( lineStyleNumber );
1016
1017 ascFile.Circles.push_back( circle );
1018 ascFile.BoundingBox.Merge( circle.TopLeft );
1019 ascFile.BoundingBox.Merge( circle.BotRight );
1020 }
1021 else if( element == "ARC" )
1022 {
1028 tokensSizeRangeCheck( tokens.size(), 10, 11, lineNumber, fileName );
1029
1030 wxString lineWidth = tokens[1];
1031 wxString botRightX = tokens[2];
1032 wxString botRightY = tokens[3];
1033 wxString topLeftX = tokens[4];
1034 wxString topRightY = tokens[5];
1035 wxString arcStartPointX = tokens[6];
1036 wxString arcStartPointY = tokens[7];
1037 wxString arcEndPointX = tokens[8];
1038 wxString arcEndPointY = tokens[9];
1039
1040 ARC arc;
1041 arc.LineWidth = getLineWidth( lineWidth );
1042 arc.BotRight = pointCheck( botRightX, botRightY, lineNumber, fileName );
1043 arc.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, fileName );
1044 arc.ArcEnd = pointCheck( arcStartPointX, arcStartPointY, lineNumber, fileName );
1045 arc.ArcStart = pointCheck( arcEndPointX, arcEndPointY, lineNumber, fileName );
1046
1047 int lineStyleNumber = 0; // default
1048
1049 if( tokens.size() == 11 )
1050 {
1051 wxString lineStyle = tokens[10];
1052 lineStyleNumber = integerCheck( lineStyle, lineNumber, fileName );
1053 }
1054
1055 arc.LineStyle = getLineStyle( lineStyleNumber );
1056
1057 ascFile.Arcs.push_back( arc );
1058 ascFile.BoundingBox.Merge( arc.TopLeft );
1059 ascFile.BoundingBox.Merge( arc.BotRight );
1060 }
1061 else if( element == "IOPIN" )
1062 {
1063 tokensSizeRangeCheck( tokens.size(), 4, 4, lineNumber, fileName );
1064
1065 wxString pinLocationX = tokens[1];
1066 wxString pinLocationY = tokens[2];
1067 wxString pinPolarity = tokens[3];
1068
1069 IOPIN iopin;
1070 iopin.Location = pointCheck( pinLocationX, pinLocationY, lineNumber, fileName );
1071 iopin.Polarity = getPolarity( pinPolarity );
1072
1073 ascFile.Iopins.push_back( iopin );
1074 ascFile.BoundingBox.Merge( iopin.Location );
1075 }
1076 else if( element == "TEXT" )
1077 {
1078 aggregateAttributeValue( tokens, 5 );
1079
1080 tokensSizeRangeCheck( tokens.size(), 6, INT_MAX, lineNumber, fileName );
1081
1082 wxString positionX = tokens[1];
1083 wxString positionY = tokens[2];
1084 wxString justification = tokens[3];
1085 wxString fontSize = tokens[4];
1086 wxString value = tokens[5];
1087
1088 TEXT text;
1089 text.Offset = pointCheck( positionX, positionY, lineNumber, fileName );
1090 text.Justification = getTextJustification( justification );
1091 text.FontSize = integerCheck( fontSize, lineNumber, fileName );
1092
1093 if( value.StartsWith( wxS( "!" ), &text.Value ) )
1094 text.Value.Replace( wxS( "! " ), wxS( "\n" ) ); // replace subsequent ! with \n
1095 else if( value.StartsWith( wxS( ";" ), &text.Value ) )
1096 text.Value.Replace( wxS( "; " ), wxS( "\n" ) ); // replace subsequent ; with \n
1097 else
1098 text.Value = value;
1099
1100 text.Value.Replace( wxS( "\\n" ), wxS( "\n" ) );
1101
1102 ascFile.Texts.push_back( text );
1103 ascFile.BoundingBox.Merge( text.Offset );
1104 }
1105 else if( element == "BUSTAP" )
1106 {
1107 tokensSizeRangeCheck( tokens.size(), 5, 5, lineNumber, fileName );
1108
1109 wxString startPointX = tokens[1];
1110 wxString startPointY = tokens[2];
1111 wxString endPointX = tokens[3];
1112 wxString endPointY = tokens[4];
1113
1114 BUSTAP bustap;
1115 bustap.Start = pointCheck( startPointX, startPointY, lineNumber, fileName );
1116 bustap.End = pointCheck( endPointX, endPointY, lineNumber, fileName );
1117
1118 ascFile.Bustap.push_back( bustap );
1119 ascFile.BoundingBox.Merge( bustap.Start );
1120 ascFile.BoundingBox.Merge( bustap.End );
1121 }
1122 else if( element == "VERSION" )
1123 {
1124 wxString versionNumber = tokens[1];
1125 ascFile.Version = integerCheck( versionNumber, lineNumber, fileName );
1126 }
1127
1128 lineNumber++;
1129 }
1130
1131 ascFiles.push_back( ascFile );
1132 }
1133
1134 return ascFiles;
1135}
1136
1137
const char * name
Definition: DXF_plotter.cpp:57
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:658
constexpr const Vec & GetOrigin() const
Definition: box2.h:210
constexpr const SizeVec & GetSize() const
Definition: box2.h:206
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:104
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
Define a library symbol object.
Definition: lib_symbol.h:78
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: lib_symbol.h:243
static VECTOR2I pointCheck(const wxString &aTokenX, const wxString &aTokenY, int aLineNumber, const wxString &aFileName)
static SYMBOLTYPE getSymbolType(const wxString &aValue)
std::vector< LT_ASC > StructureBuilder()
Build Intermediate data structure.
std::vector< LTSPICE_FILE > GetSchematicElements(const wxString &aAscFile)
Used to get symbols list present in asc file.
LT_SYMBOL SymbolBuilder(const wxString &aAscFileName, LT_ASC &aAscFile)
POLARITY
Polarity enum represents polarity of pin.
JUSTIFICATION
Defines in what ways the PIN or TEXT can be justified.
void GetAscAndAsyFilePaths(const wxDir &aDir, bool aRecursive, std::map< wxString, wxString > &aMapOfAscFiles, std::map< wxString, wxString > &aMapOfAsyFiles, const wxString &aBase=wxEmptyString)
Used to get file path for Asc and Asy files.
static ORIENTATION getSymbolRotationOrMirror(const wxString &aValue)
bool IsAsySubsheet(const wxString &aAsyFile)
Check if the asy file content indicates that we need to load subsheet.
static POLARITY getPolarity(const wxString &aValue)
static void tokensSizeRangeCheck(size_t aActualSize, int aExpectedMin, int aExpectedMax, int aLineNumber, const wxString &aFileName)
Used to check size of the token generated from split function.
static LINEWIDTH getLineWidth(const wxString &aValue)
ORIENTATION
Defines different types or rotation and mirror operation can be applied to a LT_SYMBOL.
static void aggregateAttributeValue(wxArrayString &aTokens, int aIndex)
Join value present across multiple tokens into one.
void Load(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const wxFileName &aLibraryFileName, REPORTER *aReporter)
The main function responsible for loading the .asc and .asy files.
static int integerCheck(const wxString &aToken, int aLineNumber, const wxString &aFileName)
Used to check if the given token in integer or not.
wxFileName m_ltspiceDataDir
std::map< wxString, std::map< wxString, wxString > > m_fileCache
static JUSTIFICATION getTextJustification(const wxString &aValue)
static JUSTIFICATION getPinJustification(const wxString &aValue)
std::map< wxString, wxString > ReadAsyFile(const LTSPICE_FILE &aSourceFile, const std::map< wxString, wxString > &aAsyFileMap)
SYMBOLTYPE
Type of Symbol loaded from asc and asy file.
std::map< wxString, wxString > ReadAsyFiles(const std::vector< LTSPICE_FILE > &aSourceFiles, const std::map< wxString, wxString > &aAsyFileMap)
The function returns a map.
static void removeCarriageReturn(wxString &elementFromLine)
static LINESTYLE getLineStyle(int aValue)
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:135
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:72
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
Holds all the data relating to one schematic.
Definition: schematic.h:77
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:92
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1213
The class is been used for loading the asc and asy files in intermediate data structure.
void Parse(SCH_SHEET_PATH *aSheet, std::vector< LTSPICE_SCHEMATIC::LT_ASC > &outLT_ASCs, const std::vector< wxString > &aAsyFileNames)
Function responsible for loading the .asc and .asy files in intermediate data structure.
int ToKicadCoords(int aCoordinate)
Method converts ltspice coordinate(i.e scale) to kicad coordinates.
void CreateSymbol(LTSPICE_SCHEMATIC::LT_SYMBOL &aLtSymbol, LIB_SYMBOL *aLibSymbol)
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:118
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
void SetSize(const VECTOR2I &aSize)
Definition: sch_sheet.h:113
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:93
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_sheet.cpp:998
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:110
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:173
#define _(s)
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:39
void delete_if(_Container &__c, _Function &&__f)
Deletes all values from __c for which __f returns true.
Definition: kicad_algo.h:174
@ RPT_SEVERITY_ERROR
wxString SafeReadFile(const wxString &aFilePath, const wxString &aReadType)
Nominally opens a file and reads it into a string.
Definition: richio.cpp:93
@ SHEETNAME
Definition: sch_sheet.h:45
@ SHEETFILENAME
Definition: sch_sheet.h:46
SCH_SCREEN * Screen
SCH_SHEET * Sheet
wxString ElementName
The ARC is represented inside a rectangle whose opposite site are given.
The CIRCLE is represented in Ltpsice inside a rectangle whose two opposite points and line style are ...
IOPIN is special contact on symbol used for IO operations.
A struct to hold .asc file definition.
std::vector< CIRCLE > Circles
std::vector< IOPIN > Iopins
std::vector< BUSTAP > Bustap
std::vector< LT_SYMBOL > Symbols
std::vector< TEXT > Texts
std::vector< DATAFLAG > DataFlags
std::vector< LINE > Lines
std::vector< WIRE > Wires
std::vector< RECTANGLE > Rectangles
std::vector< FLAG > Flags
A struct to hold SYMBOL definition.
std::map< wxString, wxString > SymAttributes
std::vector< RECTANGLE > Rectangles
std::vector< LT_WINDOW > Windows
std::vector< LT_PIN > Pins
std::vector< CIRCLE > Circles
A 4-sided polygon with opposite equal sides, used in representing shapes.
A metallic connection, used for transfer, between two points or pin.
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691
Definition of file extensions used in Kicad.