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 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,
361 const wxString& aFileName )
362{
363 long result;
364
365 if( !aToken.ToLong( &result ) )
366 {
367 THROW_IO_ERROR( wxString::Format( _( "Expecting integer at line %d in file %s" ),
368 aLineNumber,
369 aFileName ) );
370 }
371
372 return (int) result;
373}
374
375
376VECTOR2I LTSPICE_SCHEMATIC::pointCheck( const wxString& aTokenX, const wxString& aTokenY,
377 int aLineNumber, const wxString& aFileName )
378{
379 return VECTOR2I( integerCheck( aTokenX, aLineNumber, aFileName ),
380 integerCheck( aTokenY, aLineNumber, aFileName ) );
381}
382
383
384void LTSPICE_SCHEMATIC::tokensSizeRangeCheck( size_t aActualSize, int aExpectedMin,
385 int aExpectedMax, int aLineNumber,
386 const wxString& aFileName )
387{
388 if( (int) aActualSize < aExpectedMin )
389 {
390 THROW_IO_ERROR( wxString::Format( _( "Expected data missing on line %d in file %s" ),
391 aLineNumber,
392 aFileName ) );
393 }
394 else if( (int) aActualSize > aExpectedMax )
395 {
396 THROW_IO_ERROR( wxString::Format( _( "Extra data found on line %d in file %s" ),
397 aLineNumber,
398 aFileName ) );
399 }
400}
401
402
403void LTSPICE_SCHEMATIC::aggregateAttributeValue( wxArrayString& aTokens, int aIndex )
404{
405 // Merges a value which is across multiple tokens into one token with spaces in between.
406 for( int i = aIndex + 1; i < (int) aTokens.GetCount(); i++ )
407 aTokens[ aIndex ] += " " + aTokens[i];
408}
409
410
412{
413 std::map<int, LINESTYLE> lineStyleMap;
414
415 lineStyleMap[0] = LINESTYLE::SOLID;
416 lineStyleMap[1] = LINESTYLE::DASH;
417 lineStyleMap[2] = LINESTYLE::DOT;
418 lineStyleMap[3] = LINESTYLE::DASHDOT;
419 lineStyleMap[4] = LINESTYLE::DASHDOTDOT;
420
421 if( lineStyleMap.find( aValue ) == lineStyleMap.end() )
422 THROW_IO_ERROR( _( "Expecting 0, 1, 2, 3 or 4" ) );
423
424 return lineStyleMap[ aValue ];
425}
426
427
429{
430 std::map<wxString, LINEWIDTH> lineWidthMap;
431
432 lineWidthMap["NORMAL"] = LINEWIDTH::Normal;
433 lineWidthMap["WIDE"] = LINEWIDTH::Wide;
434
435 if( lineWidthMap.find( aValue.Upper() ) == lineWidthMap.end() )
436 THROW_IO_ERROR( _( "Expecting NORMAL or WIDE" ) );
437
438 return lineWidthMap[ aValue.Upper() ];
439}
440
441
443{
444 std::map<wxString, POLARITY> polarityMap;
445
446 polarityMap["I"] = POLARITY::PIN_INPUT;
447 polarityMap["O"] = POLARITY::OUTPUT;
448 polarityMap["B"] = POLARITY::BIDIR;
449 polarityMap["IN"] = POLARITY::PIN_INPUT;
450 polarityMap["OUT"] = POLARITY::OUTPUT;
451 polarityMap["BIDIR"] = POLARITY::BIDIR;
452
453 if( polarityMap.find( aValue.Upper() ) == polarityMap.end() )
454 THROW_IO_ERROR( _( "Expecting I, O, B, IN, OUT or BIDIR" ) );
455
456 return polarityMap[ aValue.Upper() ];
457}
458
459
461{
462 std::map<wxString, ORIENTATION> rotationMirrorMap;
463
464 rotationMirrorMap["R0"] = ORIENTATION::R0;
465 rotationMirrorMap["R90"] = ORIENTATION::R90;
466 rotationMirrorMap["R180"] = ORIENTATION::R180;
467 rotationMirrorMap["R270"] = ORIENTATION::R270;
468
469 rotationMirrorMap["M0"] = ORIENTATION::M0;
470 rotationMirrorMap["M90"] = ORIENTATION::M90;
471 rotationMirrorMap["M180"] = ORIENTATION::M180;
472 rotationMirrorMap["M270"] = ORIENTATION::M270;
473
474 if( rotationMirrorMap.find( aValue.Upper() ) == rotationMirrorMap.end() )
475 THROW_IO_ERROR( _( "Expecting R0, R90, R18, R270, M0, M90, M180 or M270" ) );
476
477 return rotationMirrorMap[ aValue.Upper() ];
478}
479
480
482{
483 std::map<wxString, JUSTIFICATION> justificationMap;
484
485 justificationMap["LEFT"] = JUSTIFICATION::LEFT;
486 justificationMap["CENTER"] = JUSTIFICATION::CENTER;
487 justificationMap["RIGHT"] = JUSTIFICATION::RIGHT;
488 justificationMap["VLEFT"] = JUSTIFICATION::VLEFT;
489 justificationMap["VRIGHT"] = JUSTIFICATION::VRIGHT;
490 justificationMap["VCENTER"] = JUSTIFICATION::VCENTER;
491 justificationMap["BOTTOM"] = JUSTIFICATION::BOTTOM;
492 justificationMap["TOP"] = JUSTIFICATION::TOP;
493 justificationMap["VBOTTOM"] = JUSTIFICATION::VBOTTOM;
494 justificationMap["VTOP"] = JUSTIFICATION::VTOP;
495 justificationMap["INVISIBLE"] = JUSTIFICATION::INVISIBLE;
496
497 if( justificationMap.find( aValue.Upper() ) == justificationMap.end() )
498 THROW_IO_ERROR( _( "Expecting LEFT, CENTER, RIGHT, TOP, BOTTOM, VLEFT, VRIGHT, VCENTER, "
499 "VTOP, VBOTTOM or INVISIBLE" ) );
500
501 return justificationMap[ aValue.Upper() ];
502}
503
504
506{
507 std::map<wxString, JUSTIFICATION> pinJustificationMap;
508
509 pinJustificationMap["BOTTOM"] = JUSTIFICATION::BOTTOM;
510 pinJustificationMap["NONE"] = JUSTIFICATION::NONE;
511 pinJustificationMap["LEFT"] = JUSTIFICATION::LEFT;
512 pinJustificationMap["RIGHT"] = JUSTIFICATION::RIGHT;
513 pinJustificationMap["TOP"] = JUSTIFICATION::TOP;
514 pinJustificationMap["VBOTTOM"] = JUSTIFICATION::VBOTTOM;
515 pinJustificationMap["VLEFT"] = JUSTIFICATION::VLEFT;
516 pinJustificationMap["VRIGHT"] = JUSTIFICATION::VRIGHT;
517 pinJustificationMap["VCENTER"] = JUSTIFICATION::VCENTER;
518 pinJustificationMap["VTOP"] = JUSTIFICATION::VTOP;
519
520 if( pinJustificationMap.find( aValue.Upper() ) == pinJustificationMap.end() )
521 THROW_IO_ERROR( _( "Expecting NONE, BOTTOM, TOP, LEFT, RIGHT, VBOTTOM, VTOP, VCENTER, VLEFT or VRIGHT" ) );
522
523 return pinJustificationMap[ aValue.Upper() ];
524}
525
526
528{
529 std::map<wxString, SYMBOLTYPE> symbolTypeMap;
530
531 symbolTypeMap["CELL"] = SYMBOLTYPE::CELL;
532 symbolTypeMap["BLOCK"] = SYMBOLTYPE::BLOCK;
533
534 if( symbolTypeMap.find( aValue.Upper() ) == symbolTypeMap.end() )
535 THROW_IO_ERROR( _( "Expecting CELL or BLOCK" ) );
536
537 return symbolTypeMap[ aValue.Upper() ];
538}
539
540
541void LTSPICE_SCHEMATIC::removeCarriageReturn( wxString& elementFromLine )
542{
543 if( elementFromLine.EndsWith( '\r' ) )
544 elementFromLine = elementFromLine.BeforeLast( '\r' );
545}
546
547
549 LT_ASC& aAscFile )
550{
551 const std::map<wxString, wxString>& asyFiles = m_fileCache[ wxS( "asyFiles" ) ];
552
553 if( !asyFiles.count( aAscFileName.Lower() ) )
554 THROW_IO_ERROR( wxString::Format( _( "Symbol '%s.asy' not found" ), aAscFileName ) );
555
556 return SymbolBuilder( aAscFileName, asyFiles.at( aAscFileName.Lower() ), aAscFile );
557}
558
560 const wxString& aAsyFileContent,
561 LT_ASC& aAscFile )
562{
563 LT_SYMBOL lt_symbol;
564 int lineNumber = 1;
565
566 lt_symbol.Name = aAscFileName;
569
570 for( wxString line : wxSplit( aAsyFileContent, '\n' ) )
571 {
572 removeCarriageReturn( line );
573
574 wxArrayString tokens = wxSplit( line, ' ' );
575
576 if( tokens.IsEmpty() )
577 continue;
578
579 wxString element = tokens[0].Upper();
580
581 if( element == "LINE" )
582 {
583 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, aAscFileName );
584
585 wxString lineWidth = tokens[1];
586 wxString startPointX = tokens[2];
587 wxString startPointY = tokens[3];
588 wxString endPointX = tokens[4];
589 wxString endPointY = tokens[5];
590
591 LINE lt_line;
592 lt_line.LineWidth = getLineWidth( lineWidth );
593 lt_line.Start = pointCheck( startPointX, startPointY, lineNumber, aAscFileName );
594 lt_line.End = pointCheck( endPointX, endPointY, lineNumber, aAscFileName );
595
596 int lineStyleNumber = 0; // default
597
598 if( tokens.size() == 7 )
599 {
600 wxString lineStyle = tokens[6];
601 lineStyleNumber = integerCheck( lineStyle, lineNumber, aAscFileName );
602 }
603
604 lt_line.LineStyle = getLineStyle( lineStyleNumber );
605
606 lt_symbol.Lines.push_back( lt_line );
607 }
608 else if( element == "RECTANGLE" )
609 {
610 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, aAscFileName );
611
612 wxString lineWidth = tokens[1];
613 wxString botRightX = tokens[2];
614 wxString botRightY = tokens[3];
615 wxString topLeftX = tokens[4];
616 wxString topRightY = tokens[5];
617
618 RECTANGLE rect;
619 rect.LineWidth = getLineWidth( lineWidth );
620 rect.BotRight = pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
621 rect.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
622
623 int lineStyleNumber = 0; // default
624
625 if( tokens.size() == 7 )
626 {
627 wxString lineStyle = tokens[6];
628 lineStyleNumber = integerCheck( lineStyle, lineNumber, aAscFileName );
629 }
630
631 rect.LineStyle = getLineStyle( lineStyleNumber );
632
633 lt_symbol.Rectangles.push_back( rect );
634 }
635 else if( element == "CIRCLE" )
636 {
641 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, aAscFileName );
642
643 wxString lineWidth = tokens[1];
644 wxString botRightX = tokens[2];
645 wxString botRightY = tokens[3];
646 wxString topLeftX = tokens[4];
647 wxString topRightY = tokens[5];
648
650 circle.LineWidth = getLineWidth( lineWidth );
651 circle.BotRight = pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
652 circle.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
653
654 int lineStyleNumber = 0; // default
655
656 if( tokens.size() == 7 )
657 {
658 wxString lineStyle = tokens[6];
659 lineStyleNumber = integerCheck( lineStyle, lineNumber, aAscFileName );
660 }
661
662 circle.LineStyle = getLineStyle( lineStyleNumber );
663
664 lt_symbol.Circles.push_back( circle );
665 }
666 else if( element == "ARC" )
667 {
673 tokensSizeRangeCheck( tokens.size(), 10, 11, lineNumber, aAscFileName );
674
675 wxString lineWidth = tokens[1];
676 wxString botRightX = tokens[2];
677 wxString botRightY = tokens[3];
678 wxString topLeftX = tokens[4];
679 wxString topRightY = tokens[5];
680 wxString arcStartPointX = tokens[6];
681 wxString arcStartPointY = tokens[7];
682 wxString arcEndPointX = tokens[8];
683 wxString arcEndPointY = tokens[9];
684
685 ARC arc;
686 arc.LineWidth = getLineWidth( lineWidth );
687 arc.BotRight = pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
688 arc.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
689 arc.ArcStart = pointCheck( arcStartPointX, arcStartPointY, lineNumber, aAscFileName );
690 arc.ArcEnd = pointCheck( arcEndPointX, arcEndPointY, lineNumber, aAscFileName );
691
692 int lineStyleNumber = 0; // default
693
694 if( tokens.size() == 11 )
695 {
696 wxString lineStyle = tokens[10];
697 lineStyleNumber = integerCheck( lineStyle, lineNumber, aAscFileName );
698 }
699
700 arc.LineStyle = getLineStyle( lineStyleNumber );
701
702 lt_symbol.Arcs.push_back( arc );
703 }
704 else if( element == "WINDOW" )
705 {
706 tokensSizeRangeCheck( tokens.size(), 6, 6, lineNumber, aAscFileName );
707
708 wxString number = tokens[1];
709 wxString windowPosX = tokens[2];
710 wxString windowPosY = tokens[3];
711 wxString justification = tokens[4];
712 wxString fontSize = tokens[5];
713
714 LT_WINDOW window;
715 window.WindowNumber = integerCheck( number, lineNumber, aAscFileName );
716 window.Position = pointCheck( windowPosX, windowPosY, lineNumber, aAscFileName );
717 window.Justification = getTextJustification( justification );
718 window.FontSize = integerCheck( fontSize, lineNumber, aAscFileName );
719
720 // LTSpice appears to ignore hidden property from .asy files
721 if( window.FontSize == 0 )
722 window.FontSize = 2;
723
724 lt_symbol.Windows.push_back( window );
725 }
726 else if( element == "SYMATTR" )
727 {
728 aggregateAttributeValue( tokens, 2 );
729
730 tokensSizeRangeCheck( tokens.size(), 3, INT_MAX, lineNumber, aAscFileName );
731
732 wxString key = tokens[1];
733 wxString value = tokens[2];
734
735 if( value == wxS( "\"\"" ) )
736 value = wxEmptyString;
737
738 lt_symbol.SymAttributes[ key.Upper() ] = value;
739 }
740 else if( element == "PIN" )
741 {
742 tokensSizeRangeCheck( tokens.size(), 5, 5, lineNumber, aAscFileName );
743
744 wxString pinLocationX = tokens[1];
745 wxString pinLocationY = tokens[2];
746 wxString Justification = tokens[3];
747 wxString nameOffSet = tokens[4];
748
749 LT_PIN pin;
750 pin.PinLocation = pointCheck( pinLocationX, pinLocationY, lineNumber,aAscFileName );
751 pin.PinJustification = getPinJustification( Justification );
752 pin.NameOffSet = integerCheck( nameOffSet, lineNumber, aAscFileName );
753
754 lt_symbol.Pins.push_back( pin );
755 }
756 else if( element == "PINATTR" )
757 {
758 aggregateAttributeValue( tokens, 2 );
759
760 tokensSizeRangeCheck( tokens.size(), 3, INT_MAX, lineNumber, aAscFileName );
761
762 wxString name = tokens[1];
763 wxString Value = tokens[2];
764
765 lt_symbol.Pins.back().PinAttribute.insert( { name, Value } );
766 }
767 else if( element == "SYMBOLTYPE" )
768 {
769 tokensSizeRangeCheck( tokens.size(), 2, 2, lineNumber, aAscFileName );
770
771 wxString symbolType = tokens[1];
772
773 lt_symbol.SymbolType = getSymbolType( symbolType );
774 }
775
776 lineNumber++;
777 }
778
779 return lt_symbol;
780}
781
782
784{
785 LT_SYMBOL lt_symbol;
786
787 lt_symbol.Name = aAscFileName;
790
791 RECTANGLE rect;
792 rect.LineWidth = getLineWidth( "NORMAL" );
794 rect.BotRight = VECTOR2I( 20, 20 );
795 rect.TopLeft = VECTOR2I( -20, -20 );
796
797 lt_symbol.Rectangles.push_back( rect );
798
799 return lt_symbol;
800}
801
802
803std::vector<LTSPICE_SCHEMATIC::LT_ASC> LTSPICE_SCHEMATIC::StructureBuilder()
804{
805 // Initialising Symbol Struct
806
807 std::vector<LT_ASC> ascFiles;
808
809 for( const auto& [ fileName, contents ] : m_fileCache[ wxS( "ascFiles" ) ] )
810 {
811 LT_ASC ascFile;
812 std::vector<LT_SYMBOL> symbolArray;
813
814 ascFile.SheetSize = VECTOR2I( 0, 0 );
815 ascFile.Symbols = symbolArray;
816 ascFile.Version = 0;
817 ascFile.VersionMinor = 0;
818 ascFile.SheetNumber = 0;
819
820 int lineNumber = 1;
821
822 for( wxString line : wxSplit( contents, '\n' ) )
823 {
824 removeCarriageReturn( line );
825
826 wxArrayString tokens = wxSplit( line, ' ' );
827
828 if( tokens.IsEmpty() )
829 continue;
830
831 wxString element = tokens[0].Upper();
832
833 if( element == "SHEET" )
834 {
835 tokensSizeRangeCheck( tokens.size(), 4, 4, lineNumber, fileName );
836
837 wxString sheetNumber = tokens[1];
838 wxString sheetWidth = tokens[2];
839 wxString sheetHeight = tokens[3];
840
841 ascFile.SheetNumber = integerCheck( sheetNumber, lineNumber, fileName );
842 ascFile.SheetSize = pointCheck( sheetWidth, sheetHeight, lineNumber, fileName );
843 }
844 else if( element == "SYMBOL" )
845 {
846 tokensSizeRangeCheck( tokens.size(), 5, 5, lineNumber, fileName );
847
848 wxString symbolName = tokens[1];
849 wxString posX = tokens[2];
850 wxString posY = tokens[3];
851 wxString rotate_mirror_option = tokens[4];
852
853 symbolName.Replace( '\\', '/' );
854
855 try
856 {
857 LT_SYMBOL lt_symbol = SymbolBuilder( symbolName, ascFile );
858 lt_symbol.Offset = pointCheck( posX, posY, lineNumber, fileName );
859 lt_symbol.SymbolOrientation = getSymbolRotationOrMirror( rotate_mirror_option );
860
861 ascFile.Symbols.push_back( lt_symbol );
862 ascFile.BoundingBox.Merge( lt_symbol.Offset );
863 }
864 catch( IO_ERROR& e )
865 {
866 if( m_reporter )
867 m_reporter->Report( e.What(), RPT_SEVERITY_ERROR );
868
869 // Use dummy symbol
870 LT_SYMBOL lt_symbol = MakeDummySymbol( symbolName );
871 lt_symbol.Offset = pointCheck( posX, posY, lineNumber, fileName );
872 lt_symbol.SymbolOrientation = getSymbolRotationOrMirror( rotate_mirror_option );
873
874 ascFile.Symbols.push_back( lt_symbol );
875 ascFile.BoundingBox.Merge( lt_symbol.Offset );
876 }
877 }
878 else if( element == "WIRE" )
879 {
880 tokensSizeRangeCheck( tokens.size(), 5, 5, lineNumber, fileName );
881
882 wxString startPointX = tokens[1];
883 wxString startPointY = tokens[2];
884 wxString endPointX = tokens[3];
885 wxString endPointY = tokens[4];
886
887 WIRE wire;
888 wire.Start = pointCheck( startPointX, startPointY, lineNumber, fileName );
889 wire.End = pointCheck( endPointX, endPointY, lineNumber, fileName );
890
891 ascFile.Wires.push_back( wire );
892 ascFile.BoundingBox.Merge( wire.Start );
893 ascFile.BoundingBox.Merge( wire.End );
894 }
895 else if( element == "FLAG" )
896 {
897 tokensSizeRangeCheck( tokens.size(), 4, 4, lineNumber, fileName );
898
899 wxString posX = tokens[1];
900 wxString posY = tokens[2];
901 wxString name = tokens[3];
902
903 FLAG flag;
904 flag.Offset = pointCheck( posX, posY, lineNumber, fileName );
905 flag.Value = name;
906 flag.FontSize = 2;
907
908 ascFile.Flags.push_back( flag );
909 ascFile.BoundingBox.Merge( flag.Offset );
910 }
911 else if( element == "DATAFLAG" )
912 {
913 tokensSizeRangeCheck( tokens.size(), 4, 4, lineNumber, fileName );
914
915 wxString posX = tokens[1];
916 wxString posY = tokens[2];
917 wxString expression = tokens[3];
918
920 flag.Offset = pointCheck( posX, posY, lineNumber, fileName );
921 flag.Expression = expression;
922 flag.FontSize = 2;
923
924 ascFile.DataFlags.push_back( flag );
925 ascFile.BoundingBox.Merge( flag.Offset );
926 }
927 else if( element == "WINDOW" )
928 {
929 tokensSizeRangeCheck( tokens.size(), 6, 6, lineNumber, fileName );
930
931 wxString number = tokens[1];
932 wxString windowPosX = tokens[2];
933 wxString windowPosY = tokens[3];
934 wxString justification = tokens[4];
935 wxString fontSize = tokens[5];
936
937 int windowNumber = integerCheck( number, lineNumber, fileName );
938 LT_WINDOW* window = nullptr;
939
940 // Overwrite an existing window from the symbol definition
941 for( LT_WINDOW& candidate : ascFile.Symbols.back().Windows )
942 {
943 if( candidate.WindowNumber == windowNumber )
944 {
945 window = &candidate;
946 break;
947 }
948 }
949
950 if( !window )
951 {
952 ascFile.Symbols.back().Windows.emplace_back( LT_WINDOW() );
953 window = &ascFile.Symbols.back().Windows.back();
954 }
955
956 window->WindowNumber = windowNumber;
957 window->Position = pointCheck( windowPosX, windowPosY, lineNumber, fileName );
958 window->Justification = getTextJustification( justification );
959 window->FontSize = integerCheck( fontSize, lineNumber, fileName );
960
961 ascFile.BoundingBox.Merge( window->Position );
962 }
963 else if( element == "SYMATTR" )
964 {
965 tokensSizeRangeCheck( tokens.size(), 3, INT_MAX, lineNumber, fileName );
966
967 aggregateAttributeValue( tokens, 2 );
968
969 wxString name = tokens[1];
970 wxString value = tokens[2];
971
972 if( value == wxS( "\"\"" ) )
973 value = wxEmptyString;
974
975 ascFile.Symbols.back().SymAttributes[ name.Upper() ] = value;
976 }
977 else if( element == "LINE" )
978 {
979 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, fileName );
980
981 wxString lineWidth = tokens[1];
982 wxString startPointX = tokens[2];
983 wxString startPointY = tokens[3];
984 wxString endPointX = tokens[4];
985 wxString endPointY = tokens[5];
986
987 LINE lt_line;
988 lt_line.LineWidth = getLineWidth( lineWidth );
989 lt_line.Start = pointCheck( startPointX, startPointY, lineNumber, fileName );
990 lt_line.End = pointCheck( endPointX, endPointY, lineNumber, fileName );
991
992 int lineStyleNumber = 0; // default
993
994 if( tokens.size() == 7 )
995 {
996 wxString lineStyle = tokens[6];
997 lineStyleNumber = integerCheck( lineStyle, lineNumber, fileName );
998 }
999
1000 lt_line.LineStyle = getLineStyle( lineStyleNumber );
1001
1002 ascFile.Lines.push_back( lt_line );
1003 ascFile.BoundingBox.Merge( lt_line.Start );
1004 ascFile.BoundingBox.Merge( lt_line.End );
1005 }
1006 else if( element == "RECTANGLE" )
1007 {
1008 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, fileName );
1009
1010 // wxString lineWidth = tokens[1];
1011 wxString botRightX = tokens[2];
1012 wxString botRightY = tokens[3];
1013 wxString topLeftX = tokens[4];
1014 wxString topRightY = tokens[5];
1015
1016 RECTANGLE rect;
1017 rect.LineWidth = getLineWidth( tokens[1] );
1018 rect.BotRight = pointCheck( botRightX, botRightY, lineNumber, fileName );
1019 rect.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, fileName );
1020
1021 int lineStyleNumber = 0; // default
1022
1023 if( tokens.size() == 7 )
1024 {
1025 wxString lineStyle = tokens[6];
1026 lineStyleNumber = integerCheck( lineStyle, lineNumber, fileName );
1027 }
1028
1029 rect.LineStyle = getLineStyle( lineStyleNumber );
1030
1031 ascFile.Rectangles.push_back( rect );
1032 ascFile.BoundingBox.Merge( rect.TopLeft );
1033 ascFile.BoundingBox.Merge( rect.BotRight );
1034 }
1035 else if( element == "CIRCLE" )
1036 {
1037 tokensSizeRangeCheck( tokens.size(), 6, 7, lineNumber, fileName );
1038
1039 wxString lineWidth = tokens[1];
1040 wxString botRightX = tokens[2];
1041 wxString botRightY = tokens[3];
1042 wxString topLeftX = tokens[4];
1043 wxString topRightY = tokens[5];
1044
1045 CIRCLE circle;
1046 circle.LineWidth = getLineWidth( lineWidth );
1047 circle.BotRight = pointCheck( botRightX, botRightY, lineNumber, fileName );
1048 circle.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, fileName );
1049
1050 int lineStyleNumber = 0; // default
1051
1052 if( tokens.size() == 7 )
1053 {
1054 wxString lineStyle = tokens[6];
1055 lineStyleNumber = integerCheck( lineStyle, lineNumber, fileName );
1056 }
1057
1058 circle.LineStyle = getLineStyle( lineStyleNumber );
1059
1060 ascFile.Circles.push_back( circle );
1061 ascFile.BoundingBox.Merge( circle.TopLeft );
1062 ascFile.BoundingBox.Merge( circle.BotRight );
1063 }
1064 else if( element == "ARC" )
1065 {
1071 tokensSizeRangeCheck( tokens.size(), 10, 11, lineNumber, fileName );
1072
1073 wxString lineWidth = tokens[1];
1074 wxString botRightX = tokens[2];
1075 wxString botRightY = tokens[3];
1076 wxString topLeftX = tokens[4];
1077 wxString topRightY = tokens[5];
1078 wxString arcStartPointX = tokens[6];
1079 wxString arcStartPointY = tokens[7];
1080 wxString arcEndPointX = tokens[8];
1081 wxString arcEndPointY = tokens[9];
1082
1083 ARC arc;
1084 arc.LineWidth = getLineWidth( lineWidth );
1085 arc.BotRight = pointCheck( botRightX, botRightY, lineNumber, fileName );
1086 arc.TopLeft = pointCheck( topLeftX, topRightY, lineNumber, fileName );
1087 arc.ArcEnd = pointCheck( arcStartPointX, arcStartPointY, lineNumber, fileName );
1088 arc.ArcStart = pointCheck( arcEndPointX, arcEndPointY, lineNumber, fileName );
1089
1090 int lineStyleNumber = 0; // default
1091
1092 if( tokens.size() == 11 )
1093 {
1094 wxString lineStyle = tokens[10];
1095 lineStyleNumber = integerCheck( lineStyle, lineNumber, fileName );
1096 }
1097
1098 arc.LineStyle = getLineStyle( lineStyleNumber );
1099
1100 ascFile.Arcs.push_back( arc );
1101 ascFile.BoundingBox.Merge( arc.TopLeft );
1102 ascFile.BoundingBox.Merge( arc.BotRight );
1103 }
1104 else if( element == "IOPIN" )
1105 {
1106 tokensSizeRangeCheck( tokens.size(), 4, 4, lineNumber, fileName );
1107
1108 wxString pinLocationX = tokens[1];
1109 wxString pinLocationY = tokens[2];
1110 wxString pinPolarity = tokens[3];
1111
1112 IOPIN iopin;
1113 iopin.Location = pointCheck( pinLocationX, pinLocationY, lineNumber, fileName );
1114 iopin.Polarity = getPolarity( pinPolarity );
1115
1116 ascFile.Iopins.push_back( iopin );
1117 ascFile.BoundingBox.Merge( iopin.Location );
1118 }
1119 else if( element == "TEXT" )
1120 {
1121 aggregateAttributeValue( tokens, 5 );
1122
1123 tokensSizeRangeCheck( tokens.size(), 6, INT_MAX, lineNumber, fileName );
1124
1125 wxString positionX = tokens[1];
1126 wxString positionY = tokens[2];
1127 wxString justification = tokens[3];
1128 wxString fontSize = tokens[4];
1129 wxString value = tokens[5];
1130
1131 TEXT text;
1132 text.Offset = pointCheck( positionX, positionY, lineNumber, fileName );
1133 text.Justification = getTextJustification( justification );
1134 text.FontSize = integerCheck( fontSize, lineNumber, fileName );
1135
1136 if( value.StartsWith( wxS( "!" ), &text.Value ) )
1137 text.Value.Replace( wxS( "! " ), wxS( "\n" ) ); // replace subsequent ! with \n
1138 else if( value.StartsWith( wxS( ";" ), &text.Value ) )
1139 text.Value.Replace( wxS( "; " ), wxS( "\n" ) ); // replace subsequent ; with \n
1140 else
1141 text.Value = value;
1142
1143 text.Value.Replace( wxS( "\\n" ), wxS( "\n" ) );
1144
1145 ascFile.Texts.push_back( text );
1146 ascFile.BoundingBox.Merge( text.Offset );
1147 }
1148 else if( element == "BUSTAP" )
1149 {
1150 tokensSizeRangeCheck( tokens.size(), 5, 5, lineNumber, fileName );
1151
1152 wxString startPointX = tokens[1];
1153 wxString startPointY = tokens[2];
1154 wxString endPointX = tokens[3];
1155 wxString endPointY = tokens[4];
1156
1157 BUSTAP bustap;
1158 bustap.Start = pointCheck( startPointX, startPointY, lineNumber, fileName );
1159 bustap.End = pointCheck( endPointX, endPointY, lineNumber, fileName );
1160
1161 ascFile.Bustap.push_back( bustap );
1162 ascFile.BoundingBox.Merge( bustap.Start );
1163 ascFile.BoundingBox.Merge( bustap.End );
1164 }
1165 else if( element == "VERSION" )
1166 {
1167 wxString versionNumber = tokens[1];
1168 if( versionNumber.Contains( '.' ) )
1169 {
1170 wxString majorStr = versionNumber.BeforeFirst( '.' );
1171 wxString minorStr = versionNumber.AfterFirst( '.' );
1172 ascFile.Version = integerCheck( majorStr, lineNumber, fileName );
1173 ascFile.VersionMinor = integerCheck( minorStr, lineNumber, fileName );
1174 }
1175 else
1176 {
1177 ascFile.Version = integerCheck( versionNumber, lineNumber, fileName );
1178 }
1179 }
1180
1181 lineNumber++;
1182 }
1183
1184 ascFiles.push_back( std::move( ascFile ) );
1185 }
1186
1187 return ascFiles;
1188}
1189
1190
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:237
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:75
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition reporter.h:104
Holds all the data relating to one schematic.
Definition schematic.h:89
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:146
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:143
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:57
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:687
Definition of file extensions used in Kicad.