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