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