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 along
19 * with this program. If not, see <http://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 {
211 bool cont = aDir.GetFirst( &filename, wxEmptyString, wxDIR_FILES | wxDIR_HIDDEN );
212
213 while( cont )
214 {
215 wxFileName path( aDir.GetName(), filename );
216
217 auto logToMap = [&]( std::map<wxString, wxString>& aMapToLogTo, const wxString& aKey )
218 {
219 if( aMapToLogTo.count( aKey ) )
220 {
221 if( m_reporter )
222 {
223 m_reporter->Report( wxString::Format( _( "File at '%s' was ignored. Using previously "
224 "found file at '%s' instead." ),
225 path.GetFullPath(),
226 aMapToLogTo.at( aKey ) ) );
227 }
228 }
229 else
230 {
231 aMapToLogTo.emplace( aKey, path.GetFullPath() );
232 }
233 };
234
235 // Add dir1/dir2/cmp, dir2/cmp, cmp
236 wxString extension = path.GetExt().Lower();
237
238 for( size_t i = 0; i < aBaseDirs.size() + 1; i++ )
239 {
240 wxString alias;
241
242 for( size_t j = i; j < aBaseDirs.size(); j++ )
243 alias << aBaseDirs[j].Lower() << '/';
244
245 alias << path.GetName().Lower();
246
247 if( extension == wxS( "asc" ) )
248 logToMap( aMapOfAscFiles, alias );
249 else if( extension == wxS( "asy" ) )
250 logToMap( aMapOfAsyFiles, alias );
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 std::vector<wxString> newBase = aBaseDirs;
267 newBase.push_back( filename );
268
269 GetAscAndAsyFilePaths( subDir, true, aMapOfAscFiles, aMapOfAsyFiles, newBase );
270
271 cont = aDir.GetNext( &filename );
272 }
273 }
274}
275
276
277std::map<wxString, wxString>
279 const std::map<wxString, wxString>& aAsyFileMap )
280{
281 std::map<wxString, wxString> resultantMap;
282
283 wxString fileName = aSourceFile.ElementName;
284
285 if( aAsyFileMap.count( fileName ) )
286 resultantMap[fileName] = SafeReadFile( aAsyFileMap.at( fileName ), wxS( "r" ) );
287
288 return resultantMap;
289}
290
291
292std::map<wxString, wxString>
293LTSPICE_SCHEMATIC::ReadAsyFiles( const std::vector<LTSPICE_FILE>& aSourceFiles,
294 const std::map<wxString, wxString>& aAsyFileMap )
295{
296 std::map<wxString, wxString> resultantMap;
297
298 for( const LTSPICE_FILE& source : aSourceFiles )
299 {
300 wxString fileName = source.ElementName;
301
302 if( aAsyFileMap.count( fileName ) )
303 resultantMap[fileName] = SafeReadFile( aAsyFileMap.at( fileName ), wxS( "r" ) );
304 }
305
306 return resultantMap;
307}
308
309
310std::vector<LTSPICE_FILE> LTSPICE_SCHEMATIC::GetSchematicElements( const wxString& aAscFile )
311{
312 std::vector<LTSPICE_FILE> resultantArray;
313 wxArrayString lines = wxSplit( aAscFile, '\n' );
314
315 for( const wxString& line : lines )
316 {
317 wxArrayString tokens = wxSplit( line, ' ' );
318
319 if( tokens.size() >= 4 && tokens[0].Upper() == wxS( "SYMBOL" ) )
320 {
321 wxString elementName( tokens[1] );
322 long posX, posY;
323
324 tokens[2].ToLong( &posX );
325 tokens[3].ToLong( &posY );
326
327 elementName.Replace( '\\', '/' );
328
329 LTSPICE_FILE asyFile( elementName, VECTOR2I( (int) posX, (int) posY ) );
330
331 resultantArray.push_back( asyFile );
332 }
333 }
334
335 return resultantArray;
336}
337
338
339bool LTSPICE_SCHEMATIC::IsAsySubsheet( const wxString& aAsyFile )
340{
341 wxStringTokenizer lines( aAsyFile, "\n" );
342
343 while( lines.HasMoreTokens() )
344 {
345 wxStringTokenizer parts( lines.GetNextToken(), " " );
346
347 if( parts.GetNextToken().IsSameAs( wxS( "SYMATTR" ), false )
348 && parts.GetNextToken().IsSameAs( wxS( "Prefix" ), false ) )
349 {
350 return false;
351 }
352 }
353
354 return true;
355}
356
357
358int LTSPICE_SCHEMATIC::integerCheck( const wxString& aToken, int aLineNumber,
359 const wxString& aFileName )
360{
361 long result;
362
363 if( !aToken.ToLong( &result ) )
364 {
365 THROW_IO_ERROR( wxString::Format( _( "Expecting integer at line %d in file %s" ),
366 aLineNumber,
367 aFileName ) );
368 }
369
370 return (int) result;
371}
372
373
374VECTOR2I LTSPICE_SCHEMATIC::pointCheck( const wxString& aTokenX, const wxString& aTokenY,
375 int aLineNumber, const wxString& aFileName )
376{
377 return VECTOR2I( integerCheck( aTokenX, aLineNumber, aFileName ),
378 integerCheck( aTokenY, aLineNumber, aFileName ) );
379}
380
381
382void LTSPICE_SCHEMATIC::tokensSizeRangeCheck( size_t aActualSize, int aExpectedMin,
383 int aExpectedMax, int aLineNumber,
384 const wxString& aFileName )
385{
386 if( (int) aActualSize < aExpectedMin )
387 {
388 THROW_IO_ERROR( wxString::Format( _( "Expected data missing on line %d in file %s" ),
389 aLineNumber,
390 aFileName ) );
391 }
392 else if( (int) aActualSize > aExpectedMax )
393 {
394 THROW_IO_ERROR( wxString::Format( _( "Extra data found on line %d in file %s" ),
395 aLineNumber,
396 aFileName ) );
397 }
398}
399
400
401void LTSPICE_SCHEMATIC::aggregateAttributeValue( wxArrayString& aTokens, int aIndex )
402{
403 // Merges a value which is across multiple tokens into one token with spaces in between.
404 for( int i = aIndex + 1; i < (int) aTokens.GetCount(); i++ )
405 aTokens[ aIndex ] += " " + aTokens[i];
406}
407
408
410{
411 std::map<int, LINESTYLE> lineStyleMap;
412
413 lineStyleMap[0] = LINESTYLE::SOLID;
414 lineStyleMap[1] = LINESTYLE::DASH;
415 lineStyleMap[2] = LINESTYLE::DOT;
416 lineStyleMap[3] = LINESTYLE::DASHDOT;
417 lineStyleMap[4] = LINESTYLE::DASHDOTDOT;
418
419 if( lineStyleMap.find( aValue ) == lineStyleMap.end() )
420 THROW_IO_ERROR( _( "Expecting 0, 1, 2, 3 or 4" ) );
421
422 return lineStyleMap[ aValue ];
423}
424
425
427{
428 std::map<wxString, LINEWIDTH> lineWidthMap;
429
430 lineWidthMap["NORMAL"] = LINEWIDTH::Normal;
431 lineWidthMap["WIDE"] = LINEWIDTH::Wide;
432
433 if( lineWidthMap.find( aValue.Upper() ) == lineWidthMap.end() )
434 THROW_IO_ERROR( _( "Expecting NORMAL or WIDE" ) );
435
436 return lineWidthMap[ aValue.Upper() ];
437}
438
439
441{
442 std::map<wxString, POLARITY> polarityMap;
443
444 polarityMap["I"] = POLARITY::PIN_INPUT;
445 polarityMap["O"] = POLARITY::OUTPUT;
446 polarityMap["B"] = POLARITY::BIDIR;
447 polarityMap["IN"] = POLARITY::PIN_INPUT;
448 polarityMap["OUT"] = POLARITY::OUTPUT;
449 polarityMap["BIDIR"] = POLARITY::BIDIR;
450
451 if( polarityMap.find( aValue.Upper() ) == polarityMap.end() )
452 THROW_IO_ERROR( _( "Expecting I, O, B, IN, OUT or BIDIR" ) );
453
454 return polarityMap[ aValue.Upper() ];
455}
456
457
459{
460 std::map<wxString, ORIENTATION> rotationMirrorMap;
461
462 rotationMirrorMap["R0"] = ORIENTATION::R0;
463 rotationMirrorMap["R90"] = ORIENTATION::R90;
464 rotationMirrorMap["R180"] = ORIENTATION::R180;
465 rotationMirrorMap["R270"] = ORIENTATION::R270;
466
467 rotationMirrorMap["M0"] = ORIENTATION::M0;
468 rotationMirrorMap["M90"] = ORIENTATION::M90;
469 rotationMirrorMap["M180"] = ORIENTATION::M180;
470 rotationMirrorMap["M270"] = ORIENTATION::M270;
471
472 if( rotationMirrorMap.find( aValue.Upper() ) == rotationMirrorMap.end() )
473 THROW_IO_ERROR( _( "Expecting R0, R90, R18, R270, M0, M90, M180 or M270" ) );
474
475 return rotationMirrorMap[ aValue.Upper() ];
476}
477
478
480{
481 std::map<wxString, JUSTIFICATION> justificationMap;
482
483 justificationMap["LEFT"] = JUSTIFICATION::LEFT;
484 justificationMap["CENTER"] = JUSTIFICATION::CENTER;
485 justificationMap["RIGHT"] = JUSTIFICATION::RIGHT;
486 justificationMap["VLEFT"] = JUSTIFICATION::VLEFT;
487 justificationMap["VRIGHT"] = JUSTIFICATION::VRIGHT;
488 justificationMap["VCENTER"] = JUSTIFICATION::VCENTER;
489 justificationMap["BOTTOM"] = JUSTIFICATION::BOTTOM;
490 justificationMap["TOP"] = JUSTIFICATION::TOP;
491 justificationMap["VBOTTOM"] = JUSTIFICATION::VBOTTOM;
492 justificationMap["VTOP"] = JUSTIFICATION::VTOP;
493 justificationMap["INVISIBLE"] = JUSTIFICATION::INVISIBLE;
494
495 if( justificationMap.find( aValue.Upper() ) == justificationMap.end() )
496 THROW_IO_ERROR( _( "Expecting LEFT, CENTER, RIGHT, TOP, BOTTOM, VLEFT, VRIGHT, VCENTER, "
497 "VTOP, VBOTTOM or INVISIBLE" ) );
498
499 return justificationMap[ aValue.Upper() ];
500}
501
502
504{
505 std::map<wxString, JUSTIFICATION> pinJustificationMap;
506
507 pinJustificationMap["BOTTOM"] = JUSTIFICATION::BOTTOM;
508 pinJustificationMap["NONE"] = JUSTIFICATION::NONE;
509 pinJustificationMap["LEFT"] = JUSTIFICATION::LEFT;
510 pinJustificationMap["RIGHT"] = JUSTIFICATION::RIGHT;
511 pinJustificationMap["TOP"] = JUSTIFICATION::TOP;
512 pinJustificationMap["VBOTTOM"] = JUSTIFICATION::VBOTTOM;
513 pinJustificationMap["VLEFT"] = JUSTIFICATION::VLEFT;
514 pinJustificationMap["VRIGHT"] = JUSTIFICATION::VRIGHT;
515 pinJustificationMap["VCENTER"] = JUSTIFICATION::VCENTER;
516 pinJustificationMap["VTOP"] = JUSTIFICATION::VTOP;
517
518 if( pinJustificationMap.find( aValue.Upper() ) == pinJustificationMap.end() )
519 THROW_IO_ERROR( _( "Expecting NONE, BOTTOM, TOP, LEFT, RIGHT, VBOTTOM, VTOP, VCENTER, VLEFT or VRIGHT" ) );
520
521 return pinJustificationMap[ aValue.Upper() ];
522}
523
524
526{
527 std::map<wxString, SYMBOLTYPE> symbolTypeMap;
528
529 symbolTypeMap["CELL"] = SYMBOLTYPE::CELL;
530 symbolTypeMap["BLOCK"] = SYMBOLTYPE::BLOCK;
531
532 if( symbolTypeMap.find( aValue.Upper() ) == symbolTypeMap.end() )
533 THROW_IO_ERROR( _( "Expecting CELL or BLOCK" ) );
534
535 return symbolTypeMap[ aValue.Upper() ];
536}
537
538
539void LTSPICE_SCHEMATIC::removeCarriageReturn( wxString& elementFromLine )
540{
541 if( elementFromLine.EndsWith( '\r' ) )
542 elementFromLine = elementFromLine.BeforeLast( '\r' );
543}
544
545
547 LT_ASC& aAscFile )
548{
549 const std::map<wxString, wxString>& asyFiles = m_fileCache[ wxS( "asyFiles" ) ];
550
551 if( !asyFiles.count( aAscFileName.Lower() ) )
552 THROW_IO_ERROR( wxString::Format( _( "Symbol '%s.asy' not found" ), aAscFileName ) );
553
554 return SymbolBuilder( aAscFileName, asyFiles.at( aAscFileName.Lower() ), aAscFile );
555}
556
558 const wxString& aAsyFileContent,
559 LT_ASC& aAscFile )
560{
561 LT_SYMBOL lt_symbol;
562 int lineNumber = 1;
563
564 lt_symbol.Name = aAscFileName;
567
568 for( wxString line : wxSplit( aAsyFileContent, '\n' ) )
569 {
570 removeCarriageReturn( line );
571
572 wxArrayString tokens = wxSplit( line, ' ' );
573
574 if( tokens.IsEmpty() )
575 continue;
576
577 wxString element = tokens[0].Upper();
578
579 if( element == "LINE" )
580 {
581 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, aAscFileName );
582
583 wxString lineWidth = tokens[1];
584 wxString startPointX = tokens[2];
585 wxString startPointY = tokens[3];
586 wxString endPointX = tokens[4];
587 wxString endPointY = tokens[5];
588
589 LINE lt_line;
590 lt_line.LineWidth = getLineWidth( lineWidth );
591 lt_line.Start = pointCheck( startPointX, startPointY, lineNumber, aAscFileName );
592 lt_line.End = pointCheck( endPointX, endPointY, lineNumber, aAscFileName );
593
594 int lineStyleNumber = 0; // default
595
596 if( tokens.size() == 7 )
597 {
598 wxString lineStyle = tokens[6];
599 lineStyleNumber = integerCheck( lineStyle, lineNumber, aAscFileName );
600 }
601
602 lt_line.LineStyle = getLineStyle( lineStyleNumber );
603
604 lt_symbol.Lines.push_back( lt_line );
605 }
606 else if( element == "RECTANGLE" )
607 {
608 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, aAscFileName );
609
610 wxString lineWidth = tokens[1];
611 wxString botRightX = tokens[2];
612 wxString botRightY = tokens[3];
613 wxString topLeftX = tokens[4];
614 wxString topRightY = tokens[5];
615
616 RECTANGLE rect;
617 rect.LineWidth = getLineWidth( lineWidth );
618 rect.BotRight = pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
619 rect.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
620
621 int lineStyleNumber = 0; // default
622
623 if( tokens.size() == 7 )
624 {
625 wxString lineStyle = tokens[6];
626 lineStyleNumber = integerCheck( lineStyle, lineNumber, aAscFileName );
627 }
628
629 rect.LineStyle = getLineStyle( lineStyleNumber );
630
631 lt_symbol.Rectangles.push_back( rect );
632 }
633 else if( element == "CIRCLE" )
634 {
639 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, aAscFileName );
640
641 wxString lineWidth = tokens[1];
642 wxString botRightX = tokens[2];
643 wxString botRightY = tokens[3];
644 wxString topLeftX = tokens[4];
645 wxString topRightY = tokens[5];
646
648 circle.LineWidth = getLineWidth( lineWidth );
649 circle.BotRight = pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
650 circle.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
651
652 int lineStyleNumber = 0; // default
653
654 if( tokens.size() == 7 )
655 {
656 wxString lineStyle = tokens[6];
657 lineStyleNumber = integerCheck( lineStyle, lineNumber, aAscFileName );
658 }
659
660 circle.LineStyle = getLineStyle( lineStyleNumber );
661
662 lt_symbol.Circles.push_back( circle );
663 }
664 else if( element == "ARC" )
665 {
671 tokensSizeRangeCheck( tokens.size(), 10, 11, lineNumber, aAscFileName );
672
673 wxString lineWidth = tokens[1];
674 wxString botRightX = tokens[2];
675 wxString botRightY = tokens[3];
676 wxString topLeftX = tokens[4];
677 wxString topRightY = tokens[5];
678 wxString arcStartPointX = tokens[6];
679 wxString arcStartPointY = tokens[7];
680 wxString arcEndPointX = tokens[8];
681 wxString arcEndPointY = tokens[9];
682
683 ARC arc;
684 arc.LineWidth = getLineWidth( lineWidth );
685 arc.BotRight = pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
686 arc.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
687 arc.ArcStart = pointCheck( arcStartPointX, arcStartPointY, lineNumber, aAscFileName );
688 arc.ArcEnd = pointCheck( arcEndPointX, arcEndPointY, lineNumber, aAscFileName );
689
690 int lineStyleNumber = 0; // default
691
692 if( tokens.size() == 11 )
693 {
694 wxString lineStyle = tokens[10];
695 lineStyleNumber = integerCheck( lineStyle, lineNumber, aAscFileName );
696 }
697
698 arc.LineStyle = getLineStyle( lineStyleNumber );
699
700 lt_symbol.Arcs.push_back( arc );
701 }
702 else if( element == "WINDOW" )
703 {
704 tokensSizeRangeCheck( tokens.size(), 6, 6, lineNumber, aAscFileName );
705
706 wxString number = tokens[1];
707 wxString windowPosX = tokens[2];
708 wxString windowPosY = tokens[3];
709 wxString justification = tokens[4];
710 wxString fontSize = tokens[5];
711
712 LT_WINDOW window;
713 window.WindowNumber = integerCheck( number, lineNumber, aAscFileName );
714 window.Position = pointCheck( windowPosX, windowPosY, lineNumber, aAscFileName );
715 window.Justification = getTextJustification( justification );
716 window.FontSize = integerCheck( fontSize, lineNumber, aAscFileName );
717
718 // LTSpice appears to ignore hidden property from .asy files
719 if( window.FontSize == 0 )
720 window.FontSize = 2;
721
722 lt_symbol.Windows.push_back( window );
723 }
724 else if( element == "SYMATTR" )
725 {
726 aggregateAttributeValue( tokens, 2 );
727
728 tokensSizeRangeCheck( tokens.size(), 3, INT_MAX, lineNumber, aAscFileName );
729
730 wxString key = tokens[1];
731 wxString value = tokens[2];
732
733 if( value == wxS( "\"\"" ) )
734 value = wxEmptyString;
735
736 lt_symbol.SymAttributes[ key.Upper() ] = value;
737 }
738 else if( element == "PIN" )
739 {
740 tokensSizeRangeCheck( tokens.size(), 5, 5, lineNumber, aAscFileName );
741
742 wxString pinLocationX = tokens[1];
743 wxString pinLocationY = tokens[2];
744 wxString Justification = tokens[3];
745 wxString nameOffSet = tokens[4];
746
747 LT_PIN pin;
748 pin.PinLocation = pointCheck( pinLocationX, pinLocationY, lineNumber,aAscFileName );
749 pin.PinJustification = getPinJustification( Justification );
750 pin.NameOffSet = integerCheck( nameOffSet, lineNumber, aAscFileName );
751
752 lt_symbol.Pins.push_back( pin );
753 }
754 else if( element == "PINATTR" )
755 {
756 aggregateAttributeValue( tokens, 2 );
757
758 tokensSizeRangeCheck( tokens.size(), 3, INT_MAX, lineNumber, aAscFileName );
759
760 wxString name = tokens[1];
761 wxString Value = tokens[2];
762
763 lt_symbol.Pins.back().PinAttribute.insert( { name, Value } );
764 }
765 else if( element == "SYMBOLTYPE" )
766 {
767 tokensSizeRangeCheck( tokens.size(), 2, 2, lineNumber, aAscFileName );
768
769 wxString symbolType = tokens[1];
770
771 lt_symbol.SymbolType = getSymbolType( symbolType );
772 }
773
774 lineNumber++;
775 }
776
777 return lt_symbol;
778}
779
780
782{
783 LT_SYMBOL lt_symbol;
784
785 lt_symbol.Name = aAscFileName;
788
789 RECTANGLE rect;
790 rect.LineWidth = getLineWidth( "NORMAL" );
792 rect.BotRight = VECTOR2I( 20, 20 );
793 rect.TopLeft = VECTOR2I( -20, -20 );
794
795 lt_symbol.Rectangles.push_back( rect );
796
797 return lt_symbol;
798}
799
800
801std::vector<LTSPICE_SCHEMATIC::LT_ASC> LTSPICE_SCHEMATIC::StructureBuilder()
802{
803 // Initialising Symbol Struct
804
805 std::vector<LT_ASC> ascFiles;
806
807 for( const auto& [ fileName, contents ] : m_fileCache[ wxS( "ascFiles" ) ] )
808 {
809 LT_ASC ascFile;
810 std::vector<LT_SYMBOL> symbolArray;
811
812 ascFile.SheetSize = VECTOR2I( 0, 0 );
813 ascFile.Symbols = symbolArray;
814 ascFile.Version = 0;
815 ascFile.VersionMinor = 0;
816 ascFile.SheetNumber = 0;
817
818 int lineNumber = 1;
819
820 for( wxString line : wxSplit( contents, '\n' ) )
821 {
822 removeCarriageReturn( line );
823
824 wxArrayString tokens = wxSplit( line, ' ' );
825
826 if( tokens.IsEmpty() )
827 continue;
828
829 wxString element = tokens[0].Upper();
830
831 if( element == "SHEET" )
832 {
833 tokensSizeRangeCheck( tokens.size(), 4, 4, lineNumber, fileName );
834
835 wxString sheetNumber = tokens[1];
836 wxString sheetWidth = tokens[2];
837 wxString sheetHeight = tokens[3];
838
839 ascFile.SheetNumber = integerCheck( sheetNumber, lineNumber, fileName );
840 ascFile.SheetSize = pointCheck( sheetWidth, sheetHeight, lineNumber, fileName );
841 }
842 else if( element == "SYMBOL" )
843 {
844 tokensSizeRangeCheck( tokens.size(), 5, 5, lineNumber, fileName );
845
846 wxString symbolName = tokens[1];
847 wxString posX = tokens[2];
848 wxString posY = tokens[3];
849 wxString rotate_mirror_option = tokens[4];
850
851 symbolName.Replace( '\\', '/' );
852
853 try
854 {
855 LT_SYMBOL lt_symbol = SymbolBuilder( symbolName, ascFile );
856 lt_symbol.Offset = pointCheck( posX, posY, lineNumber, fileName );
857 lt_symbol.SymbolOrientation = getSymbolRotationOrMirror( rotate_mirror_option );
858
859 ascFile.Symbols.push_back( lt_symbol );
860 ascFile.BoundingBox.Merge( lt_symbol.Offset );
861 }
862 catch( IO_ERROR& e )
863 {
864 if( m_reporter )
865 m_reporter->Report( e.What(), RPT_SEVERITY_ERROR );
866
867 // Use dummy symbol
868 LT_SYMBOL lt_symbol = MakeDummySymbol( symbolName );
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 }
876 else if( element == "WIRE" )
877 {
878 tokensSizeRangeCheck( tokens.size(), 5, 5, lineNumber, fileName );
879
880 wxString startPointX = tokens[1];
881 wxString startPointY = tokens[2];
882 wxString endPointX = tokens[3];
883 wxString endPointY = tokens[4];
884
885 WIRE wire;
886 wire.Start = pointCheck( startPointX, startPointY, lineNumber, fileName );
887 wire.End = pointCheck( endPointX, endPointY, lineNumber, fileName );
888
889 ascFile.Wires.push_back( wire );
890 ascFile.BoundingBox.Merge( wire.Start );
891 ascFile.BoundingBox.Merge( wire.End );
892 }
893 else if( element == "FLAG" )
894 {
895 tokensSizeRangeCheck( tokens.size(), 4, 4, lineNumber, fileName );
896
897 wxString posX = tokens[1];
898 wxString posY = tokens[2];
899 wxString name = tokens[3];
900
901 FLAG flag;
902 flag.Offset = pointCheck( posX, posY, lineNumber, fileName );
903 flag.Value = name;
904 flag.FontSize = 2;
905
906 ascFile.Flags.push_back( flag );
907 ascFile.BoundingBox.Merge( flag.Offset );
908 }
909 else if( element == "DATAFLAG" )
910 {
911 tokensSizeRangeCheck( tokens.size(), 4, 4, lineNumber, fileName );
912
913 wxString posX = tokens[1];
914 wxString posY = tokens[2];
915 wxString expression = tokens[3];
916
918 flag.Offset = pointCheck( posX, posY, lineNumber, fileName );
919 flag.Expression = expression;
920 flag.FontSize = 2;
921
922 ascFile.DataFlags.push_back( flag );
923 ascFile.BoundingBox.Merge( flag.Offset );
924 }
925 else if( element == "WINDOW" )
926 {
927 tokensSizeRangeCheck( tokens.size(), 6, 6, lineNumber, fileName );
928
929 wxString number = tokens[1];
930 wxString windowPosX = tokens[2];
931 wxString windowPosY = tokens[3];
932 wxString justification = tokens[4];
933 wxString fontSize = tokens[5];
934
935 int windowNumber = integerCheck( number, lineNumber, fileName );
936 LT_WINDOW* window = nullptr;
937
938 // Overwrite an existing window from the symbol definition
939 for( LT_WINDOW& candidate : ascFile.Symbols.back().Windows )
940 {
941 if( candidate.WindowNumber == windowNumber )
942 {
943 window = &candidate;
944 break;
945 }
946 }
947
948 if( !window )
949 {
950 ascFile.Symbols.back().Windows.emplace_back( LT_WINDOW() );
951 window = &ascFile.Symbols.back().Windows.back();
952 }
953
954 window->WindowNumber = windowNumber;
955 window->Position = pointCheck( windowPosX, windowPosY, lineNumber, fileName );
956 window->Justification = getTextJustification( justification );
957 window->FontSize = integerCheck( fontSize, lineNumber, fileName );
958
959 ascFile.BoundingBox.Merge( window->Position );
960 }
961 else if( element == "SYMATTR" )
962 {
963 tokensSizeRangeCheck( tokens.size(), 3, INT_MAX, lineNumber, fileName );
964
965 aggregateAttributeValue( tokens, 2 );
966
967 wxString name = tokens[1];
968 wxString value = tokens[2];
969
970 if( value == wxS( "\"\"" ) )
971 value = wxEmptyString;
972
973 ascFile.Symbols.back().SymAttributes[ name.Upper() ] = value;
974 }
975 else if( element == "LINE" )
976 {
977 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, fileName );
978
979 wxString lineWidth = tokens[1];
980 wxString startPointX = tokens[2];
981 wxString startPointY = tokens[3];
982 wxString endPointX = tokens[4];
983 wxString endPointY = tokens[5];
984
985 LINE lt_line;
986 lt_line.LineWidth = getLineWidth( lineWidth );
987 lt_line.Start = pointCheck( startPointX, startPointY, lineNumber, fileName );
988 lt_line.End = pointCheck( endPointX, endPointY, lineNumber, fileName );
989
990 int lineStyleNumber = 0; // default
991
992 if( tokens.size() == 7 )
993 {
994 wxString lineStyle = tokens[6];
995 lineStyleNumber = integerCheck( lineStyle, lineNumber, fileName );
996 }
997
998 lt_line.LineStyle = getLineStyle( lineStyleNumber );
999
1000 ascFile.Lines.push_back( lt_line );
1001 ascFile.BoundingBox.Merge( lt_line.Start );
1002 ascFile.BoundingBox.Merge( lt_line.End );
1003 }
1004 else if( element == "RECTANGLE" )
1005 {
1006 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, fileName );
1007
1008 // wxString lineWidth = tokens[1];
1009 wxString botRightX = tokens[2];
1010 wxString botRightY = tokens[3];
1011 wxString topLeftX = tokens[4];
1012 wxString topRightY = tokens[5];
1013
1014 RECTANGLE rect;
1015 rect.LineWidth = getLineWidth( tokens[1] );
1016 rect.BotRight = pointCheck( botRightX, botRightY, lineNumber, fileName );
1017 rect.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, fileName );
1018
1019 int lineStyleNumber = 0; // default
1020
1021 if( tokens.size() == 7 )
1022 {
1023 wxString lineStyle = tokens[6];
1024 lineStyleNumber = integerCheck( lineStyle, lineNumber, fileName );
1025 }
1026
1027 rect.LineStyle = getLineStyle( lineStyleNumber );
1028
1029 ascFile.Rectangles.push_back( rect );
1030 ascFile.BoundingBox.Merge( rect.TopLeft );
1031 ascFile.BoundingBox.Merge( rect.BotRight );
1032 }
1033 else if( element == "CIRCLE" )
1034 {
1035 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, fileName );
1036
1037 wxString lineWidth = tokens[1];
1038 wxString botRightX = tokens[2];
1039 wxString botRightY = tokens[3];
1040 wxString topLeftX = tokens[4];
1041 wxString topRightY = tokens[5];
1042
1043 CIRCLE circle;
1044 circle.LineWidth = getLineWidth( lineWidth );
1045 circle.BotRight = pointCheck( botRightX, botRightY, lineNumber, fileName );
1046 circle.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, fileName );
1047
1048 int lineStyleNumber = 0; // default
1049
1050 if( tokens.size() == 7 )
1051 {
1052 wxString lineStyle = tokens[6];
1053 lineStyleNumber = integerCheck( lineStyle, lineNumber, fileName );
1054 }
1055
1056 circle.LineStyle = getLineStyle( lineStyleNumber );
1057
1058 ascFile.Circles.push_back( circle );
1059 ascFile.BoundingBox.Merge( circle.TopLeft );
1060 ascFile.BoundingBox.Merge( circle.BotRight );
1061 }
1062 else if( element == "ARC" )
1063 {
1069 tokensSizeRangeCheck( tokens.size(), 10, 11, lineNumber, fileName );
1070
1071 wxString lineWidth = tokens[1];
1072 wxString botRightX = tokens[2];
1073 wxString botRightY = tokens[3];
1074 wxString topLeftX = tokens[4];
1075 wxString topRightY = tokens[5];
1076 wxString arcStartPointX = tokens[6];
1077 wxString arcStartPointY = tokens[7];
1078 wxString arcEndPointX = tokens[8];
1079 wxString arcEndPointY = tokens[9];
1080
1081 ARC arc;
1082 arc.LineWidth = getLineWidth( lineWidth );
1083 arc.BotRight = pointCheck( botRightX, botRightY, lineNumber, fileName );
1084 arc.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, fileName );
1085 arc.ArcEnd = pointCheck( arcStartPointX, arcStartPointY, lineNumber, fileName );
1086 arc.ArcStart = pointCheck( arcEndPointX, arcEndPointY, lineNumber, fileName );
1087
1088 int lineStyleNumber = 0; // default
1089
1090 if( tokens.size() == 11 )
1091 {
1092 wxString lineStyle = tokens[10];
1093 lineStyleNumber = integerCheck( lineStyle, lineNumber, fileName );
1094 }
1095
1096 arc.LineStyle = getLineStyle( lineStyleNumber );
1097
1098 ascFile.Arcs.push_back( arc );
1099 ascFile.BoundingBox.Merge( arc.TopLeft );
1100 ascFile.BoundingBox.Merge( arc.BotRight );
1101 }
1102 else if( element == "IOPIN" )
1103 {
1104 tokensSizeRangeCheck( tokens.size(), 4, 4, lineNumber, fileName );
1105
1106 wxString pinLocationX = tokens[1];
1107 wxString pinLocationY = tokens[2];
1108 wxString pinPolarity = tokens[3];
1109
1110 IOPIN iopin;
1111 iopin.Location = pointCheck( pinLocationX, pinLocationY, lineNumber, fileName );
1112 iopin.Polarity = getPolarity( pinPolarity );
1113
1114 ascFile.Iopins.push_back( iopin );
1115 ascFile.BoundingBox.Merge( iopin.Location );
1116 }
1117 else if( element == "TEXT" )
1118 {
1119 aggregateAttributeValue( tokens, 5 );
1120
1121 tokensSizeRangeCheck( tokens.size(), 6, INT_MAX, lineNumber, fileName );
1122
1123 wxString positionX = tokens[1];
1124 wxString positionY = tokens[2];
1125 wxString justification = tokens[3];
1126 wxString fontSize = tokens[4];
1127 wxString value = tokens[5];
1128
1129 TEXT text;
1130 text.Offset = pointCheck( positionX, positionY, lineNumber, fileName );
1131 text.Justification = getTextJustification( justification );
1132 text.FontSize = integerCheck( fontSize, lineNumber, fileName );
1133
1134 if( value.StartsWith( wxS( "!" ), &text.Value ) )
1135 text.Value.Replace( wxS( "! " ), wxS( "\n" ) ); // replace subsequent ! with \n
1136 else if( value.StartsWith( wxS( ";" ), &text.Value ) )
1137 text.Value.Replace( wxS( "; " ), wxS( "\n" ) ); // replace subsequent ; with \n
1138 else
1139 text.Value = value;
1140
1141 text.Value.Replace( wxS( "\\n" ), wxS( "\n" ) );
1142
1143 ascFile.Texts.push_back( text );
1144 ascFile.BoundingBox.Merge( text.Offset );
1145 }
1146 else if( element == "BUSTAP" )
1147 {
1148 tokensSizeRangeCheck( tokens.size(), 5, 5, lineNumber, fileName );
1149
1150 wxString startPointX = tokens[1];
1151 wxString startPointY = tokens[2];
1152 wxString endPointX = tokens[3];
1153 wxString endPointY = tokens[4];
1154
1155 BUSTAP bustap;
1156 bustap.Start = pointCheck( startPointX, startPointY, lineNumber, fileName );
1157 bustap.End = pointCheck( endPointX, endPointY, lineNumber, fileName );
1158
1159 ascFile.Bustap.push_back( bustap );
1160 ascFile.BoundingBox.Merge( bustap.Start );
1161 ascFile.BoundingBox.Merge( bustap.End );
1162 }
1163 else if( element == "VERSION" )
1164 {
1165 wxString versionNumber = tokens[1];
1166 if( versionNumber.Contains( '.' ) )
1167 {
1168 wxString majorStr = versionNumber.BeforeFirst( '.' );
1169 wxString minorStr = versionNumber.AfterFirst( '.' );
1170 ascFile.Version = integerCheck( majorStr, lineNumber, fileName );
1171 ascFile.VersionMinor = integerCheck( minorStr, lineNumber, fileName );
1172 }
1173 else
1174 {
1175 ascFile.Version = integerCheck( versionNumber, lineNumber, fileName );
1176 }
1177 }
1178
1179 lineNumber++;
1180 }
1181
1182 ascFiles.push_back( std::move( ascFile ) );
1183 }
1184
1185 return ascFiles;
1186}
1187
1188
const char * name
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
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.cpp:93
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:83
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition lib_symbol.h:240
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:88
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
@ 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:695
Definition of file extensions used in Kicad.