KiCad PCB EDA Suite
cadstar_sch_archive_loader.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) 2020-2021 Roberto Fernandez Bautista <[email protected]>
5 * Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
27
28#include <bus_alias.h>
29#include <core/mirror.h>
30#include <core/kicad_algo.h>
31#include <eda_text.h>
32#include <lib_shape.h>
33#include <lib_text.h>
34#include <macros.h>
35#include <progress_reporter.h>
36#include <string_utils.h>
37#include <sch_bus_entry.h>
38#include <sch_edit_frame.h> //SYMBOL_ORIENTATION_T
39#include <sch_io_mgr.h>
40#include <sch_junction.h>
41#include <sch_line.h>
42#include <sch_screen.h>
43#include <sch_sheet.h>
44#include <sch_sheet_path.h>
45#include <sch_sheet_pin.h>
46#include <sch_label.h>
47#include <schematic.h>
48#include <trigo.h>
50
51
52const wxString PartNameFieldName = "Part Name";
53
54
57 const wxFileName& aLibraryFileName )
58{
60 m_progressReporter->SetNumPhases( 3 ); // (0) Read file, (1) Parse file, (2) Load file
61
62 Parse();
63
65
66 //Note: can't use getKiCadPoint() due VECTOR2I being int - need long long to make the check
67 long long designSizeXkicad = (long long) designLimit.x / KiCadUnitDivider;
68 long long designSizeYkicad = (long long) designLimit.y / KiCadUnitDivider;
69
70 // Max size limited by the positive dimension of VECTOR2I (which is an int)
71 constexpr long long maxDesignSizekicad = std::numeric_limits<int>::max();
72
73 if( designSizeXkicad > maxDesignSizekicad || designSizeYkicad > maxDesignSizekicad )
74 {
76 _( "The design is too large and cannot be imported into KiCad. \n"
77 "Please reduce the maximum design size in CADSTAR by navigating to: \n"
78 "Design Tab -> Properties -> Design Options -> Maximum Design Size. \n"
79 "Current Design size: %.2f, %.2f millimeters. \n"
80 "Maximum permitted design size: %.2f, %.2f millimeters.\n" ),
81 (double) designSizeXkicad / SCH_IU_PER_MM,
82 (double) designSizeYkicad / SCH_IU_PER_MM,
83 (double) maxDesignSizekicad / SCH_IU_PER_MM,
84 (double) maxDesignSizekicad / SCH_IU_PER_MM ) );
85 }
86
87 // Assume the center at 0,0 since we are going to be translating the design afterwards anyway
88 m_designCenter = { 0, 0 };
89
90 m_schematic = aSchematic;
91 m_rootSheet = aRootSheet;
92 m_plugin = aSchPlugin;
93 m_libraryFileName = aLibraryFileName;
94
96 {
98 long numSteps = 11; // one step for each of below functions + one at the end of import
99
100 // Step 4 is by far the longest - add granularity in reporting
101 numSteps += Parts.PartDefinitions.size();
102
104 }
105
106 loadTextVariables(); // Load text variables right at the start to ensure bounding box
107 // calculations work correctly for text items
108 checkPoint(); // Step 1
109 loadSheets();
110 checkPoint(); // Step 2
112 checkPoint(); // Step 3
114 checkPoint(); // Step 4, Subdivided into extra steps
116 checkPoint(); // Step 5
117 loadBusses();
118 checkPoint(); // Step 6
119 loadNets();
120 checkPoint(); // Step 7
121 loadFigures();
122 checkPoint(); // Step 8
123 loadTexts();
124 checkPoint(); // Step 9
126 checkPoint(); // Step 10
127
128 if( Schematic.VariantHierarchy.Variants.size() > 0 )
129 {
130 m_reporter->Report( wxString::Format( _( "The CADSTAR design contains variants which has "
131 "no KiCad equivalent. Only the master variant "
132 "('%s') was loaded." ),
133 Schematic.VariantHierarchy.Variants.at( "V0" ).Name ),
135 }
136
137 if( Schematic.Groups.size() > 0 )
138 {
139 m_reporter->Report( _( "The CADSTAR design contains grouped items which has no KiCad "
140 "equivalent. Any grouped items have been ungrouped." ),
142 }
143
144 if( Schematic.ReuseBlocks.size() > 0 )
145 {
146 m_reporter->Report( _( "The CADSTAR design contains re-use blocks which has no KiCad "
147 "equivalent. The re-use block information has been discarded during "
148 "the import." ),
150 }
151
152
153 // For all sheets, center all elements and re calculate the page size:
154 for( std::pair<LAYER_ID, SCH_SHEET*> sheetPair : m_sheetMap )
155 {
156 SCH_SHEET* sheet = sheetPair.second;
157
158 // Calculate the new sheet size.
159 BOX2I sheetBoundingBox;
160
161 for( SCH_ITEM* item : sheet->GetScreen()->Items() )
162 {
163 BOX2I bbox;
164
165 // Only use the visible fields of the symbols to calculate their bounding box
166 // (hidden fields could be very long and artificially enlarge the sheet bounding box)
167 if( item->Type() == SCH_SYMBOL_T )
168 {
169 SCH_SYMBOL* comp = static_cast<SCH_SYMBOL*>( item );
170 bbox = comp->GetBodyAndPinsBoundingBox();
171
172 for( const SCH_FIELD& field : comp->GetFields() )
173 {
174 if( field.IsVisible() )
175 bbox.Merge( field.GetBoundingBox() );
176 }
177 }
178 else if( item->Type() == SCH_TEXT_T )
179 {
180 SCH_TEXT* txtItem = static_cast<SCH_TEXT*>( item );
181 wxString txt = txtItem->GetText();
182
183 if( txt.Contains( "${" ) )
184 continue; // We can't calculate bounding box of text items with variables
185 else
186 bbox = txtItem->GetBoundingBox();
187 }
188 else
189 {
190 bbox = item->GetBoundingBox();
191 }
192
193 sheetBoundingBox.Merge( bbox );
194 }
195
196 // Find the working grid of the original CADSTAR design
198
203
205
206 auto roundToNearestGrid =
207 [&]( int aNumber ) -> int
208 {
209 int error = aNumber % grid;
210 int absError = sign( error ) * error;
211
212 if( absError > ( grid / 2 ) )
213 return aNumber + ( sign( error ) * grid ) - error;
214 else
215 return aNumber - error;
216 };
217
218 // When exporting to pdf, CADSTAR applies a margin of 3% of the longest dimension (height
219 // or width) to all 4 sides (top, bottom, left right). For the import, we are also rounding
220 // the margin to the nearest grid, ensuring all items remain on the grid.
221 wxSize targetSheetSize = (wxSize)sheetBoundingBox.GetSize();
222 int longestSide = std::max( targetSheetSize.x, targetSheetSize.y );
223 int margin = ( (double) longestSide * 0.03 );
224 margin = roundToNearestGrid( margin );
225 targetSheetSize.IncBy( margin * 2, margin * 2 );
226
227 // Update page size always
228 PAGE_INFO pageInfo = sheet->GetScreen()->GetPageSettings();
229 pageInfo.SetWidthMils( schIUScale.IUToMils( targetSheetSize.x ) );
230 pageInfo.SetHeightMils( schIUScale.IUToMils( targetSheetSize.y ) );
231
232 // Set the new sheet size.
233 sheet->GetScreen()->SetPageSettings( pageInfo );
234
235 wxSize pageSizeIU = sheet->GetScreen()->GetPageSettings().GetSizeIU( schIUScale.IU_PER_MILS );
236 VECTOR2I sheetcentre( pageSizeIU.x / 2, pageSizeIU.y / 2 );
237 VECTOR2I itemsCentre = sheetBoundingBox.Centre();
238
239 // round the translation to nearest point on the grid
240 VECTOR2I translation = sheetcentre - itemsCentre;
241 translation.x = roundToNearestGrid( translation.x );
242 translation.y = roundToNearestGrid( translation.y );
243
244 // Translate the items.
245 std::vector<SCH_ITEM*> allItems;
246
247 std::copy( sheet->GetScreen()->Items().begin(), sheet->GetScreen()->Items().end(),
248 std::back_inserter( allItems ) );
249
250 for( SCH_ITEM* item : allItems )
251 {
252 item->Move( translation );
253 item->ClearFlags();
254 sheet->GetScreen()->Update( item );
255 }
256 }
257
258 checkPoint();
259
260 m_reporter->Report( _( "CADSTAR fonts are different to the ones in KiCad. This will likely "
261 "result in alignment issues. Please review the imported text elements "
262 "carefully and correct manually if required." ),
264
265 m_reporter->Report( _( "The CADSTAR design has been imported successfully.\n"
266 "Please review the import errors and warnings (if any)." ) );
267}
268
269
271{
272 const std::vector<LAYER_ID>& orphanSheets = findOrphanSheets();
273 SCH_SHEET_PATH rootPath;
274 rootPath.push_back( m_rootSheet );
275 rootPath.SetPageNumber( wxT( "1" ) );
276
277 if( orphanSheets.size() > 1 )
278 {
279 int x = 1;
280 int y = 1;
281
282 for( LAYER_ID sheetID : orphanSheets )
283 {
284 VECTOR2I pos( x * schIUScale.MilsToIU( 1000 ), y * schIUScale.MilsToIU( 1000 ) );
285 wxSize siz( schIUScale.MilsToIU( 1000 ), schIUScale.MilsToIU( 1000 ) );
286
287 loadSheetAndChildSheets( sheetID, pos, siz, rootPath );
288
289 x += 2;
290
291 if( x > 10 ) // start next row
292 {
293 x = 1;
294 y += 2;
295 }
296 }
297 }
298 else if( orphanSheets.size() > 0 )
299 {
300 LAYER_ID rootSheetID = orphanSheets.at( 0 );
301
302 wxFileName loadedFilePath = wxFileName( Filename );
303
304 std::string filename = wxString::Format( "%s_%02d",
305 loadedFilePath.GetName(),
306 getSheetNumber( rootSheetID ) ).ToStdString();
307 ReplaceIllegalFileNameChars( &filename );
308 filename += wxT( "." ) + KiCadSchematicFileExtension;
309
310 wxFileName fn( m_schematic->Prj().GetProjectPath() + filename );
311 m_rootSheet->GetScreen()->SetFileName( fn.GetFullPath() );
312
313 m_sheetMap.insert( { rootSheetID, m_rootSheet } );
314 loadChildSheets( rootSheetID, rootPath );
315 }
316 else
317 {
318 THROW_IO_ERROR( _( "The CADSTAR schematic might be corrupt: there is no root sheet." ) );
319 }
320}
321
322
324{
325 for( std::pair<BLOCK_ID, BLOCK> blockPair : Schematic.Blocks )
326 {
327 BLOCK& block = blockPair.second;
328 LAYER_ID sheetID = "";
329
330 if( block.Type == BLOCK::TYPE::PARENT )
331 sheetID = block.LayerID;
332 else if( block.Type == BLOCK::TYPE::CHILD )
333 sheetID = block.AssocLayerID;
334 else
335 continue;
336
337 if( m_sheetMap.find( sheetID ) != m_sheetMap.end() )
338 {
339 SCH_SHEET* sheet = m_sheetMap.at( sheetID );
340
341 for( std::pair<TERMINAL_ID, TERMINAL> termPair : block.Terminals )
342 {
343 TERMINAL term = termPair.second;
344 wxString name = "YOU SHOULDN'T SEE THIS TEXT. THIS IS A BUG.";
345
346 SCH_HIERLABEL* sheetPin = nullptr;
347
348 if( block.Type == BLOCK::TYPE::PARENT )
349 sheetPin = new SCH_HIERLABEL();
350 else if( block.Type == BLOCK::TYPE::CHILD )
351 sheetPin = new SCH_SHEET_PIN( sheet );
352
353 sheetPin->SetText( name );
355 sheetPin->SetTextSpinStyle( getSpinStyle( term.OrientAngle, false ) );
356 sheetPin->SetPosition( getKiCadPoint( term.Position ) );
357
358 if( sheetPin->Type() == SCH_SHEET_PIN_T )
359 sheet->AddPin( (SCH_SHEET_PIN*) sheetPin );
360 else
361 sheet->GetScreen()->Append( sheetPin );
362
363 BLOCK_PIN_ID blockPinID = std::make_pair( block.ID, term.ID );
364 m_sheetPinMap.insert( { blockPinID, sheetPin } );
365 }
366 }
367 }
368}
369
370
372{
373 for( std::pair<PART_ID, PART> partPair : Parts.PartDefinitions )
374 {
375 PART_ID partID = partPair.first;
376 PART part = partPair.second;
377
378 wxString escapedPartName = EscapeString( part.Name, CTX_LIBID );
379 LIB_SYMBOL* kiPart = new LIB_SYMBOL( escapedPartName );
380
381 kiPart->SetUnitCount( part.Definition.GateSymbols.size() );
382 bool ok = true;
383
384 for( std::pair<GATE_ID, PART::DEFINITION::GATE> gatePair : part.Definition.GateSymbols )
385 {
386 GATE_ID gateID = gatePair.first;
387 PART::DEFINITION::GATE gate = gatePair.second;
388 SYMDEF_ID symbolID = getSymDefFromName( gate.Name, gate.Alternate );
389
390 if( symbolID.IsEmpty() )
391 {
392 m_reporter->Report( wxString::Format( _( "Part definition '%s' references symbol "
393 "'%s' (alternate '%s') which could not be "
394 "found in the symbol library. The part has "
395 "not been loaded into the KiCad library." ),
396 part.Name,
397 gate.Name,
398 gate.Alternate ),
400
401 ok = false;
402 break;
403 }
404
405 m_partSymbolsMap.insert( { { partID, gateID }, symbolID } );
406 loadSymDefIntoLibrary( symbolID, &part, gateID, kiPart );
407 }
408
409 if( ok && part.Definition.GateSymbols.size() != 0 )
410 {
411 ( *m_plugin )->SaveSymbol( m_libraryFileName.GetFullPath(), kiPart );
412
413 LIB_SYMBOL* loadedPart =
414 ( *m_plugin )->LoadSymbol( m_libraryFileName.GetFullPath(), kiPart->GetName() );
415
416 m_partMap.insert( { partID, loadedPart } );
417 }
418 else
419 {
420 if( part.Definition.GateSymbols.size() == 0 )
421 {
423 wxString::Format( _( "Part definition '%s' has an incomplete definition (no"
424 " symbol definitions are associated with it). The part"
425 " has not been loaded into the KiCad library." ),
426 part.Name ),
428 }
429
430 // Don't save in the library, but still keep it cached as some of the units might have
431 // been loaded correctly (saving us time later on), plus the part definition contains
432 // the part name, which is important to load
433 m_partMap.insert( { partID, kiPart } );
434 }
435
436 checkPoint();
437 }
438}
439
440
442{
443 for( std::pair<SYMBOL_ID, SYMBOL> symPair : Schematic.Symbols )
444 {
445 SYMBOL sym = symPair.second;
446
447 if( !sym.VariantID.empty() && sym.VariantParentSymbolID != sym.ID )
448 continue; // Only load master Variant
449
450 if( sym.IsComponent )
451 {
452 if( m_partMap.find( sym.PartRef.RefID ) == m_partMap.end() )
453 {
454 m_reporter->Report( wxString::Format( _( "Symbol '%s' references part '%s' which "
455 "could not be found in the library. The "
456 "symbol was not loaded" ),
458 sym.PartRef.RefID ),
460
461 continue;
462 }
463
464 if( sym.GateID.IsEmpty() )
465 sym.GateID = wxT( "A" ); // Assume Gate "A" if unspecified
466
467 PART_GATE_ID partSymbolID = { sym.PartRef.RefID, sym.GateID };
468 LIB_SYMBOL* kiPart = m_partMap.at( sym.PartRef.RefID );
469 bool copy = false;
470
471 // The symbol definition in the part either does not exist for this gate number
472 // or is different to the symbol instance. We need to load a new symbol
473 if( m_partSymbolsMap.find( partSymbolID ) == m_partSymbolsMap.end()
474 || m_partSymbolsMap.at( partSymbolID ) != sym.SymdefID )
475 {
476 kiPart = new LIB_SYMBOL( *kiPart ); // Make a copy
477 copy = true;
478 const PART& part = Parts.PartDefinitions.at( sym.PartRef.RefID );
479 loadSymDefIntoLibrary( sym.SymdefID, &part, sym.GateID, kiPart );
480 }
481
482 LIB_SYMBOL* scaledPart = getScaledLibPart( kiPart, sym.ScaleRatioNumerator,
484
485 EDA_ANGLE symOrient = ANGLE_0;
486 SCH_SYMBOL* symbol = loadSchematicSymbol( sym, *scaledPart, symOrient );
487
488 delete scaledPart;
489
490 if( copy )
491 delete kiPart;
492
493 SCH_FIELD* refField = symbol->GetField( REFERENCE_FIELD );
494
495 sym.ComponentRef.Designator.Replace( wxT( "\n" ), wxT( "\\n" ) );
496 sym.ComponentRef.Designator.Replace( wxT( "\r" ), wxT( "\\r" ) );
497 sym.ComponentRef.Designator.Replace( wxT( "\t" ), wxT( "\\t" ) );
498 sym.ComponentRef.Designator.Replace( wxT( " " ), wxT( "_" ) );
499
500 refField->SetText( sym.ComponentRef.Designator );
501 loadSymbolFieldAttribute( sym.ComponentRef.AttrLoc, symOrient, sym.Mirror, refField );
502
503 if( sym.HasPartRef )
504 {
505 SCH_FIELD* partField = symbol->FindField( PartNameFieldName );
506
507 if( !partField )
508 {
509 int fieldID = symbol->GetFieldCount();
510 partField = symbol->AddField( SCH_FIELD( VECTOR2I(), fieldID, symbol,
512 }
513
514 wxASSERT( partField->GetName() == PartNameFieldName );
515
516 wxString partname = getPart( sym.PartRef.RefID ).Name;
517 partname.Replace( wxT( "\n" ), wxT( "\\n" ) );
518 partname.Replace( wxT( "\r" ), wxT( "\\r" ) );
519 partname.Replace( wxT( "\t" ), wxT( "\\t" ) );
520 partField->SetText( partname );
521
522 loadSymbolFieldAttribute( sym.PartRef.AttrLoc, symOrient, sym.Mirror, partField );
523
525 }
526
527 for( auto attr : sym.AttributeValues )
528 {
529 ATTRIBUTE_VALUE attrVal = attr.second;
530
531 if( attrVal.HasLocation )
532 {
533 wxString attrName = getAttributeName( attrVal.AttributeID );
534 SCH_FIELD* attrField = symbol->FindField( attrName );
535
536 if( !attrField )
537 {
538 int fieldID = symbol->GetFieldCount();
539 attrField = symbol->AddField(
540 SCH_FIELD( VECTOR2I(), fieldID, symbol, attrName ) );
541 }
542
543 wxASSERT( attrField->GetName() == attrName );
544
545 attrVal.Value.Replace( wxT( "\n" ), wxT( "\\n" ) );
546 attrVal.Value.Replace( wxT( "\r" ), wxT( "\\r" ) );
547 attrVal.Value.Replace( wxT( "\t" ), wxT( "\\t" ) );
548 attrField->SetText( attrVal.Value );
549
550 loadSymbolFieldAttribute( attrVal.AttributeLocation, symOrient, sym.Mirror,
551 attrField );
552 attrField->SetVisible( isAttributeVisible( attrVal.AttributeID ) );
553 }
554 }
555 }
556 else if( sym.IsSymbolVariant )
557 {
559 {
561 _( "Symbol ID '%s' references library symbol '%s' which could not be "
562 "found in the library. Did you export all items of the design?" ),
563 sym.ID, sym.PartRef.RefID ) );
564 }
565
566 SYMDEF_SCM libSymDef = Library.SymbolDefinitions.at( sym.SymdefID );
567
568 if( libSymDef.Terminals.size() != 1 )
569 {
571 _( "Symbol ID '%s' is a signal reference or global signal but it has too "
572 "many pins. The expected number of pins is 1 but %d were found." ),
573 sym.ID, libSymDef.Terminals.size() ) );
574 }
575
576 if( sym.SymbolVariant.Type == SYMBOLVARIANT::TYPE::GLOBALSIGNAL )
577 {
578 SYMDEF_ID symID = sym.SymdefID;
579 LIB_SYMBOL* kiPart = nullptr;
580
581 // In CADSTAR "GlobalSignal" is a special type of symbol which defines
582 // a Power Symbol. The "Alternate" name defines the default net name of
583 // the power symbol but this can be overridden in the design itself.
584 wxString libraryNetName = Library.SymbolDefinitions.at( symID ).Alternate;
585
586 // Name of the net that the symbol instance in CADSTAR refers to:
587 wxString symbolInstanceNetName = sym.SymbolVariant.Reference;
588 symbolInstanceNetName = EscapeString( symbolInstanceNetName, CTX_LIBID );
589
590 // Name of the symbol we will use for saving the part in KiCad
591 // Note: In CADSTAR all power symbols will start have the reference name be
592 // "GLOBALSIGNAL" followed by the default net name, so it makes sense to save
593 // the symbol in KiCad as the default net name as well.
594 wxString libPartName = libraryNetName;
595
596 // In CADSTAR power symbol instances can refer to a different net to that defined
597 // in the library. This causes problems in KiCad v6 as it breaks connectivity when
598 // the user decides to update all symbols from library. We handle this by creating
599 // individual versions of the power symbol for each net name.
600 if( libPartName != symbolInstanceNetName )
601 {
602 libPartName += wxT( " (" ) + symbolInstanceNetName + wxT( ")" );
603 }
604
605 if( m_powerSymLibMap.find( libPartName ) == m_powerSymLibMap.end() )
606 {
607 SYMDEF_SCM symbolDef = Library.SymbolDefinitions.at( symID );
608
609 kiPart = new LIB_SYMBOL( libPartName );
610 kiPart->SetPower();
611 loadSymDefIntoLibrary( symID, nullptr, "A", kiPart );
612
613 kiPart->GetValueField().SetText( symbolInstanceNetName );
614
615 if( symbolDef.TextLocations.find( SIGNALNAME_ORIGIN_ATTRID )
616 != symbolDef.TextLocations.end() )
617 {
618 TEXT_LOCATION txtLoc =
620
621 VECTOR2I valPos = getKiCadLibraryPoint( txtLoc.Position, symbolDef.Origin );
622
623 kiPart->GetValueField().SetPosition( valPos );
624 kiPart->GetValueField().SetVisible( true );
625 }
626 else
627 {
628 kiPart->GetValueField().SetVisible( false );
629 }
630
631 kiPart->GetReferenceField().SetText( "#PWR" );
632 kiPart->GetReferenceField().SetVisible( false );
633 ( *m_plugin )->SaveSymbol( m_libraryFileName.GetFullPath(), kiPart );
634 m_powerSymLibMap.insert( { libPartName, kiPart } );
635 }
636 else
637 {
638 kiPart = m_powerSymLibMap.at( libPartName );
639 wxASSERT( kiPart->GetValueField().GetText() == symbolInstanceNetName );
640 }
641
642 LIB_SYMBOL* scaledPart = getScaledLibPart( kiPart, sym.ScaleRatioNumerator,
644
645 EDA_ANGLE returnedOrient = ANGLE_0;
646 SCH_SYMBOL* symbol = loadSchematicSymbol( sym, *scaledPart, returnedOrient );
647 m_powerSymMap.insert( { sym.ID, symbol } );
648
649 delete scaledPart;
650 }
651 else if( sym.SymbolVariant.Type == SYMBOLVARIANT::TYPE::SIGNALREF )
652 {
653 // There should only be one pin and we'll use that to set the position
654 TERMINAL& symbolTerminal = libSymDef.Terminals.begin()->second;
655 VECTOR2I terminalPosOffset = symbolTerminal.Position - libSymDef.Origin;
656 EDA_ANGLE rotate = getAngle( sym.OrientAngle );
657
658 if( sym.Mirror )
659 rotate += ANGLE_180;
660
661 RotatePoint( terminalPosOffset, -rotate );
662
663 SCH_GLOBALLABEL* netLabel = new SCH_GLOBALLABEL;
664 netLabel->SetPosition( getKiCadPoint( (VECTOR2I)sym.Origin + terminalPosOffset ) );
665 netLabel->SetText( "***UNKNOWN NET****" ); // This should be later updated when we load the netlist
666 netLabel->SetTextSize( wxSize( schIUScale.MilsToIU( 50 ), schIUScale.MilsToIU( 50 ) ) );
667
668 SYMDEF_SCM symbolDef = Library.SymbolDefinitions.at( sym.SymdefID );
669
670 if( symbolDef.TextLocations.count( LINK_ORIGIN_ATTRID ) )
671 {
672 TEXT_LOCATION linkOrigin = symbolDef.TextLocations.at( LINK_ORIGIN_ATTRID );
673 applyTextSettings( netLabel, linkOrigin.TextCodeID, linkOrigin.Alignment,
674 linkOrigin.Justification );
675 }
676
677 netLabel->SetTextSpinStyle( getSpinStyle( sym.OrientAngle, sym.Mirror ) );
678
679 if( libSymDef.Alternate.Lower().Contains( "in" ) )
681 else if( libSymDef.Alternate.Lower().Contains( "bi" ) )
683 else if( libSymDef.Alternate.Lower().Contains( "out" ) )
685 else
687
688 SCH_SCREEN* screen = m_sheetMap.at( sym.LayerID )->GetScreen();
689
690 // autoplace intersheet refs
691 netLabel->AutoplaceFields( screen, false );
692
693 screen->Append( netLabel );
694 m_globalLabelsMap.insert( { sym.ID, netLabel } );
695 }
696 else
697 {
698 wxASSERT_MSG( false, "Unknown Symbol Variant." );
699 }
700 }
701 else
702 {
703 m_reporter->Report( wxString::Format( _( "Symbol ID '%s' is of an unknown type. It is "
704 "neither a symbol or a net power / symbol. "
705 "The symbol was not loaded." ),
706 sym.ID ),
708 }
709
710 if( sym.ScaleRatioDenominator != 1 || sym.ScaleRatioNumerator != 1 )
711 {
712 wxString symbolName = sym.ComponentRef.Designator;
713
714 if( symbolName.empty() )
715 symbolName = wxString::Format( "ID: %s", sym.ID );
716 else
717 symbolName += sym.GateID;
718
719 m_reporter->Report( wxString::Format( _( "Symbol '%s' is scaled in the original "
720 "CADSTAR schematic but this is not supported "
721 "in KiCad. When the symbol is reloaded from "
722 "the library, it will revert to the original "
723 "1:1 scale." ),
724 symbolName,
725 sym.PartRef.RefID ),
727 }
728 }
729}
730
731
733{
734 for( std::pair<BUS_ID, BUS> busPair : Schematic.Buses )
735 {
736 BUS bus = busPair.second;
737 bool firstPt = true;
738 VERTEX last;
739
740 if( bus.LayerID != wxT( "NO_SHEET" ) )
741 {
742 SCH_SCREEN* screen = m_sheetMap.at( bus.LayerID )->GetScreen();
743 std::shared_ptr<BUS_ALIAS> kiBusAlias = std::make_shared<BUS_ALIAS>();
744
745 kiBusAlias->SetName( bus.Name );
746 kiBusAlias->SetParent( screen );
747 screen->AddBusAlias( kiBusAlias );
748 m_busesMap.insert( { bus.ID, kiBusAlias } );
749
750 SCH_LABEL* label = new SCH_LABEL();
751
752 wxString busname = HandleTextOverbar( bus.Name );
753
754 label->SetText( wxT( "{" ) + busname + wxT( "}" ) );
755 label->SetVisible( true );
756 screen->Append( label );
757
758 SHAPE_LINE_CHAIN busLineChain; // to compute nearest segment to bus label
759
760 for( const VERTEX& cur : bus.Shape.Vertices )
761 {
762 busLineChain.Append( getKiCadPoint( cur.End ) );
763
764 if( firstPt )
765 {
766 last = cur;
767 firstPt = false;
768
769 if( !bus.HasBusLabel )
770 {
771 // Add a bus label on the starting point if the original CADSTAR design
772 // does not have an explicit label
773 label->SetPosition( getKiCadPoint( last.End ) );
774 }
775
776 continue;
777 }
778
779
780 SCH_LINE* kiBus = new SCH_LINE();
781
782 kiBus->SetStartPoint( getKiCadPoint( last.End ) );
783 kiBus->SetEndPoint( getKiCadPoint( cur.End ) );
784 kiBus->SetLayer( LAYER_BUS );
786 screen->Append( kiBus );
787
788 last = cur;
789 }
790
791 if( bus.HasBusLabel )
792 {
793 //lets find the closest point in the busline to the label
794 VECTOR2I busLabelLoc = getKiCadPoint( bus.BusLabel.Position );
795 VECTOR2I nearestPt = busLineChain.NearestPoint( busLabelLoc );
796
797 label->SetPosition( nearestPt );
798
799 applyTextSettings( label,
803
804 // Re-set bus name as it might have been "double-escaped" after applyTextSettings
805 label->SetText( wxT( "{" ) + busname + wxT( "}" ) );
806
807 // Note orientation of the bus label will be determined in loadNets
808 // (the position of the wire will determine how best to place the bus label)
809 }
810 }
811 }
812}
813
814
816{
817 for( std::pair<NET_ID, NET_SCH> netPair : Schematic.Nets )
818 {
819 NET_SCH net = netPair.second;
820 wxString netName = net.Name;
821 std::map<NETELEMENT_ID, SCH_LABEL*> netlabels;
822
823 if( netName.IsEmpty() )
824 netName = wxString::Format( "$%ld", net.SignalNum );
825
826 netName = HandleTextOverbar( netName );
827
828 for( std::pair<NETELEMENT_ID, NET_SCH::SYM_TERM> terminalPair : net.Terminals )
829 {
830 NET_SCH::SYM_TERM netTerm = terminalPair.second;
831
832 if( m_powerSymMap.find( netTerm.SymbolID ) != m_powerSymMap.end() )
833 {
834 SCH_FIELD* val = m_powerSymMap.at( netTerm.SymbolID )->GetField( VALUE_FIELD );
835 val->SetText( netName );
836 val->SetBold( false );
837 val->SetVisible( false );
838
839 if( netTerm.HasNetLabel )
840 {
841 val->SetVisible( true );
842 val->SetPosition( getKiCadPoint( netTerm.NetLabel.Position ) );
843
845 netTerm.NetLabel.TextCodeID,
846 netTerm.NetLabel.Alignment,
847 netTerm.NetLabel.Justification,
848 netTerm.NetLabel.OrientAngle,
849 netTerm.NetLabel.Mirror );
850 }
851 }
852 else if( m_globalLabelsMap.find( netTerm.SymbolID ) != m_globalLabelsMap.end() )
853 {
854 m_globalLabelsMap.at( netTerm.SymbolID )->SetText( netName );
855
856 LAYER_ID sheet = Schematic.Symbols.at( netTerm.SymbolID ).LayerID;
857
858 if( m_sheetMap.count( sheet ) )
859 {
860 SCH_SCREEN* screen = m_sheetMap.at( sheet )->GetScreen();
861
862 // autoplace intersheet refs again since we've changed the name
863 m_globalLabelsMap.at( netTerm.SymbolID )->AutoplaceFields( screen, false );
864 }
865 }
866 else if( !net.Name.IsEmpty() && Schematic.Symbols.count( netTerm.SymbolID )
867 && netTerm.HasNetLabel )
868 {
869 // This is a named net that connects to a schematic symbol pin - we need to put a label
870 SCH_LABEL* label = new SCH_LABEL();
871 label->SetText( netName );
872
873 POINT pinLocation = getLocationOfNetElement( net, netTerm.ID );
874 label->SetPosition( getKiCadPoint( pinLocation ) );
875 label->SetVisible( true );
876
877 applyTextSettings( label, netTerm.NetLabel.TextCodeID, netTerm.NetLabel.Alignment,
878 netTerm.NetLabel.Justification );
879
880 netlabels.insert( { netTerm.ID, label } );
881
882 LAYER_ID sheet = Schematic.Symbols.at( netTerm.SymbolID ).LayerID;
883 m_sheetMap.at( sheet )->GetScreen()->Append( label );
884 }
885 }
886
887 auto getHierarchicalLabel =
888 [&]( NETELEMENT_ID aNode ) -> SCH_HIERLABEL*
889 {
890 if( aNode.Contains( "BLKT" ) )
891 {
892 NET_SCH::BLOCK_TERM blockTerm = net.BlockTerminals.at( aNode );
893 BLOCK_PIN_ID blockPinID = std::make_pair( blockTerm.BlockID,
894 blockTerm.TerminalID );
895
896 if( m_sheetPinMap.find( blockPinID ) != m_sheetPinMap.end() )
897 return m_sheetPinMap.at( blockPinID );
898 }
899
900 return nullptr;
901 };
902
903 //Add net name to all hierarchical pins (block terminals in CADSTAR)
904 for( std::pair<NETELEMENT_ID, NET_SCH::BLOCK_TERM> blockPair : net.BlockTerminals )
905 {
906 SCH_HIERLABEL* label = getHierarchicalLabel( blockPair.first );
907
908 if( label )
909 label->SetText( netName );
910 }
911
912 // Load all bus entries and add net label if required
913 for( std::pair<NETELEMENT_ID, NET_SCH::BUS_TERM> busPair : net.BusTerminals )
914 {
915 NET_SCH::BUS_TERM busTerm = busPair.second;
916 BUS bus = Schematic.Buses.at( busTerm.BusID );
917
918 if( !alg::contains( m_busesMap.at( bus.ID )->Members(), netName ) )
919 m_busesMap.at( bus.ID )->Members().emplace_back( netName );
920
921 SCH_BUS_WIRE_ENTRY* busEntry =
922 new SCH_BUS_WIRE_ENTRY( getKiCadPoint( busTerm.FirstPoint ), false );
923
924 VECTOR2I size =
925 getKiCadPoint( busTerm.SecondPoint ) - getKiCadPoint( busTerm.FirstPoint );
926 busEntry->SetSize( wxSize( size.x, size.y ) );
927
928 m_sheetMap.at( bus.LayerID )->GetScreen()->Append( busEntry );
929
930 // Always add a label at bus terminals to ensure connectivity.
931 // If the original design does not have a label, just make it very small
932 // to keep connectivity but make the design look visually similar to
933 // the original.
934 SCH_LABEL* label = new SCH_LABEL();
935 label->SetText( netName );
936 label->SetPosition( getKiCadPoint( busTerm.SecondPoint ) );
937 label->SetVisible( true );
938
939 if( busTerm.HasNetLabel )
940 {
941 applyTextSettings( label,
942 busTerm.NetLabel.TextCodeID,
943 busTerm.NetLabel.Alignment,
944 busTerm.NetLabel.Justification );
945 }
946 else
947 {
948 label->SetTextSize( wxSize( SMALL_LABEL_SIZE, SMALL_LABEL_SIZE ) );
949 }
950
951 netlabels.insert( { busTerm.ID, label } );
952 m_sheetMap.at( bus.LayerID )->GetScreen()->Append( label );
953 }
954
955 for( std::pair<NETELEMENT_ID, NET_SCH::DANGLER> danglerPair : net.Danglers )
956 {
957 NET_SCH::DANGLER dangler = danglerPair.second;
958
959 SCH_LABEL* label = new SCH_LABEL();
960 label->SetPosition( getKiCadPoint( dangler.Position ) );
961 label->SetVisible( true );
962
963 if( dangler.HasNetLabel )
964 {
965 applyTextSettings( label,
966 dangler.NetLabel.TextCodeID,
967 dangler.NetLabel.Alignment,
968 dangler.NetLabel.Justification );
969 }
970
971 label->SetText( netName ); // set text after applying settings to avoid double-escaping
972 netlabels.insert( { dangler.ID, label } );
973
974 m_sheetMap.at( dangler.LayerID )->GetScreen()->Append( label );
975 }
976
977 for( NET_SCH::CONNECTION_SCH conn : net.Connections )
978 {
979 if( conn.LayerID == wxT( "NO_SHEET" ) )
980 continue; // No point loading virtual connections. KiCad handles that internally
981
982 POINT start = getLocationOfNetElement( net, conn.StartNode );
983 POINT end = getLocationOfNetElement( net, conn.EndNode );
984
985 if( start.x == UNDEFINED_VALUE || end.x == UNDEFINED_VALUE )
986 continue;
987
988 // Connections in CADSTAR are always implied between symbols even if the route
989 // doesn't start and end exactly at the connection points
990 if( conn.Path.size() < 1 || conn.Path.front() != start )
991 conn.Path.insert( conn.Path.begin(), start );
992
993 if( conn.Path.size() < 2 || conn.Path.back() != end )
994 conn.Path.push_back( end );
995
996 bool firstPt = true;
997 bool secondPt = false;
998 VECTOR2I last;
999 SCH_LINE* wire = nullptr;
1000
1001 SHAPE_LINE_CHAIN wireChain; // Create a temp. line chain representing the connection
1002
1003 for( POINT pt : conn.Path )
1004 {
1005 wireChain.Append( getKiCadPoint( pt ) );
1006 }
1007
1008 // AUTO-FIX SHEET PINS
1009 //--------------------
1010 // KiCad constrains the sheet pin on the edge of the sheet object whereas in
1011 // CADSTAR it can be anywhere. Let's find the intersection of the wires with the sheet
1012 // and place the hierarchical
1013 std::vector<NETELEMENT_ID> nodes;
1014 nodes.push_back( conn.StartNode );
1015 nodes.push_back( conn.EndNode );
1016
1017 for( NETELEMENT_ID node : nodes )
1018 {
1019 SCH_HIERLABEL* sheetPin = getHierarchicalLabel( node );
1020
1021 if( sheetPin )
1022 {
1023 if( sheetPin->Type() == SCH_SHEET_PIN_T
1024 && SCH_SHEET::ClassOf( sheetPin->GetParent() ) )
1025 {
1026 SCH_SHEET* parentSheet = static_cast<SCH_SHEET*>( sheetPin->GetParent() );
1027 wxSize sheetSize = parentSheet->GetSize();
1028 VECTOR2I sheetPosition = parentSheet->GetPosition();
1029
1030 int leftSide = sheetPosition.x;
1031 int rightSide = sheetPosition.x + sheetSize.x;
1032 int topSide = sheetPosition.y;
1033 int botSide = sheetPosition.y + sheetSize.y;
1034
1035 SHAPE_LINE_CHAIN sheetEdge;
1036
1037 sheetEdge.Append( leftSide, topSide );
1038 sheetEdge.Append( rightSide, topSide );
1039 sheetEdge.Append( rightSide, botSide );
1040 sheetEdge.Append( leftSide, botSide );
1041 sheetEdge.Append( leftSide, topSide );
1042
1043 SHAPE_LINE_CHAIN::INTERSECTIONS wireToSheetIntersects;
1044
1045 if( !wireChain.Intersect( sheetEdge, wireToSheetIntersects ) )
1046 {
1047 // The block terminal is outside the block shape in the original
1048 // CADSTAR design. Since KiCad's Sheet Pin will already be constrained
1049 // on the edge, we will simply join to it with a straight line.
1050 if( node == conn.StartNode )
1051 wireChain = wireChain.Reverse();
1052
1053 wireChain.Append( sheetPin->GetPosition() );
1054
1055 if( node == conn.StartNode )
1056 wireChain = wireChain.Reverse();
1057 }
1058 else
1059 {
1060 // The block terminal is either inside or on the shape edge. Lets use
1061 // the first intersection point.
1062 VECTOR2I intsctPt = wireToSheetIntersects.at( 0 ).p;
1063 int intsctIndx = wireChain.FindSegment( intsctPt );
1064 wxASSERT_MSG( intsctIndx != -1, "Can't find intersecting segment" );
1065
1066 if( node == conn.StartNode )
1067 wireChain.Replace( 0, intsctIndx, intsctPt );
1068 else
1069 wireChain.Replace( intsctIndx + 1, /*end index*/ -1, intsctPt );
1070
1071 sheetPin->SetPosition( intsctPt );
1072 }
1073 }
1074 }
1075 }
1076
1077 auto fixNetLabelsAndSheetPins =
1078 [&]( const EDA_ANGLE& aWireAngle, NETELEMENT_ID& aNetEleID )
1079 {
1080 TEXT_SPIN_STYLE spin = getSpinStyle( aWireAngle );
1081
1082 if( netlabels.find( aNetEleID ) != netlabels.end() )
1083 netlabels.at( aNetEleID )->SetTextSpinStyle( spin.MirrorY() );
1084
1085 SCH_HIERLABEL* sheetPin = getHierarchicalLabel( aNetEleID );
1086
1087 if( sheetPin )
1088 sheetPin->SetTextSpinStyle( spin.MirrorX() );
1089 };
1090
1091 // Now we can load the wires and fix the label orientations
1092 for( const VECTOR2I& pt : wireChain.CPoints() )
1093 {
1094 if( firstPt )
1095 {
1096 last = pt;
1097 firstPt = false;
1098 secondPt = true;
1099 continue;
1100 }
1101
1102 if( secondPt )
1103 {
1104 secondPt = false;
1105
1106 EDA_ANGLE wireAngle( last - pt );
1107 fixNetLabelsAndSheetPins( wireAngle, conn.StartNode );
1108 }
1109
1110 wire = new SCH_LINE();
1111
1112 wire->SetStartPoint( last );
1113 wire->SetEndPoint( pt );
1114 wire->SetLayer( LAYER_WIRE );
1115
1116 if( !conn.ConnectionLineCode.IsEmpty() )
1117 wire->SetLineWidth( getLineThickness( conn.ConnectionLineCode ) );
1118
1119 last = pt;
1120
1121 m_sheetMap.at( conn.LayerID )->GetScreen()->Append( wire );
1122 }
1123
1124 //Fix labels on the end wire
1125 if( wire )
1126 {
1127 EDA_ANGLE wireAngle( wire->GetEndPoint() - wire->GetStartPoint() );
1128 fixNetLabelsAndSheetPins( wireAngle, conn.EndNode );
1129 }
1130 }
1131
1132 for( std::pair<NETELEMENT_ID, NET_SCH::JUNCTION_SCH> juncPair : net.Junctions )
1133 {
1134 NET_SCH::JUNCTION_SCH junc = juncPair.second;
1135
1136 SCH_JUNCTION* kiJunc = new SCH_JUNCTION();
1137
1138 kiJunc->SetPosition( getKiCadPoint( junc.Location ) );
1139 m_sheetMap.at( junc.LayerID )->GetScreen()->Append( kiJunc );
1140
1141 if( junc.HasNetLabel )
1142 {
1143 // In CADSTAR the label can be placed anywhere, but in KiCad it has to be placed
1144 // in the same location as the junction for it to be connected to it.
1145 SCH_LABEL* label = new SCH_LABEL();
1146 label->SetText( netName );
1147 label->SetPosition( getKiCadPoint( junc.Location ) );
1148 label->SetVisible( true );
1149
1150 EDA_ANGLE labelAngle = getAngle( junc.NetLabel.OrientAngle );
1151 TEXT_SPIN_STYLE spin = getSpinStyle( labelAngle );
1152 label->SetTextSpinStyle( spin );
1153
1154 m_sheetMap.at( junc.LayerID )->GetScreen()->Append( label );
1155 }
1156 }
1157 }
1158}
1159
1160
1162{
1163 for( std::pair<FIGURE_ID, FIGURE> figPair : Schematic.Figures )
1164 {
1165 FIGURE fig = figPair.second;
1166
1167 loadFigure( fig, fig.LayerID, LAYER_NOTES );
1168 }
1169}
1170
1171
1173{
1174 for( std::pair<TEXT_ID, TEXT> textPair : Schematic.Texts )
1175 {
1176 TEXT txt = textPair.second;
1177
1178 SCH_TEXT* kiTxt = getKiCadSchText( txt );
1179 loadItemOntoKiCadSheet( txt.LayerID, kiTxt );
1180 }
1181}
1182
1183
1185{
1186 for( std::pair<DOCUMENTATION_SYMBOL_ID, DOCUMENTATION_SYMBOL> docSymPair :
1188 {
1189 DOCUMENTATION_SYMBOL docSym = docSymPair.second;
1190
1191 if( Library.SymbolDefinitions.find( docSym.SymdefID ) == Library.SymbolDefinitions.end() )
1192 {
1193 m_reporter->Report( wxString::Format( _( "Documentation Symbol '%s' refers to symbol "
1194 "definition ID '%s' which does not exist in "
1195 "the library. The symbol was not loaded." ),
1196 docSym.ID,
1197 docSym.SymdefID ),
1199 continue;
1200 }
1201
1202 SYMDEF_SCM docSymDef = Library.SymbolDefinitions.at( docSym.SymdefID );
1203 VECTOR2I moveVector = getKiCadPoint( docSym.Origin ) - getKiCadPoint( docSymDef.Origin );
1204 EDA_ANGLE rotationAngle = getAngle( docSym.OrientAngle );
1205 double scalingFactor = (double) docSym.ScaleRatioNumerator
1206 / (double) docSym.ScaleRatioDenominator;
1207 VECTOR2I centreOfTransform = getKiCadPoint( docSymDef.Origin );
1208 bool mirrorInvert = docSym.Mirror;
1209
1210 for( std::pair<FIGURE_ID, FIGURE> figPair : docSymDef.Figures )
1211 {
1212 FIGURE fig = figPair.second;
1213
1214 loadFigure( fig, docSym.LayerID, LAYER_NOTES, moveVector, rotationAngle, scalingFactor,
1215 centreOfTransform, mirrorInvert );
1216 }
1217
1218 for( std::pair<TEXT_ID, TEXT> textPair : docSymDef.Texts )
1219 {
1220 TEXT txt = textPair.second;
1221
1222 txt.Mirror = ( txt.Mirror ) ? !mirrorInvert : mirrorInvert;
1223 txt.OrientAngle = docSym.OrientAngle - txt.OrientAngle;
1224
1225 SCH_TEXT* kiTxt = getKiCadSchText( txt );
1226
1227 VECTOR2I newPosition = applyTransform( kiTxt->GetPosition(), moveVector, rotationAngle,
1228 scalingFactor, centreOfTransform, mirrorInvert );
1229
1230 int newTxtWidth = KiROUND( kiTxt->GetTextWidth() * scalingFactor );
1231 int newTxtHeight = KiROUND( kiTxt->GetTextHeight() * scalingFactor );
1232 int newTxtThickness = KiROUND( kiTxt->GetTextThickness() * scalingFactor );
1233
1234 kiTxt->SetPosition( newPosition );
1235 kiTxt->SetTextWidth( newTxtWidth );
1236 kiTxt->SetTextHeight( newTxtHeight );
1237 kiTxt->SetTextThickness( newTxtThickness );
1238
1239 loadItemOntoKiCadSheet( docSym.LayerID, kiTxt );
1240 }
1241 }
1242}
1243
1244
1246{
1247 auto findAndReplaceTextField =
1248 [&]( TEXT_FIELD_NAME aField, wxString aValue )
1249 {
1250 if( m_context.TextFieldToValuesMap.find( aField ) != m_context.TextFieldToValuesMap.end() )
1251 {
1252 if( m_context.TextFieldToValuesMap.at( aField ) != aValue )
1253 {
1254 m_context.TextFieldToValuesMap.at( aField ) = aValue;
1255 m_context.InconsistentTextFields.insert( aField );
1256 return false;
1257 }
1258 }
1259 else
1260 {
1261 m_context.TextFieldToValuesMap.insert( { aField, aValue } );
1262 }
1263
1264 return true;
1265 };
1266
1267 PROJECT* pj = &m_schematic->Prj();
1268
1269 if( pj )
1270 {
1271 std::map<wxString, wxString>& txtVars = pj->GetTextVars();
1272
1273 // Most of the design text fields can be derived from other elements
1274 if( Schematic.VariantHierarchy.Variants.size() > 0 )
1275 {
1276 VARIANT loadedVar = Schematic.VariantHierarchy.Variants.begin()->second;
1277
1278 findAndReplaceTextField( TEXT_FIELD_NAME::VARIANT_NAME, loadedVar.Name );
1279 findAndReplaceTextField( TEXT_FIELD_NAME::VARIANT_DESCRIPTION, loadedVar.Description );
1280 }
1281
1282 findAndReplaceTextField( TEXT_FIELD_NAME::DESIGN_TITLE, Header.JobTitle );
1283
1284 for( std::pair<TEXT_FIELD_NAME, wxString> txtvalue : m_context.TextFieldToValuesMap )
1285 {
1286 wxString varName = CADSTAR_TO_KICAD_FIELDS.at( txtvalue.first );
1287 wxString varValue = txtvalue.second;
1288
1289 txtVars.insert( { varName, varValue } );
1290 }
1291
1292 for( std::pair<wxString, wxString> txtvalue : m_context.FilenamesToTextMap )
1293 {
1294 wxString varName = txtvalue.first;
1295 wxString varValue = txtvalue.second;
1296
1297 txtVars.insert( { varName, varValue } );
1298 }
1299 }
1300 else
1301 {
1302 m_reporter->Report( _( "Text Variables could not be set as there is no project attached." ),
1304 }
1305}
1306
1307
1309 const PART* aCadstarPart, const GATE_ID& aGateID, LIB_SYMBOL* aSymbol )
1310{
1311 wxCHECK( Library.SymbolDefinitions.find( aSymdefID ) != Library.SymbolDefinitions.end(), );
1312
1313 SYMDEF_SCM symbol = Library.SymbolDefinitions.at( aSymdefID );
1314 int gateNumber = getKiCadUnitNumberFromGate( aGateID );
1315
1316 // Ensure there are no items on this unit (e.g. if we already previously loaded the symbol from
1317 // the part definition)
1318 std::vector<LIB_ITEM*> drawItems = aSymbol->GetUnitDrawItems( gateNumber, 0 );
1319
1320 for( LIB_ITEM* item : drawItems )
1321 aSymbol->RemoveDrawItem( item );
1322
1323 for( std::pair<FIGURE_ID, FIGURE> figPair : symbol.Figures )
1324 {
1325 FIGURE fig = figPair.second;
1326 int lineThickness = getLineThickness( fig.LineCodeID );
1327 PLOT_DASH_TYPE linestyle = getLineStyle( fig.LineCodeID );
1328
1329 if( fig.Shape.Type == SHAPE_TYPE::OPENSHAPE )
1330 {
1331 loadLibrarySymbolShapeVertices( fig.Shape.Vertices, symbol.Origin, aSymbol, gateNumber,
1332 lineThickness );
1333 }
1334 else
1335 {
1336 LIB_SHAPE* shape = new LIB_SHAPE( aSymbol, SHAPE_T::POLY );
1338 [&]( const VECTOR2I& aPt )
1339 {
1340 return getKiCadLibraryPoint( aPt, symbol.Origin );
1341 },
1342 ARC_ACCURACY ) );
1343
1344 shape->SetUnit( gateNumber );
1345
1346 shape->SetStroke( STROKE_PARAMS( lineThickness, linestyle ) );
1347
1348 if( fig.Shape.Type == SHAPE_TYPE::SOLID )
1350 else if( fig.Shape.Type == SHAPE_TYPE::OUTLINE )
1351 shape->SetFillMode( FILL_T::NO_FILL );
1352 else if( fig.Shape.Type == SHAPE_TYPE::HATCHED ) // We don't have an equivalent
1354
1355 aSymbol->AddDrawItem( shape );
1356 }
1357 }
1358
1359 TERMINAL_TO_PINNUM_MAP pinNumMap;
1360
1361 for( std::pair<TERMINAL_ID, TERMINAL> termPair : symbol.Terminals )
1362 {
1363 TERMINAL term = termPair.second;
1364 wxString pinNum = wxString::Format( "%ld", term.ID );
1365 wxString pinName = wxEmptyString;
1366 LIB_PIN* pin = new LIB_PIN( aSymbol );
1367
1368 if( aCadstarPart )
1369 {
1370 PART::DEFINITION::PIN csPin = getPartDefinitionPin( *aCadstarPart, aGateID, term.ID );
1371
1372 pinName = HandleTextOverbar( csPin.Label );
1373 pinNum = HandleTextOverbar( csPin.Name );
1374
1375 if( pinNum.IsEmpty() )
1376 {
1377 if( !csPin.Identifier.IsEmpty() )
1378 pinNum = csPin.Identifier;
1379 else if( csPin.ID == UNDEFINED_VALUE )
1380 pinNum = wxString::Format( "%ld", term.ID );
1381 else
1382 pinNum = wxString::Format( "%ld", csPin.ID );
1383 }
1384
1385 pin->SetType( getKiCadPinType( csPin.Type ) );
1386
1387 pinNumMap.insert( { term.ID, pinNum } );
1388 }
1389 else
1390 {
1391 // If no part is defined, we don't know the pin type. Assume passive pin
1393 }
1394
1395 pin->SetPosition( getKiCadLibraryPoint( term.Position, symbol.Origin ) );
1396 pin->SetLength( 0 ); //CADSTAR Pins are just a point (have no length)
1397 pin->SetShape( GRAPHIC_PINSHAPE::LINE );
1398 pin->SetUnit( gateNumber );
1399 pin->SetNumber( pinNum );
1400 pin->SetName( pinName );
1401
1402 int pinNumberHeight = getTextHeightFromTextCode( wxT( "TC0" ) ); // TC0 is the default CADSTAR text size for name/number
1403 int pinNameHeight = getTextHeightFromTextCode( wxT( "TC0" ) );
1404
1405 if( symbol.PinNumberLocations.count( term.ID ) )
1406 {
1407 PIN_NUM_LABEL_LOC pinNumLocation = symbol.PinNumberLocations.at( term.ID );
1408 pinNumberHeight = getTextHeightFromTextCode( pinNumLocation.TextCodeID );
1409 }
1410
1411 if( symbol.PinLabelLocations.count( term.ID ) )
1412 {
1413 PIN_NUM_LABEL_LOC pinNameLocation = symbol.PinLabelLocations.at( term.ID );
1414 pinNameHeight = getTextHeightFromTextCode( pinNameLocation.TextCodeID );
1415 }
1416
1417 pin->SetNumberTextSize( pinNumberHeight );
1418 pin->SetNameTextSize( pinNameHeight );
1419
1420 if( aSymbol->IsPower() )
1421 {
1422 pin->SetVisible( false );
1424 pin->SetName( aSymbol->GetName() );
1425 }
1426
1427 aSymbol->AddDrawItem( pin );
1428 }
1429
1430 fixUpLibraryPins( aSymbol, gateNumber );
1431
1432 if(aCadstarPart)
1433 m_pinNumsMap.insert( { aCadstarPart->ID + aGateID, pinNumMap } );
1434
1435 for( std::pair<TEXT_ID, TEXT> textPair : symbol.Texts )
1436 {
1437 TEXT csText = textPair.second;
1438
1439 LIB_TEXT* libtext = new LIB_TEXT( aSymbol );
1440 libtext->SetText( csText.Text );
1441 libtext->SetUnit( gateNumber );
1442 libtext->SetPosition( getKiCadLibraryPoint( csText.Position, symbol.Origin ) );
1443 libtext->SetMultilineAllowed( true ); // temporarily so that we calculate bbox correctly
1444
1445 applyTextSettings( libtext,
1446 csText.TextCodeID,
1447 csText.Alignment,
1448 csText.Justification,
1449 csText.OrientAngle,
1450 csText.Mirror );
1451
1452 // Split out multi line text items into individual text elements
1453 if( csText.Text.Contains( "\n" ) )
1454 {
1455 wxArrayString strings;
1456 wxStringSplit( csText.Text, strings, '\n' );
1457 wxPoint firstLinePos;
1458
1459 for( size_t ii = 0; ii < strings.size(); ++ii )
1460 {
1461 BOX2I bbox = libtext->GetTextBox( ii, true );
1462 VECTOR2I linePos = { bbox.GetLeft(), -bbox.GetBottom() };
1463
1464 RotatePoint( linePos, libtext->GetTextPos(), -libtext->GetTextAngle() );
1465
1466 LIB_TEXT* line = static_cast<LIB_TEXT*>( libtext->Clone() );
1467 line->SetText( strings[ii] );
1470 line->SetTextPos( linePos );
1471
1472 // Multiline text not allowed in LIB_TEXT
1473 line->SetMultilineAllowed( false );
1474 aSymbol->AddDrawItem( line );
1475 }
1476
1477 delete libtext;
1478 }
1479 else
1480 {
1481 // Multiline text not allowed in LIB_TEXT
1482 libtext->SetMultilineAllowed( false );
1483 aSymbol->AddDrawItem( libtext );
1484 }
1485 }
1486
1487 if( symbol.TextLocations.find( SYMBOL_NAME_ATTRID ) != symbol.TextLocations.end() )
1488 {
1489 TEXT_LOCATION textLoc = symbol.TextLocations.at( SYMBOL_NAME_ATTRID );
1490 LIB_FIELD* field = &aSymbol->GetReferenceField();
1491 applyToLibraryFieldAttribute( textLoc, symbol.Origin, field );
1492 field->SetUnit( gateNumber );
1493 }
1494
1495 // Hide the value field for now (it might get unhidden if an attribute exists in the cadstar
1496 // design with the text "Value"
1497 aSymbol->GetValueField().SetVisible( false );
1498
1499 if( symbol.TextLocations.find( PART_NAME_ATTRID ) != symbol.TextLocations.end() )
1500 {
1501 TEXT_LOCATION textLoc = symbol.TextLocations.at( PART_NAME_ATTRID );
1502 LIB_FIELD* field = aSymbol->FindField( PartNameFieldName );
1503
1504 if( !field )
1505 {
1506 int fieldID = aSymbol->GetFieldCount();
1507 field = new LIB_FIELD( aSymbol, fieldID );
1508 field->SetName( PartNameFieldName );
1509 aSymbol->AddField( field );
1510 }
1511
1512 wxASSERT( field->GetName() == PartNameFieldName );
1513 applyToLibraryFieldAttribute( textLoc, symbol.Origin, field );
1514
1515 if( aCadstarPart )
1516 {
1517 wxString partName = aCadstarPart->Name;
1518 partName.Replace( wxT( "\n" ), wxT( "\\n" ) );
1519 partName.Replace( wxT( "\r" ), wxT( "\\r" ) );
1520 partName.Replace( wxT( "\t" ), wxT( "\\t" ) );
1521 field->SetText( partName );
1522 }
1523
1524 field->SetUnit( gateNumber );
1526 }
1527
1528 if( aCadstarPart )
1529 {
1530 wxString footprintRefName = wxEmptyString;
1531 wxString footprintAlternateName = wxEmptyString;
1532
1533 auto loadLibraryField =
1534 [&]( ATTRIBUTE_VALUE& aAttributeVal )
1535 {
1536 wxString attrName = getAttributeName( aAttributeVal.AttributeID );
1537
1538 // Remove invalid field characters
1539 aAttributeVal.Value.Replace( wxT( "\n" ), wxT( "\\n" ) );
1540 aAttributeVal.Value.Replace( wxT( "\r" ), wxT( "\\r" ) );
1541 aAttributeVal.Value.Replace( wxT( "\t" ), wxT( "\\t" ) );
1542
1543 //TODO: Handle "links": In cadstar a field can be a "link" if its name starts
1544 // with the characters "Link ". Need to figure out how to convert them to
1545 // equivalent in KiCad.
1546
1547 if( attrName == wxT( "(PartDefinitionNameStem)" ) )
1548 {
1549 //Space not allowed in Reference field
1550 aAttributeVal.Value.Replace( wxT( " " ), "_" );
1551 aSymbol->GetReferenceField().SetText( aAttributeVal.Value );
1552 return;
1553 }
1554 else if( attrName == wxT( "(PartDescription)" ) )
1555 {
1556 aSymbol->SetDescription( aAttributeVal.Value );
1557 return;
1558 }
1559 else if( attrName == wxT( "(PartDefinitionReferenceName)" ) )
1560 {
1561 footprintRefName = aAttributeVal.Value;
1562 return;
1563 }
1564 else if( attrName == wxT( "(PartDefinitionAlternateName)" ) )
1565 {
1566 footprintAlternateName = aAttributeVal.Value;
1567 return;
1568 }
1569
1570 LIB_FIELD* attrField = aSymbol->FindField( attrName );
1571
1572 if( !attrField )
1573 {
1574 int fieldID = aSymbol->GetFieldCount();
1575 attrField = new LIB_FIELD( aSymbol, fieldID );
1576 attrField->SetName( attrName );
1577 aSymbol->AddField( attrField );
1578 }
1579
1580 wxASSERT( attrField->GetName() == attrName );
1581 attrField->SetText( aAttributeVal.Value );
1582 attrField->SetUnit( gateNumber );
1583
1584 ATTRIBUTE_ID& attrid = aAttributeVal.AttributeID;
1585 attrField->SetVisible( isAttributeVisible( attrid ) );
1586
1587 if( aAttributeVal.HasLocation )
1588 {
1589 // #1 Check if the part itself defined a location for the field
1590 applyToLibraryFieldAttribute( aAttributeVal.AttributeLocation, symbol.Origin,
1591 attrField );
1592 }
1593 else if( symbol.TextLocations.find( aAttributeVal.AttributeID )
1594 != symbol.TextLocations.end() )
1595 {
1596 // #2 Look in the symbol definition: Text locations
1597 TEXT_LOCATION symTxtLoc = symbol.TextLocations.at( aAttributeVal.AttributeID );
1598 applyToLibraryFieldAttribute( symTxtLoc, symbol.Origin, attrField );
1599 }
1600 else if( symbol.AttributeValues.find( attrid ) != symbol.AttributeValues.end()
1601 && symbol.AttributeValues.at( attrid ).HasLocation )
1602 {
1603 // #3 Look in the symbol definition: Attribute values
1604 ATTRIBUTE_VALUE symAttrVal = symbol.AttributeValues.at( attrid );
1606 attrField );
1607 }
1608 else
1609 {
1610 attrField->SetVisible( false );
1611 applyTextSettings( attrField, wxT( "TC1" ), ALIGNMENT::NO_ALIGNMENT,
1613 }
1614 };
1615
1616 // Load all attributes in the Part Definition
1617 for( std::pair<ATTRIBUTE_ID,
1618 ATTRIBUTE_VALUE> attr : aCadstarPart->Definition.AttributeValues )
1619 {
1620 ATTRIBUTE_VALUE attrVal = attr.second;
1621 loadLibraryField( attrVal );
1622 }
1623
1624 // Load all attributes in the Part itself.
1625 for( std::pair<ATTRIBUTE_ID, ATTRIBUTE_VALUE> attr : aCadstarPart->AttributeValues )
1626 {
1627 ATTRIBUTE_VALUE attrVal = attr.second;
1628 loadLibraryField( attrVal );
1629 }
1630
1631 wxString fpNameInLibrary = generateLibName( footprintRefName, footprintAlternateName );
1632
1633 if( !fpNameInLibrary.IsEmpty() )
1634 {
1635 wxArrayString fpFilters;
1636 fpFilters.Add( fpNameInLibrary );
1637 aSymbol->SetFPFilters( fpFilters );
1638
1639 // Assume that the PCB footprint library name will be the same as the schematic filename
1640 wxFileName schFilename( Filename );
1641 wxString libName = schFilename.GetName();
1642 aSymbol->GetFootprintField().SetText( libName + wxT( ":" ) + fpNameInLibrary );
1643 }
1644 }
1645
1646 if( aCadstarPart && aCadstarPart->Definition.HidePinNames )
1647 {
1648 aSymbol->SetShowPinNames( false );
1649 aSymbol->SetShowPinNumbers( false );
1650 }
1651}
1652
1653
1654void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
1655 wxPoint aSymbolOrigin,
1656 LIB_SYMBOL* aSymbol,
1657 int aGateNumber,
1658 int aLineThickness )
1659{
1660 const VERTEX* prev = &aCadstarVertices.at( 0 );
1661 const VERTEX* cur;
1662
1663 wxASSERT_MSG( prev->Type == VERTEX_TYPE::POINT, "First vertex should always be a point." );
1664
1665 for( size_t i = 1; i < aCadstarVertices.size(); i++ )
1666 {
1667 cur = &aCadstarVertices.at( i );
1668
1669 LIB_SHAPE* shape = nullptr;
1670 bool cw = false;
1671 VECTOR2I startPoint = getKiCadLibraryPoint( prev->End, aSymbolOrigin );
1672 VECTOR2I endPoint = getKiCadLibraryPoint( cur->End, aSymbolOrigin );
1673 VECTOR2I centerPoint;
1674
1677 {
1678 centerPoint = ( startPoint + endPoint ) / 2;
1679 }
1680 else
1681 {
1682 centerPoint = getKiCadLibraryPoint( cur->Center, aSymbolOrigin );
1683 }
1684
1685
1686 switch( cur->Type )
1687 {
1688 case VERTEX_TYPE::POINT:
1689 shape = new LIB_SHAPE( aSymbol, SHAPE_T::POLY );
1690 shape->AddPoint( startPoint );
1691 shape->AddPoint( endPoint );
1692 break;
1693
1696 cw = true;
1698
1701 shape = new LIB_SHAPE( aSymbol, SHAPE_T::ARC );
1702
1703 shape->SetPosition( centerPoint );
1704
1705 if( cw )
1706 {
1707 shape->SetStart( endPoint );
1708 shape->SetEnd( startPoint );
1709 }
1710 else
1711 {
1712 shape->SetStart( startPoint );
1713 shape->SetEnd( endPoint );
1714 }
1715
1716 break;
1717 }
1718
1719 shape->SetUnit( aGateNumber );
1720 shape->SetStroke( STROKE_PARAMS( aLineThickness, PLOT_DASH_TYPE::SOLID ) );
1721 aSymbol->AddDrawItem( shape );
1722
1723 prev = cur;
1724 }
1725}
1726
1727
1729 const ATTRIBUTE_LOCATION& aCadstarAttrLoc, wxPoint aSymbolOrigin, LIB_FIELD* aKiCadField )
1730{
1731 aKiCadField->SetTextPos( getKiCadLibraryPoint( aCadstarAttrLoc.Position, aSymbolOrigin ) );
1732
1733 applyTextSettings( aKiCadField,
1734 aCadstarAttrLoc.TextCodeID,
1735 aCadstarAttrLoc.Alignment,
1736 aCadstarAttrLoc.Justification,
1737 aCadstarAttrLoc.OrientAngle,
1738 aCadstarAttrLoc.Mirror );
1739}
1740
1741
1743 const LIB_SYMBOL& aKiCadPart,
1744 EDA_ANGLE& aComponentOrientation )
1745{
1746 LIB_ID libId( m_libraryFileName.GetName(), aKiCadPart.GetName() );
1747 int unit = getKiCadUnitNumberFromGate( aCadstarSymbol.GateID );
1748
1749 SCH_SHEET_PATH sheetpath;
1750 SCH_SHEET* kiSheet = m_sheetMap.at( aCadstarSymbol.LayerID );
1751 m_rootSheet->LocatePathOfScreen( kiSheet->GetScreen(), &sheetpath );
1752
1753 SCH_SYMBOL* symbol = new SCH_SYMBOL( aKiCadPart, libId, &sheetpath, unit );
1754
1755 if( aCadstarSymbol.IsComponent )
1756 {
1757 symbol->SetRef( &sheetpath, aCadstarSymbol.ComponentRef.Designator );
1758 }
1759
1760 symbol->SetPosition( getKiCadPoint( aCadstarSymbol.Origin ) );
1761
1762 EDA_ANGLE compAngle = getAngle( aCadstarSymbol.OrientAngle );
1763 int compOrientation = 0;
1764
1765 if( aCadstarSymbol.Mirror )
1766 {
1767 compAngle = -compAngle;
1768 compOrientation += SYMBOL_ORIENTATION_T::SYM_MIRROR_Y;
1769 }
1770
1771 compOrientation += getComponentOrientation( compAngle, aComponentOrientation );
1772 EDA_ANGLE test1( compAngle );
1773 EDA_ANGLE test2( aComponentOrientation );
1774
1775 if( test1.Normalize180() != test2.Normalize180() )
1776 {
1777 m_reporter->Report( wxString::Format( _( "Symbol '%s' is rotated by an angle of %.1f "
1778 "degrees in the original CADSTAR design but "
1779 "KiCad only supports rotation angles multiples "
1780 "of 90 degrees. The connecting wires will need "
1781 "manual fixing." ),
1782 aCadstarSymbol.ComponentRef.Designator,
1783 compAngle.AsDegrees() ),
1785 }
1786
1787 symbol->SetOrientation( compOrientation );
1788
1789 if( m_sheetMap.find( aCadstarSymbol.LayerID ) == m_sheetMap.end() )
1790 {
1791 m_reporter->Report( wxString::Format( _( "Symbol '%s' references sheet ID '%s' which does "
1792 "not exist in the design. The symbol was not "
1793 "loaded." ),
1794 aCadstarSymbol.ComponentRef.Designator,
1795 aCadstarSymbol.LayerID ),
1797
1798 delete symbol;
1799 return nullptr;
1800 }
1801
1802 wxString gate = ( aCadstarSymbol.GateID.IsEmpty() ) ? wxT( "A" ) : aCadstarSymbol.GateID;
1803 wxString partGateIndex = aCadstarSymbol.PartRef.RefID + gate;
1804
1805 //Handle pin swaps
1806 if( m_pinNumsMap.find( partGateIndex ) != m_pinNumsMap.end() )
1807 {
1808 TERMINAL_TO_PINNUM_MAP termNumMap = m_pinNumsMap.at( partGateIndex );
1809
1810 std::map<wxString, LIB_PIN*> pinNumToLibPinMap;
1811
1812 for( auto& term : termNumMap )
1813 {
1814 wxString pinNum = term.second;
1815 pinNumToLibPinMap.insert( { pinNum,
1816 symbol->GetLibSymbolRef()->GetPin( term.second ) } );
1817 }
1818
1819 auto replacePinNumber =
1820 [&]( wxString aOldPinNum, wxString aNewPinNum )
1821 {
1822 if( aOldPinNum == aNewPinNum )
1823 return;
1824
1825 LIB_PIN* libpin = pinNumToLibPinMap.at( aOldPinNum );
1826 libpin->SetNumber( HandleTextOverbar( aNewPinNum ) );
1827 };
1828
1829 //Older versions of Cadstar used pin numbers
1830 for( auto& pinPair : aCadstarSymbol.PinNumbers )
1831 {
1832 SYMBOL::PIN_NUM pin = pinPair.second;
1833
1834 replacePinNumber( termNumMap.at( pin.TerminalID ),
1835 wxString::Format( "%ld", pin.PinNum ) );
1836 }
1837
1838 //Newer versions of Cadstar use pin names
1839 for( auto& pinPair : aCadstarSymbol.PinNames )
1840 {
1841 SYMPINNAME_LABEL pin = pinPair.second;
1842 replacePinNumber( termNumMap.at( pin.TerminalID ), pin.NameOrLabel );
1843 }
1844
1845 symbol->UpdatePins();
1846 }
1847
1848 kiSheet->GetScreen()->Append( symbol );
1849
1850 return symbol;
1851}
1852
1853
1855 const EDA_ANGLE& aComponentOrientation,
1856 bool aIsMirrored,
1857 SCH_FIELD* aKiCadField )
1858{
1859 aKiCadField->SetPosition( getKiCadPoint( aCadstarAttrLoc.Position ) );
1860 aKiCadField->SetVisible( true );
1861
1862 ALIGNMENT alignment = aCadstarAttrLoc.Alignment;
1863 EDA_ANGLE textAngle = getAngle( aCadstarAttrLoc.OrientAngle );
1864
1865 if( aIsMirrored )
1866 {
1867 // We need to change the aligment when the symbol is mirrored based on the text orientation
1868 // To ensure the anchor point is the same in KiCad.
1869
1870 int textIsVertical = KiROUND( textAngle.AsDegrees() / 90.0 ) % 2;
1871
1872 if( textIsVertical )
1873 alignment = rotate180( alignment );
1874
1875 alignment = mirrorX( alignment );
1876 }
1877
1878 applyTextSettings( aKiCadField,
1879 aCadstarAttrLoc.TextCodeID,
1880 alignment,
1881 aCadstarAttrLoc.Justification,
1882 getCadstarAngle( textAngle - aComponentOrientation ),
1883 aCadstarAttrLoc.Mirror );
1884}
1885
1886
1888 EDA_ANGLE& aReturnedOrientation )
1889{
1890 int compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_0;
1891
1892 EDA_ANGLE oDeg = aOrientAngle;
1893 oDeg.Normalize180();
1894
1895 if( oDeg >= -ANGLE_45 && oDeg <= ANGLE_45 )
1896 {
1897 compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_0;
1898 aReturnedOrientation = ANGLE_0;
1899 }
1900 else if( oDeg >= ANGLE_45 && oDeg <= ANGLE_135 )
1901 {
1902 compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_90;
1903 aReturnedOrientation = ANGLE_90;
1904 }
1905 else if( oDeg >= ANGLE_135 || oDeg <= -ANGLE_135 )
1906 {
1907 compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_180;
1908 aReturnedOrientation = ANGLE_180;
1909 }
1910 else
1911 {
1912 compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_270;
1913 aReturnedOrientation = ANGLE_270;
1914 }
1915
1916 return compOrientation;
1917}
1918
1919
1922 const NETELEMENT_ID& aNetElementID )
1923{
1924 // clang-format off
1925 auto logUnknownNetElementError =
1926 [&]()
1927 {
1928 m_reporter->Report( wxString::Format( _( "Net %s references unknown net element %s. "
1929 "The net was not properly loaded and may "
1930 "require manual fixing." ),
1931 getNetName( aNet ),
1932 aNetElementID ),
1934
1935 return POINT();
1936 };
1937 // clang-format on
1938
1939 if( aNetElementID.Contains( "J" ) ) // Junction
1940 {
1941 if( aNet.Junctions.find( aNetElementID ) == aNet.Junctions.end() )
1942 return logUnknownNetElementError();
1943
1944 return aNet.Junctions.at( aNetElementID ).Location;
1945 }
1946 else if( aNetElementID.Contains( "P" ) ) // Terminal/Pin of a symbol
1947 {
1948 if( aNet.Terminals.find( aNetElementID ) == aNet.Terminals.end() )
1949 return logUnknownNetElementError();
1950
1951 SYMBOL_ID symid = aNet.Terminals.at( aNetElementID ).SymbolID;
1952 TERMINAL_ID termid = aNet.Terminals.at( aNetElementID ).TerminalID;
1953
1954 if( Schematic.Symbols.find( symid ) == Schematic.Symbols.end() )
1955 return logUnknownNetElementError();
1956
1957 SYMBOL sym = Schematic.Symbols.at( symid );
1958 SYMDEF_ID symdefid = sym.SymdefID;
1959 VECTOR2I symbolOrigin = sym.Origin;
1960
1961 if( Library.SymbolDefinitions.find( symdefid ) == Library.SymbolDefinitions.end() )
1962 return logUnknownNetElementError();
1963
1964 VECTOR2I libpinPosition =
1965 Library.SymbolDefinitions.at( symdefid ).Terminals.at( termid ).Position;
1966 VECTOR2I libOrigin = Library.SymbolDefinitions.at( symdefid ).Origin;
1967
1968 VECTOR2I pinOffset = libpinPosition - libOrigin;
1969 pinOffset.x = ( pinOffset.x * sym.ScaleRatioNumerator ) / sym.ScaleRatioDenominator;
1970 pinOffset.y = ( pinOffset.y * sym.ScaleRatioNumerator ) / sym.ScaleRatioDenominator;
1971
1972 VECTOR2I pinPosition = symbolOrigin + pinOffset;
1973 EDA_ANGLE compAngle = getAngle( sym.OrientAngle );
1974
1975 if( sym.Mirror )
1976 pinPosition.x = ( 2 * symbolOrigin.x ) - pinPosition.x;
1977
1978 EDA_ANGLE adjustedOrientation;
1979 getComponentOrientation( compAngle, adjustedOrientation );
1980
1981 RotatePoint( pinPosition, symbolOrigin, -adjustedOrientation );
1982
1983 POINT retval;
1984 retval.x = pinPosition.x;
1985 retval.y = pinPosition.y;
1986
1987 return retval;
1988 }
1989 else if( aNetElementID.Contains( "BT" ) ) // Bus Terminal
1990 {
1991 if( aNet.BusTerminals.find( aNetElementID ) == aNet.BusTerminals.end() )
1992 return logUnknownNetElementError();
1993
1994 return aNet.BusTerminals.at( aNetElementID ).SecondPoint;
1995 }
1996 else if( aNetElementID.Contains( "BLKT" ) ) // Block Terminal (sheet hierarchy connection)
1997 {
1998 if( aNet.BlockTerminals.find( aNetElementID ) == aNet.BlockTerminals.end() )
1999 return logUnknownNetElementError();
2000
2001 BLOCK_ID blockid = aNet.BlockTerminals.at( aNetElementID ).BlockID;
2002 TERMINAL_ID termid = aNet.BlockTerminals.at( aNetElementID ).TerminalID;
2003
2004 if( Schematic.Blocks.find( blockid ) == Schematic.Blocks.end() )
2005 return logUnknownNetElementError();
2006
2007 return Schematic.Blocks.at( blockid ).Terminals.at( termid ).Position;
2008 }
2009 else if( aNetElementID.Contains( "D" ) ) // Dangler
2010 {
2011 if( aNet.Danglers.find( aNetElementID ) == aNet.Danglers.end() )
2012 return logUnknownNetElementError();
2013
2014 return aNet.Danglers.at( aNetElementID ).Position;
2015 }
2016 else
2017 {
2018 return logUnknownNetElementError();
2019 }
2020
2021 return POINT();
2022}
2023
2024
2026{
2027 wxString netname = aNet.Name;
2028
2029 if( netname.IsEmpty() )
2030 netname = wxString::Format( "$%ld", aNet.SignalNum );
2031
2032 return netname;
2033}
2034
2035
2037 const VECTOR2I& aEndPoint,
2038 const LINECODE_ID& aCadstarLineCodeID,
2039 const LAYER_ID& aCadstarSheetID,
2040 const SCH_LAYER_ID& aKiCadSchLayerID,
2041 const VECTOR2I& aMoveVector,
2042 const EDA_ANGLE& aRotation,
2043 const double& aScalingFactor,
2044 const VECTOR2I& aTransformCentre,
2045 const bool& aMirrorInvert )
2046{
2047 SCH_LINE* segment = new SCH_LINE();
2048
2049 segment->SetLayer( aKiCadSchLayerID );
2050 segment->SetLineWidth( KiROUND( getLineThickness( aCadstarLineCodeID ) * aScalingFactor ) );
2051 segment->SetLineStyle( getLineStyle( aCadstarLineCodeID ) );
2052
2053 //Apply transforms
2054 VECTOR2I startPoint = applyTransform( aStartPoint, aMoveVector, aRotation, aScalingFactor,
2055 aTransformCentre, aMirrorInvert );
2056 VECTOR2I endPoint = applyTransform( aEndPoint, aMoveVector, aRotation, aScalingFactor,
2057 aTransformCentre, aMirrorInvert );
2058
2059 segment->SetStartPoint( startPoint );
2060 segment->SetEndPoint( endPoint );
2061
2062 loadItemOntoKiCadSheet( aCadstarSheetID, segment );
2063}
2064
2065
2066void CADSTAR_SCH_ARCHIVE_LOADER::loadShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
2067 LINECODE_ID aCadstarLineCodeID,
2068 LAYER_ID aCadstarSheetID,
2069 SCH_LAYER_ID aKiCadSchLayerID,
2070 const VECTOR2I& aMoveVector,
2071 const EDA_ANGLE& aRotation,
2072 const double& aScalingFactor,
2073 const VECTOR2I& aTransformCentre,
2074 const bool& aMirrorInvert )
2075{
2076 const VERTEX* prev = &aCadstarVertices.at( 0 );
2077 const VERTEX* cur;
2078
2079 wxASSERT_MSG( prev->Type == VERTEX_TYPE::POINT,
2080 "First vertex should always be a point vertex" );
2081
2082 for( size_t ii = 1; ii < aCadstarVertices.size(); ii++ )
2083 {
2084 cur = &aCadstarVertices.at( ii );
2085
2086 VECTOR2I startPoint = getKiCadPoint( prev->End );
2087 VECTOR2I endPoint = getKiCadPoint( cur->End );
2088 VECTOR2I centerPoint = getKiCadPoint( cur->Center );
2089 bool cw = false;
2090
2093 {
2094 centerPoint = ( startPoint + endPoint ) / 2;
2095 }
2096
2097 switch( cur->Type )
2098 {
2101 cw = true;
2105 {
2106 EDA_ANGLE arcStartAngle( startPoint - centerPoint );
2107 EDA_ANGLE arcEndAngle( endPoint - centerPoint );
2108 EDA_ANGLE arcAngle = arcEndAngle - arcStartAngle;
2109
2110 if( cw )
2111 arcAngle = arcAngle.Normalize();
2112 else
2113 arcAngle = -arcAngle.Normalize();
2114
2115 // TODO: Load as arc...
2116
2117 SHAPE_ARC tempArc( centerPoint, startPoint, arcAngle );
2118 SHAPE_LINE_CHAIN arcSegments = tempArc.ConvertToPolyline( ARC_ACCURACY );
2119
2120 // Load the arc as a series of piece-wise segments
2121
2122 for( int jj = 0; jj < arcSegments.SegmentCount(); jj++ )
2123 {
2124 VECTOR2I segStart = arcSegments.Segment( jj ).A;
2125 VECTOR2I segEnd = arcSegments.Segment( jj ).B;
2126
2127 loadGraphicStaightSegment( segStart, segEnd, aCadstarLineCodeID, aCadstarSheetID,
2128 aKiCadSchLayerID, aMoveVector, aRotation, aScalingFactor,
2129 aTransformCentre, aMirrorInvert );
2130 }
2131 }
2132 break;
2133
2134 case VERTEX_TYPE::POINT:
2135 loadGraphicStaightSegment( startPoint, endPoint, aCadstarLineCodeID, aCadstarSheetID,
2136 aKiCadSchLayerID, aMoveVector, aRotation, aScalingFactor,
2137 aTransformCentre, aMirrorInvert );
2138 break;
2139
2140 default:
2141 wxFAIL_MSG( "Unknown CADSTAR Vertex type" );
2142 }
2143
2144
2145 prev = cur;
2146 }
2147}
2148
2149
2151 const LAYER_ID& aCadstarSheetIDOverride,
2152 SCH_LAYER_ID aKiCadSchLayerID,
2153 const VECTOR2I& aMoveVector,
2154 const EDA_ANGLE& aRotation,
2155 const double& aScalingFactor,
2156 const VECTOR2I& aTransformCentre,
2157 const bool& aMirrorInvert )
2158{
2159 loadShapeVertices( aCadstarFigure.Shape.Vertices, aCadstarFigure.LineCodeID,
2160 aCadstarSheetIDOverride, aKiCadSchLayerID, aMoveVector, aRotation,
2161 aScalingFactor, aTransformCentre, aMirrorInvert );
2162
2163 for( CUTOUT cutout : aCadstarFigure.Shape.Cutouts )
2164 {
2165 loadShapeVertices( cutout.Vertices, aCadstarFigure.LineCodeID, aCadstarSheetIDOverride,
2166 aKiCadSchLayerID, aMoveVector, aRotation, aScalingFactor,
2167 aTransformCentre, aMirrorInvert );
2168 }
2169}
2170
2171
2173 const VECTOR2I& aPosition,
2174 VECTOR2I aSheetSize,
2175 const SCH_SHEET_PATH& aParentSheet )
2176{
2177 wxCHECK_MSG( m_sheetMap.find( aCadstarSheetID ) == m_sheetMap.end(), ,
2178 "Sheet already loaded!" );
2179
2180 SCH_SHEET* sheet = new SCH_SHEET(
2181 /* aParent */ aParentSheet.Last(),
2182 /* aPosition */ aPosition,
2183 /* aSize */ wxSize( aSheetSize ) );
2184 SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
2185 SCH_SHEET_PATH instance( aParentSheet );
2186
2187 sheet->SetScreen( screen );
2188
2189 wxString name = Sheets.SheetNames.at( aCadstarSheetID );
2190
2191 SCH_FIELD& sheetNameField = sheet->GetFields()[SHEETNAME];
2192 SCH_FIELD& filenameField = sheet->GetFields()[SHEETFILENAME];
2193
2194 sheetNameField.SetText( name );
2195
2196 int sheetNum = getSheetNumber( aCadstarSheetID );
2197 wxString loadedFilename = wxFileName( Filename ).GetName();
2198 std::string filename = wxString::Format( "%s_%02d", loadedFilename, sheetNum ).ToStdString();
2199
2200 ReplaceIllegalFileNameChars( &filename );
2201 filename += wxT( "." ) + KiCadSchematicFileExtension;
2202
2203 filenameField.SetText( filename );
2204
2205 wxFileName fn( m_schematic->Prj().GetProjectPath() + filename );
2206 sheet->GetScreen()->SetFileName( fn.GetFullPath() );
2207 aParentSheet.Last()->GetScreen()->Append( sheet );
2208 instance.push_back( sheet );
2209
2210 wxString pageNumStr = wxString::Format( "%d", getSheetNumber( aCadstarSheetID ) );
2211 instance.SetPageNumber( pageNumStr );
2212
2213 sheet->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
2214
2215 m_sheetMap.insert( { aCadstarSheetID, sheet } );
2216
2217 loadChildSheets( aCadstarSheetID, instance );
2218}
2219
2220
2222 const SCH_SHEET_PATH& aSheet )
2223{
2224 wxCHECK_MSG( m_sheetMap.find( aCadstarSheetID ) != m_sheetMap.end(), ,
2225 "FIXME! Parent sheet should be loaded before attempting to load subsheets" );
2226
2227 for( std::pair<BLOCK_ID, BLOCK> blockPair : Schematic.Blocks )
2228 {
2229 BLOCK& block = blockPair.second;
2230
2231 if( block.LayerID == aCadstarSheetID && block.Type == BLOCK::TYPE::CHILD )
2232 {
2233 if( block.AssocLayerID == wxT( "NO_LINK" ) )
2234 {
2235 if( block.Figures.size() > 0 )
2236 {
2237 m_reporter->Report( wxString::Format( _( "The block ID %s (Block name: '%s') "
2238 "is drawn on sheet '%s' but is not "
2239 "linked to another sheet in the "
2240 "design. KiCad requires all sheet "
2241 "symbols to be associated to a sheet, "
2242 "so the block was not loaded." ),
2243 block.ID, block.Name,
2244 Sheets.SheetNames.at( aCadstarSheetID ) ),
2246 }
2247
2248 continue;
2249 }
2250
2251 // In KiCad you can only draw rectangular shapes whereas in Cadstar arbitrary shapes
2252 // are allowed. We will calculate the extents of the Cadstar shape and draw a rectangle
2253
2254 std::pair<VECTOR2I, wxSize> blockExtents;
2255
2256 if( block.Figures.size() > 0 )
2257 {
2258 blockExtents = getFigureExtentsKiCad( block.Figures.begin()->second );
2259 }
2260 else
2261 {
2262 THROW_IO_ERROR( wxString::Format( _( "The CADSTAR schematic might be corrupt: "
2263 "Block %s references a child sheet but has no "
2264 "Figure defined." ),
2265 block.ID ) );
2266 }
2267
2268 loadSheetAndChildSheets( block.AssocLayerID, blockExtents.first, blockExtents.second,
2269 aSheet );
2270
2271 // Hide all KiCad sheet properties (sheet name/filename is not applicable in CADSTAR)
2272 SCH_SHEET* loadedSheet = m_sheetMap.at( block.AssocLayerID );
2273 SCH_FIELDS fields = loadedSheet->GetFields();
2274
2275 for( SCH_FIELD& field : fields )
2276 {
2277 field.SetVisible( false );
2278 }
2279
2280 if( block.HasBlockLabel )
2281 {
2282 //@todo use below code when KiCad supports multi-line fields
2283 /*
2284 // Add the block label as a separate field
2285 SCH_FIELD blockNameField( getKiCadPoint( block.BlockLabel.Position ), 2,
2286 loadedSheet, wxString( "Block name" ) );
2287 blockNameField.SetText( block.Name );
2288 blockNameField.SetVisible( true );
2289
2290 applyTextSettings( &blockNameField,
2291 block.BlockLabel.TextCodeID,
2292 block.BlockLabel.Alignment,
2293 block.BlockLabel.Justification,
2294 block.BlockLabel.OrientAngle,
2295 block.BlockLabel.Mirror );
2296
2297 fields.push_back( blockNameField );*/
2298
2299 // For now as as a text item (supports multi-line properly)
2300 SCH_TEXT* kiTxt = new SCH_TEXT();
2301
2302 kiTxt->SetParent( m_schematic );
2303 kiTxt->SetPosition( getKiCadPoint( block.BlockLabel.Position ) );
2304 kiTxt->SetText( block.Name );
2305
2306 applyTextSettings( kiTxt,
2307 block.BlockLabel.TextCodeID,
2308 block.BlockLabel.Alignment,
2310 block.BlockLabel.OrientAngle,
2311 block.BlockLabel.Mirror );
2312
2313 loadItemOntoKiCadSheet( aCadstarSheetID, kiTxt );
2314 }
2315
2316 loadedSheet->SetFields( fields );
2317 }
2318 }
2319}
2320
2321
2322std::vector<CADSTAR_SCH_ARCHIVE_LOADER::LAYER_ID> CADSTAR_SCH_ARCHIVE_LOADER::findOrphanSheets()
2323{
2324 std::vector<LAYER_ID> childSheets, orphanSheets;
2325
2326 //Find all sheets that are child of another
2327 for( std::pair<BLOCK_ID, BLOCK> blockPair : Schematic.Blocks )
2328 {
2329 BLOCK& block = blockPair.second;
2330 LAYER_ID& assocSheetID = block.AssocLayerID;
2331
2332 if( block.Type == BLOCK::TYPE::CHILD )
2333 childSheets.push_back( assocSheetID );
2334 }
2335
2336 //Add sheets that do not have a parent
2337 for( LAYER_ID sheetID : Sheets.SheetOrder )
2338 {
2339 if( std::find( childSheets.begin(), childSheets.end(), sheetID ) == childSheets.end() )
2340 orphanSheets.push_back( sheetID );
2341 }
2342
2343 return orphanSheets;
2344}
2345
2346
2348{
2349 int i = 1;
2350
2351 for( LAYER_ID sheetID : Sheets.SheetOrder )
2352 {
2353 if( sheetID == aCadstarSheetID )
2354 return i;
2355
2356 ++i;
2357 }
2358
2359 return -1;
2360}
2361
2362
2364{
2365 wxCHECK_MSG( aItem, /*void*/, "aItem is null" );
2366
2367 if( aCadstarSheetID == "ALL_SHEETS" )
2368 {
2369 SCH_ITEM* duplicateItem;
2370
2371 for( std::pair<LAYER_ID, SHEET_NAME> sheetPair : Sheets.SheetNames )
2372 {
2373 LAYER_ID sheetID = sheetPair.first;
2374 duplicateItem = aItem->Duplicate();
2375 m_sheetMap.at( sheetID )->GetScreen()->Append( aItem->Duplicate() );
2376 }
2377
2378 //Get rid of the extra copy:
2379 delete aItem;
2380 aItem = duplicateItem;
2381 }
2382 else if( aCadstarSheetID == "NO_SHEET" )
2383 {
2384 wxASSERT_MSG( false,
2385 "Trying to add an item to NO_SHEET? This might be a documentation symbol." );
2386 }
2387 else
2388 {
2389 if( m_sheetMap.find( aCadstarSheetID ) != m_sheetMap.end() )
2390 {
2391 m_sheetMap.at( aCadstarSheetID )->GetScreen()->Append( aItem );
2392 }
2393 else
2394 {
2395 delete aItem;
2396 wxASSERT_MSG( false, "Unknown Sheet ID." );
2397 }
2398 }
2399}
2400
2401
2404 const wxString& aSymDefAlternate )
2405{
2406 // Do a case-insensitive comparison
2407 for( std::pair<SYMDEF_ID, SYMDEF_SCM> symPair : Library.SymbolDefinitions )
2408 {
2409 SYMDEF_ID id = symPair.first;
2410 SYMDEF_SCM symdef = symPair.second;
2411
2412 if( symdef.ReferenceName.Lower() == aSymdefName.Lower()
2413 && symdef.Alternate.Lower() == aSymDefAlternate.Lower() )
2414 {
2415 return id;
2416 }
2417 }
2418
2419 return SYMDEF_ID();
2420}
2421
2422
2424{
2425 // Use CADSTAR visibility settings to determine if an attribute is visible
2426 if( AttrColors.AttributeColors.find( aCadstarAttributeID ) != AttrColors.AttributeColors.end() )
2427 {
2428 return AttrColors.AttributeColors.at( aCadstarAttributeID ).IsVisible;
2429 }
2430
2431 return false; // If there is no visibility setting, assume not displayed
2432}
2433
2434
2436{
2437 wxCHECK( Assignments.Codedefs.LineCodes.find( aCadstarLineCodeID )
2440
2441 return getKiCadLength( Assignments.Codedefs.LineCodes.at( aCadstarLineCodeID ).Width );
2442}
2443
2444
2446{
2447 wxCHECK( Assignments.Codedefs.LineCodes.find( aCadstarLineCodeID )
2450
2451 // clang-format off
2452 switch( Assignments.Codedefs.LineCodes.at( aCadstarLineCodeID ).Style )
2453 {
2456 case LINESTYLE::DASHDOTDOT: return PLOT_DASH_TYPE::DASHDOT; //TODO: update in future
2459 default: return PLOT_DASH_TYPE::DEFAULT;
2460 }
2461 // clang-format on
2462
2463 return PLOT_DASH_TYPE();
2464}
2465
2466
2469{
2470 wxCHECK( Assignments.Codedefs.TextCodes.find( aCadstarTextCodeID )
2472 TEXTCODE() );
2473
2474 return Assignments.Codedefs.TextCodes.at( aCadstarTextCodeID );
2475}
2476
2477
2479{
2480 TEXTCODE txtCode = getTextCode( aCadstarTextCodeID );
2481
2482 return KiROUND( (double) getKiCadLength( txtCode.Height ) * TXT_HEIGHT_RATIO );
2483}
2484
2485
2487{
2488 wxCHECK( Assignments.Codedefs.AttributeNames.find( aCadstarAttributeID )
2490 wxEmptyString );
2491
2492 return Assignments.Codedefs.AttributeNames.at( aCadstarAttributeID ).Name;
2493}
2494
2495
2498{
2499 wxCHECK( Parts.PartDefinitions.find( aCadstarPartID ) != Parts.PartDefinitions.end(), PART() );
2500
2501 return Parts.PartDefinitions.at( aCadstarPartID );
2502}
2503
2504
2507{
2508 wxCHECK( Assignments.Codedefs.RouteCodes.find( aCadstarRouteCodeID )
2510 ROUTECODE() );
2511
2512 return Assignments.Codedefs.RouteCodes.at( aCadstarRouteCodeID );
2513}
2514
2515
2516CADSTAR_SCH_ARCHIVE_LOADER::PART::DEFINITION::PIN
2518 const TERMINAL_ID& aTerminalID )
2519{
2520 for( std::pair<PART_DEFINITION_PIN_ID, PART::DEFINITION::PIN> pinPair :
2521 aCadstarPart.Definition.Pins )
2522 {
2523 PART::DEFINITION::PIN partPin = pinPair.second;
2524
2525 if( partPin.TerminalGate == aGateID && partPin.TerminalPin == aTerminalID )
2526 return partPin;
2527 }
2528
2529 return PART::DEFINITION::PIN();
2530}
2531
2532
2534{
2535 switch( aPinType )
2536 {
2537 case PART::PIN_TYPE::UNCOMMITTED: return ELECTRICAL_PINTYPE::PT_PASSIVE;
2538 case PART::PIN_TYPE::INPUT: return ELECTRICAL_PINTYPE::PT_INPUT;
2539 case PART::PIN_TYPE::OUTPUT_OR: return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
2540 case PART::PIN_TYPE::OUTPUT_NOT_OR: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2541 case PART::PIN_TYPE::OUTPUT_NOT_NORM_OR: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2542 case PART::PIN_TYPE::POWER: return ELECTRICAL_PINTYPE::PT_POWER_IN;
2543 case PART::PIN_TYPE::GROUND: return ELECTRICAL_PINTYPE::PT_POWER_IN;
2544 case PART::PIN_TYPE::TRISTATE_BIDIR: return ELECTRICAL_PINTYPE::PT_BIDI;
2545 case PART::PIN_TYPE::TRISTATE_INPUT: return ELECTRICAL_PINTYPE::PT_INPUT;
2546 case PART::PIN_TYPE::TRISTATE_DRIVER: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2547 }
2548
2550}
2551
2553{
2554 if( aCadstarGateID.IsEmpty() )
2555 return 1;
2556
2557 return (int) aCadstarGateID.Upper().GetChar( 0 ) - (int) wxUniChar( 'A' ) + 1;
2558}
2559
2560
2561TEXT_SPIN_STYLE CADSTAR_SCH_ARCHIVE_LOADER::getSpinStyle( const long long& aCadstarOrientation,
2562 bool aMirror )
2563{
2564 EDA_ANGLE orientation = getAngle( aCadstarOrientation );
2565 TEXT_SPIN_STYLE spinStyle = getSpinStyle( orientation );
2566
2567 if( aMirror )
2568 {
2569 spinStyle = spinStyle.RotateCCW();
2570 spinStyle = spinStyle.RotateCCW();
2571 }
2572
2573 return spinStyle;
2574}
2575
2576
2578{
2580
2581 EDA_ANGLE oDeg = aOrientation;
2582 oDeg.Normalize180();
2583
2584 if( oDeg >= -ANGLE_45 && oDeg <= ANGLE_45 )
2585 spinStyle = TEXT_SPIN_STYLE::RIGHT; // 0deg
2586 else if( oDeg >= ANGLE_45 && oDeg <= ANGLE_135 )
2587 spinStyle = TEXT_SPIN_STYLE::UP; // 90deg
2588 else if( oDeg >= ANGLE_135 || oDeg <= -ANGLE_135 )
2589 spinStyle = TEXT_SPIN_STYLE::LEFT; // 180deg
2590 else
2591 spinStyle = TEXT_SPIN_STYLE::BOTTOM; // 270deg
2592
2593 return spinStyle;
2594}
2595
2596
2599{
2600 switch( aCadstarAlignment )
2601 {
2602 // Change left to right:
2607
2608 //Change right to left:
2612
2613 // Center alignment does not mirror:
2616 case ALIGNMENT::TOPCENTER: return aCadstarAlignment;
2617
2618 // Shouldn't be here
2619 default: wxFAIL_MSG( "Unknown Cadstar Alignment" ); return aCadstarAlignment;
2620 }
2621}
2622
2623
2626{
2627 switch( aCadstarAlignment )
2628 {
2639
2640 // Shouldn't be here
2641 default: wxFAIL_MSG( "Unknown Cadstar Alignment" ); return aCadstarAlignment;
2642 }
2643}
2644
2645
2647 const TEXTCODE_ID& aCadstarTextCodeID,
2648 const ALIGNMENT& aCadstarAlignment,
2649 const JUSTIFICATION& aCadstarJustification,
2650 const long long aCadstarOrientAngle,
2651 bool aMirrored )
2652{
2653 // Justification ignored for now as not supported in Eeschema, but leaving this code in
2654 // place for future upgrades.
2655 // TODO update this when Eeschema supports justification independent of anchor position.
2656
2657 TEXTCODE textCode = getTextCode( aCadstarTextCodeID );
2658 int textHeight = KiROUND( (double) getKiCadLength( textCode.Height ) * TXT_HEIGHT_RATIO );
2659 int textWidth = getKiCadLength( textCode.Width );
2660
2661 // Ensure we have no Cadstar overbar characters
2662 wxString escapedText = HandleTextOverbar( aKiCadTextItem->GetText() );
2663 aKiCadTextItem->SetText( escapedText );
2664
2665 // The width is zero for all non-cadstar fonts. Using a width equal to 2/3 the height seems
2666 // to work well for most fonts.
2667 if( textWidth == 0 )
2668 textWidth = getKiCadLength( 2 * textCode.Height / 3 );
2669
2670 aKiCadTextItem->SetTextWidth( textWidth );
2671 aKiCadTextItem->SetTextHeight( textHeight );
2672 aKiCadTextItem->SetTextThickness( getKiCadLength( textCode.LineWidth ) );
2673 aKiCadTextItem->SetTextAngle( getAngle( aCadstarOrientAngle ) );
2674 aKiCadTextItem->SetBold( textCode.Font.Modifier1 == FONT_BOLD );
2675 aKiCadTextItem->SetItalic( textCode.Font.Italic );
2676
2677 ALIGNMENT textAlignment = aCadstarAlignment;
2678
2679 // KiCad mirrors the justification and alignment when the symbol is mirrored but CADSTAR
2680 // specifies it post-mirroring. In contrast, if the text item itself is mirrored (not
2681 // supported in KiCad), CADSTAR specifies the alignment and justification pre-mirroring
2682 if( aMirrored )
2683 textAlignment = mirrorX( aCadstarAlignment );
2684
2685 auto setAlignment =
2686 [&]( EDA_TEXT* aText, ALIGNMENT aAlignment )
2687 {
2688 switch( aAlignment )
2689 {
2690 case ALIGNMENT::NO_ALIGNMENT: // Bottom left of the first line
2691 //No exact KiCad equivalent, so lets move the position of the text
2697 break;
2698
2702 break;
2703
2707 break;
2708
2712 break;
2713
2717 break;
2718
2722 break;
2723
2724 case ALIGNMENT::TOPLEFT:
2727 break;
2728
2732 break;
2733
2737 break;
2738 }
2739 };
2740
2741 TEXT_SPIN_STYLE spin = getSpinStyle( aCadstarOrientAngle, aMirrored );
2742 EDA_ITEM* textEdaItem = dynamic_cast<EDA_ITEM*>( aKiCadTextItem );
2743 wxCHECK( textEdaItem, /* void */ ); // ensure this is a EDA_ITEM
2744
2745 switch( textEdaItem->Type() )
2746 {
2747 // Some KiCad schematic text items only permit a limited amount of angles
2748 // and text justifications
2749 case LIB_TEXT_T:
2750 case SCH_FIELD_T:
2751 case LIB_FIELD_T:
2752 {
2753 // Spin style not used. All text justifications are permitted. However, only orientations
2754 // of 0 deg or 90 deg are supported
2755 EDA_ANGLE angle = aKiCadTextItem->GetTextAngle();
2756 angle.Normalize();
2757
2758 int quadrant = KiROUND( angle.AsDegrees() / 90.0 );
2759 quadrant %= 4;
2760
2761 switch( quadrant )
2762 {
2763 case 0:
2765 break;
2766 case 1:
2768 break;
2769 case 2:
2771 textAlignment = rotate180( textAlignment );
2772 break;
2773 case 3:
2775 textAlignment = rotate180( textAlignment );
2776 break;
2777 default: wxFAIL_MSG( "Unknown Quadrant" );
2778 }
2779
2780 aKiCadTextItem->SetTextAngle( angle );
2781 setAlignment( aKiCadTextItem, textAlignment );
2782 return;
2783 }
2784
2785 case SCH_TEXT_T:
2786 {
2787 // Note spin style in a SCH_TEXT results in a vertical alignment GR_TEXT_V_ALIGN_BOTTOM
2788 // so need to adjust the location of the text element based on Cadstar's original text
2789 // alignment (anchor position).
2790 setAlignment( aKiCadTextItem, textAlignment );
2791 BOX2I bb = textEdaItem->GetBoundingBox();
2792 int off = static_cast<SCH_TEXT*>( aKiCadTextItem )->GetTextOffset();
2793 wxPoint pos;
2794
2795 // Change the anchor point of the text item to make it match the same bounding box
2796 // And correct the error introduced by the text offsetting in KiCad
2797 switch( spin )
2798 {
2799 case TEXT_SPIN_STYLE::BOTTOM: pos = { bb.GetRight() - off, bb.GetTop() }; break;
2800 case TEXT_SPIN_STYLE::UP: pos = { bb.GetRight() - off, bb.GetBottom() }; break;
2801 case TEXT_SPIN_STYLE::LEFT: pos = { bb.GetRight() , bb.GetBottom() + off }; break;
2802 case TEXT_SPIN_STYLE::RIGHT: pos = { bb.GetLeft() , bb.GetBottom() + off }; break;
2803 }
2804
2805 aKiCadTextItem->SetTextPos( pos );
2806 }
2808
2809 // We don't want to change position of net labels as that would break connectivity
2810 case SCH_LABEL_T:
2811 case SCH_GLOBAL_LABEL_T:
2812 case SCH_HIER_LABEL_T:
2813 case SCH_SHEET_PIN_T:
2814 static_cast<SCH_TEXT*>( aKiCadTextItem )->SetTextSpinStyle( spin );
2815 return;
2816
2817 default:
2818 wxFAIL_MSG( "Unexpected item type" );
2819 return;
2820 }
2821}
2822
2823
2825{
2826 SCH_TEXT* kiTxt = new SCH_TEXT();
2827
2828 kiTxt->SetParent( m_schematic ); // set to the schematic for now to avoid asserts
2829 kiTxt->SetPosition( getKiCadPoint( aCadstarTextElement.Position ) );
2830 kiTxt->SetText( aCadstarTextElement.Text );
2831
2832 applyTextSettings( kiTxt,
2833 aCadstarTextElement.TextCodeID,
2834 aCadstarTextElement.Alignment,
2835 aCadstarTextElement.Justification,
2836 aCadstarTextElement.OrientAngle,
2837 aCadstarTextElement.Mirror );
2838
2839 return kiTxt;
2840}
2841
2842
2844 long long aScalingFactorNumerator,
2845 long long aScalingFactorDenominator )
2846{
2847 LIB_SYMBOL* retval = new LIB_SYMBOL( *aSymbol );
2848
2849 if( aScalingFactorNumerator == aScalingFactorDenominator )
2850 return retval; // 1:1 scale, nothing to do
2851
2852 auto scaleLen =
2853 [&]( int aLength ) -> int
2854 {
2855 return( aLength * aScalingFactorNumerator ) / aScalingFactorDenominator;
2856 };
2857
2858 auto scalePt =
2859 [&]( VECTOR2I aCoord ) -> VECTOR2I
2860 {
2861 return VECTOR2I( scaleLen( aCoord.x ), scaleLen( aCoord.y ) );
2862 };
2863
2864 auto scaleSize =
2865 [&]( VECTOR2I aSize ) -> VECTOR2I
2866 {
2867 return VECTOR2I( scaleLen( aSize.x ), scaleLen( aSize.y ) );
2868 };
2869
2870 LIB_ITEMS_CONTAINER& items = retval->GetDrawItems();
2871
2872 for( LIB_ITEM& item : items )
2873 {
2874 switch( item.Type() )
2875 {
2877 {
2878 LIB_SHAPE& shape = static_cast<LIB_SHAPE&>( item );
2879
2880 if( shape.GetShape() == SHAPE_T::ARC )
2881 {
2882 shape.SetPosition( scalePt( shape.GetPosition() ) );
2883 shape.SetStart( scalePt( shape.GetStart() ) );
2884 shape.SetEnd( scalePt( shape.GetEnd() ) );
2885 }
2886 else if( shape.GetShape() == SHAPE_T::POLY )
2887 {
2888 SHAPE_LINE_CHAIN& poly = shape.GetPolyShape().Outline( 0 );
2889
2890 for( size_t ii = 0; ii < poly.GetPointCount(); ++ii )
2891 poly.SetPoint( ii, scalePt( poly.CPoint( ii ) ) );
2892 }
2893 break;
2894 }
2895
2896 case KICAD_T::LIB_PIN_T:
2897 {
2898 LIB_PIN& pin = static_cast<LIB_PIN&>( item );
2899
2900 pin.SetPosition( scalePt( pin.GetPosition() ) );
2901 pin.SetLength( scaleLen( pin.GetLength() ) );
2902 break;
2903 }
2904
2906 {
2907 LIB_TEXT& txt = static_cast<LIB_TEXT&>( item );
2908
2909 txt.SetPosition( scalePt( txt.GetPosition() ) );
2910 txt.SetTextSize( scaleSize( txt.GetTextSize() ) );
2911 break;
2912 }
2913
2914 default:
2915 break;
2916 }
2917
2918 }
2919
2920 return retval;
2921}
2922
2923
2924void CADSTAR_SCH_ARCHIVE_LOADER::fixUpLibraryPins( LIB_SYMBOL* aSymbolToFix, int aGateNumber )
2925{
2926 auto compLambda = []( const VECTOR2I& aA, const VECTOR2I& aB )
2927 {
2928 return LexicographicalCompare( aA, aB ) < 0;
2929 };
2930
2931 // Store a list of vertical or horizontal segments in the symbol
2932 // Note: Need the custom comparison function to ensure the map is sorted correctly
2933 std::map<VECTOR2I, SHAPE_LINE_CHAIN, decltype( compLambda )> uniqueSegments( compLambda );
2934
2935 LIB_ITEMS_CONTAINER::ITERATOR shapeIt = aSymbolToFix->GetDrawItems().begin( LIB_SHAPE_T );
2936
2937 for( ; shapeIt != aSymbolToFix->GetDrawItems().end( LIB_SHAPE_T ); ++shapeIt )
2938 {
2939 LIB_SHAPE& shape = static_cast<LIB_SHAPE&>( *shapeIt );
2940
2941 if( aGateNumber > 0 && shape.GetUnit() != aGateNumber )
2942 continue;
2943
2944 if( shape.GetShape() != SHAPE_T::POLY )
2945 continue;
2946
2947 SHAPE_LINE_CHAIN poly = shape.GetPolyShape().Outline( 0 );
2948
2949 if( poly.GetPointCount() == 2 )
2950 {
2951 VECTOR2I pt0 = poly.CPoint( 0 );
2952 VECTOR2I pt1 = poly.CPoint( 1 );
2953
2954 if( pt0 != pt1 && uniqueSegments.count( pt0 ) == 0 && uniqueSegments.count( pt1 ) == 0 )
2955 {
2956 // we are only interested in vertical or horizontal segments
2957 if( pt0.x == pt1.x || pt0.y == pt1.y )
2958 {
2959 uniqueSegments.insert( { pt0, poly } );
2960 uniqueSegments.insert( { pt1, poly } );
2961 }
2962 }
2963 }
2964 }
2965
2966 LIB_PINS pins;
2967 aSymbolToFix->GetPins( pins, aGateNumber );
2968
2969 for( auto& pin : pins )
2970 {
2971 auto setPinOrientation =
2972 [&]( const EDA_ANGLE& aAngle )
2973 {
2974 EDA_ANGLE angle( aAngle );
2975 angle.Normalize180();
2976
2977 if( angle >= -ANGLE_45 && angle <= ANGLE_45 )
2978 pin->SetOrientation( 'R' ); // 0 degrees
2979 else if( angle >= ANGLE_45 && angle <= ANGLE_135 )
2980 pin->SetOrientation( 'U' ); // 90 degrees
2981 else if( angle >= ANGLE_135 || angle <= -ANGLE_135 )
2982 pin->SetOrientation( 'L' ); // 180 degrees
2983 else
2984 pin->SetOrientation( 'D' ); // -90 degrees
2985 };
2986
2987 if( uniqueSegments.count( pin->GetPosition() ) )
2988 {
2989 SHAPE_LINE_CHAIN& poly = uniqueSegments.at( pin->GetPosition() );
2990
2991 VECTOR2I otherPt = poly.CPoint( 0 );
2992
2993 if( otherPt == pin->GetPosition() )
2994 otherPt = poly.CPoint( 1 );
2995
2996 VECTOR2I vec( otherPt - pin->GetPosition() );
2997
2998 pin->SetLength( vec.EuclideanNorm() );
2999 setPinOrientation( EDA_ANGLE( vec ) );
3000 }
3001 }
3002}
3003
3004
3005std::pair<VECTOR2I, wxSize>
3007{
3008 VECTOR2I upperLeft( Assignments.Settings.DesignLimit.x, 0 );
3009 VECTOR2I lowerRight( 0, Assignments.Settings.DesignLimit.y );
3010
3011 for( const VERTEX& v : aCadstarFigure.Shape.Vertices )
3012 {
3013 if( upperLeft.x > v.End.x )
3014 upperLeft.x = v.End.x;
3015
3016 if( upperLeft.y < v.End.y )
3017 upperLeft.y = v.End.y;
3018
3019 if( lowerRight.x < v.End.x )
3020 lowerRight.x = v.End.x;
3021
3022 if( lowerRight.y > v.End.y )
3023 lowerRight.y = v.End.y;
3024 }
3025
3026 for( CUTOUT cutout : aCadstarFigure.Shape.Cutouts )
3027 {
3028 for( const VERTEX& v : aCadstarFigure.Shape.Vertices )
3029 {
3030 if( upperLeft.x > v.End.x )
3031 upperLeft.x = v.End.x;
3032
3033 if( upperLeft.y < v.End.y )
3034 upperLeft.y = v.End.y;
3035
3036 if( lowerRight.x < v.End.x )
3037 lowerRight.x = v.End.x;
3038
3039 if( lowerRight.y > v.End.y )
3040 lowerRight.y = v.End.y;
3041 }
3042 }
3043
3044 VECTOR2I upperLeftKiCad = getKiCadPoint( upperLeft );
3045 VECTOR2I lowerRightKiCad = getKiCadPoint( lowerRight );
3046
3047 VECTOR2I size = lowerRightKiCad - upperLeftKiCad;
3048
3049 return { upperLeftKiCad, wxSize( abs( size.x ), abs( size.y ) ) };
3050}
3051
3052
3054{
3055 VECTOR2I retval;
3056
3057 retval.x = getKiCadLength( aCadstarPoint.x - m_designCenter.x );
3058 retval.y = -getKiCadLength( aCadstarPoint.y - m_designCenter.y );
3059
3060 return retval;
3061}
3062
3063
3065 const VECTOR2I& aCadstarCentre )
3066{
3067 VECTOR2I retval;
3068
3069 retval.x = getKiCadLength( aCadstarPoint.x - aCadstarCentre.x );
3070 retval.y = getKiCadLength( aCadstarPoint.y - aCadstarCentre.y );
3071
3072 return retval;
3073}
3074
3075
3077 const VECTOR2I& aMoveVector,
3078 const EDA_ANGLE& aRotation,
3079 const double& aScalingFactor,
3080 const VECTOR2I& aTransformCentre,
3081 const bool& aMirrorInvert )
3082{
3083 VECTOR2I retVal = aPoint;
3084
3085 if( aScalingFactor != 1.0 )
3086 {
3087 //scale point
3088 retVal -= aTransformCentre;
3089 retVal.x = KiROUND( retVal.x * aScalingFactor );
3090 retVal.y = KiROUND( retVal.y * aScalingFactor );
3091 retVal += aTransformCentre;
3092 }
3093
3094 if( aMirrorInvert )
3095 MIRROR( retVal.x, aTransformCentre.x );
3096
3097 if( !aRotation.IsZero() )
3098 RotatePoint( retVal, aTransformCentre, aRotation );
3099
3100 if( aMoveVector != wxPoint{ 0, 0 } )
3101 retVal += aMoveVector;
3102
3103 return retVal;
3104}
3105
3106
3108{
3109 return sqrt( ( (double) aPoint.x * (double) aPoint.x )
3110 + ( (double) aPoint.y * (double) aPoint.y ) );
3111}
const char * name
Definition: DXF_plotter.cpp:56
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
constexpr double SCH_IU_PER_MM
Definition: base_units.h:73
#define SYMBOL_NAME_ATTRID
Symbol Name attribute ID - used for placement of designators on the schematic.
#define SIGNALNAME_ORIGIN_ATTRID
#define LINK_ORIGIN_ATTRID
#define PART_NAME_ATTRID
const wxString PartNameFieldName
Loads a csa file into a KiCad SCHEMATIC object.
coord_type GetTop() const
Definition: box2.h:194
Vec Centre() const
Definition: box2.h:70
coord_type GetRight() const
Definition: box2.h:189
coord_type GetLeft() const
Definition: box2.h:193
const Vec & GetSize() const
Definition: box2.h:179
coord_type GetBottom() const
Definition: box2.h:190
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:588
static wxString generateLibName(const wxString &aRefName, const wxString &aAlternateName)
@ FRACTIONALGRID
Param1 = Units, Param2 = Divisor.
static const std::map< TEXT_FIELD_NAME, wxString > CADSTAR_TO_KICAD_FIELDS
Map between CADSTAR fields and KiCad text variables.
long TERMINAL_ID
Terminal is the pin identifier in the schematic.
TEXT_FIELD_NAME
These are special fields in text objects enclosed between the tokens '<@' and '>' such as <@[FIELD_NA...
ALIGNMENT
From CADSTAR Help: "Text Alignment enables you to define the position of an alignment origin for all ...
@ NO_ALIGNMENT
NO_ALIGNMENT has different meaning depending on the object type.
static const long UNDEFINED_VALUE
wxString LAYER_ID
ID of a Sheet (if schematic) or board Layer (if PCB)
static void FixTextPositionNoAlignment(EDA_TEXT *aKiCadTextItem)
Corrects the position of a text element that had NO_ALIGNMENT in CADSTAR.
@ OUTLINE
Unfilled closed shape.
@ OPENSHAPE
Unfilled open shape. Cannot have cutouts.
@ SOLID
Filled closed shape (solid fill).
@ HATCHED
Filled closed shape (hatch fill).
static const double TXT_HEIGHT_RATIO
CADSTAR fonts are drawn on a 24x24 integer matrix, where the each axis goes from 0 to 24.
void checkPoint()
Updates m_progressReporter or throws if user cancelled.
static wxString HandleTextOverbar(wxString aCadstarString)
Convert a string with CADSTAR overbar characters to equivalent in KiCad.
JUSTIFICATION
From CADSTAR Help: "Multi Line Text can also be justified as Left, Centre or Right.
PROGRESS_REPORTER * m_progressReporter
ELECTRICAL_PINTYPE getKiCadPinType(const PART::PIN_TYPE &aPinType)
ROUTECODE getRouteCode(const ROUTECODE_ID &aCadstarRouteCodeID)
void applyToLibraryFieldAttribute(const ATTRIBUTE_LOCATION &aCadstarAttrLoc, wxPoint aSymbolOrigin, LIB_FIELD *aKiCadField)
std::pair< VECTOR2I, wxSize > getFigureExtentsKiCad(const FIGURE &aCadstarFigure)
std::map< BLOCK_PIN_ID, SCH_HIERLABEL * > m_sheetPinMap
Map between Cadstar and KiCad Sheets Pins.
VECTOR2I applyTransform(const VECTOR2I &aPoint, const VECTOR2I &aMoveVector={ 0, 0 }, const EDA_ANGLE &aRotation=ANGLE_0, const double &aScalingFactor=1.0, const VECTOR2I &aTransformCentre={ 0, 0 }, const bool &aMirrorInvert=false)
std::map< SYMBOL_ID, SCH_GLOBALLABEL * > m_globalLabelsMap
Map between Cadstar and KiCad Global Labels.
SCH_SYMBOL * loadSchematicSymbol(const SYMBOL &aCadstarSymbol, const LIB_SYMBOL &aKiCadPart, EDA_ANGLE &aComponentOrientation)
SCH_PLUGIN::SCH_PLUGIN_RELEASER * m_plugin
void applyTextSettings(EDA_TEXT *aKiCadTextItem, const TEXTCODE_ID &aCadstarTextCodeID, const ALIGNMENT &aCadstarAlignment, const JUSTIFICATION &aCadstarJustification, const long long aCadstarOrientAngle=0, bool aMirrored=false)
wxString getAttributeName(const ATTRIBUTE_ID &aCadstarAttributeID)
PART getPart(const PART_ID &aCadstarPartID)
std::vector< LAYER_ID > findOrphanSheets()
std::map< BUS_ID, std::shared_ptr< BUS_ALIAS > > m_busesMap
Map of Cadstar and KiCad Buses.
int getSheetNumber(LAYER_ID aCadstarSheetID)
SCH_TEXT * getKiCadSchText(const TEXT &aCadstarTextElement)
std::map< TERMINAL_ID, wxString > TERMINAL_TO_PINNUM_MAP
Map between a terminal ID in a symbol definition to the pin number that should be imported into KiCad...
wxString getNetName(const NET_SCH &aNet)
std::pair< BLOCK_ID, TERMINAL_ID > BLOCK_PIN_ID
std::map< SYMBOL_ID, SCH_SYMBOL * > m_powerSymMap
Map between Cadstar and KiCad Power Symbols.
std::pair< PART_ID, GATE_ID > PART_GATE_ID
VECTOR2I getKiCadLibraryPoint(const VECTOR2I &aCadstarPoint, const VECTOR2I &aCadstarCentre)
PART::DEFINITION::PIN getPartDefinitionPin(const PART &aCadstarPart, const GATE_ID &aGateID, const TERMINAL_ID &aTerminalID)
void Load(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, SCH_PLUGIN::SCH_PLUGIN_RELEASER *aSchPlugin, const wxFileName &aLibraryFileName)
Loads a CADSTAR PCB Archive file into the KiCad BOARD object given.
int getTextHeightFromTextCode(const TEXTCODE_ID &aCadstarTextCodeID)
TEXT_SPIN_STYLE getSpinStyle(const long long &aCadstarOrientation, bool aMirror)
double getPolarRadius(const VECTOR2I &aPoint)
int getLineThickness(const LINECODE_ID &aCadstarLineCodeID)
TEXTCODE getTextCode(const TEXTCODE_ID &aCadstarTextCodeID)
std::map< wxString, LIB_SYMBOL * > m_powerSymLibMap
Map of KiCad Power Symbol Library items.
PLOT_DASH_TYPE getLineStyle(const LINECODE_ID &aCadstarLineCodeID)
std::map< PART_ID, TERMINAL_TO_PINNUM_MAP > m_pinNumsMap
Map of pin numbers in CADSTAR parts.
void loadSymDefIntoLibrary(const SYMDEF_ID &aSymdefID, const PART *aCadstarPart, const GATE_ID &aGateID, LIB_SYMBOL *aSymbol)
void loadSheetAndChildSheets(LAYER_ID aCadstarSheetID, const VECTOR2I &aPosition, VECTOR2I aSheetSize, const SCH_SHEET_PATH &aParentSheet)
void loadItemOntoKiCadSheet(LAYER_ID aCadstarSheetID, SCH_ITEM *aItem)
int getKiCadLength(long long aCadstarLength)
std::map< PART_ID, LIB_SYMBOL * > m_partMap
Map between Cadstar and KiCad Parts.
void loadGraphicStaightSegment(const VECTOR2I &aStartPoint, const VECTOR2I &aEndPoint, const LINECODE_ID &aCadstarLineCodeID, const LAYER_ID &aCadstarSheetID, const SCH_LAYER_ID &aKiCadSchLayerID, const VECTOR2I &aMoveVector={ 0, 0 }, const EDA_ANGLE &aRotation=ANGLE_0, const double &aScalingFactor=1.0, const VECTOR2I &aTransformCentre={ 0, 0 }, const bool &aMirrorInvert=false)
bool isAttributeVisible(const ATTRIBUTE_ID &aCadstarAttributeID)
VECTOR2I getKiCadPoint(const VECTOR2I &aCadstarPoint)
EDA_ANGLE getAngle(const long long &aCadstarAngle)
void loadFigure(const FIGURE &aCadstarFigure, const LAYER_ID &aCadstarSheetIDOverride, SCH_LAYER_ID aKiCadSchLayerID, const VECTOR2I &aMoveVector={ 0, 0 }, const EDA_ANGLE &aRotation=ANGLE_0, const double &aScalingFactor=1.0, const VECTOR2I &aTransformCentre={ 0, 0 }, const bool &aMirrorInvert=false)
void loadLibrarySymbolShapeVertices(const std::vector< VERTEX > &aCadstarVertices, wxPoint aSymbolOrigin, LIB_SYMBOL *aSymbol, int aGateNumber, int aLineThickness)
std::map< PART_GATE_ID, SYMDEF_ID > m_partSymbolsMap
Map holding the symbols loaded so far for a particular PART_ID and GATE_ID.
wxPoint m_designCenter
Used for calculating the required offset to apply to the Cadstar design so that it fits in KiCad canv...
LIB_SYMBOL * getScaledLibPart(const LIB_SYMBOL *aSymbol, long long aScalingFactorNumerator, long long aScalingFactorDenominator)
SYMDEF_ID getSymDefFromName(const wxString &aSymdefName, const wxString &aSymDefAlternate)
std::map< LAYER_ID, SCH_SHEET * > m_sheetMap
Map between Cadstar and KiCad Sheets.
POINT getLocationOfNetElement(const NET_SCH &aNet, const NETELEMENT_ID &aNetElementID)
void fixUpLibraryPins(LIB_SYMBOL *aSymbolToFix, int aGateNumber)
ALIGNMENT rotate180(const ALIGNMENT &aCadstarAlignment)
long long getCadstarAngle(const EDA_ANGLE &aAngle)
void loadChildSheets(LAYER_ID aCadstarSheetID, const SCH_SHEET_PATH &aSheet)
ALIGNMENT mirrorX(const ALIGNMENT &aCadstarAlignment)
int getComponentOrientation(const EDA_ANGLE &aOrientAngle, EDA_ANGLE &aReturnedOrientation)
void loadShapeVertices(const std::vector< VERTEX > &aCadstarVertices, LINECODE_ID aCadstarLineCodeID, LAYER_ID aCadstarSheetID, SCH_LAYER_ID aKiCadSchLayerID, const VECTOR2I &aMoveVector={ 0, 0 }, const EDA_ANGLE &aRotation=ANGLE_0, const double &aScalingFactor=1.0, const VECTOR2I &aTransformCentre={ 0, 0 }, const bool &aMirrorInvert=false)
int getKiCadUnitNumberFromGate(const GATE_ID &aCadstarGateID)
void loadSymbolFieldAttribute(const ATTRIBUTE_LOCATION &aCadstarAttrLoc, const EDA_ANGLE &aComponentOrientation, bool aIsMirrored, SCH_FIELD *aKiCadField)
int KiCadUnitDivider
Use this value to convert units in this CSA file to KiCad units.
EDA_ANGLE Normalize()
Definition: eda_angle.h:249
double AsDegrees() const
Definition: eda_angle.h:149
bool IsZero() const
Definition: eda_angle.h:169
EDA_ANGLE Normalize180()
Definition: eda_angle.h:271
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
EDA_ITEM * GetParent() const
Definition: eda_item.h:99
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:247
SHAPE_T GetShape() const
Definition: eda_shape.h:113
void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition: eda_shape.h:255
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:145
void SetStart(const VECTOR2I &aStart)
Definition: eda_shape.h:124
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:120
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:149
void SetFillMode(FILL_T aFill)
Definition: eda_shape.h:100
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:72
int GetTextHeight() const
Definition: eda_text.h:202
BOX2I GetTextBox(int aLine=-1, bool aInvertY=false) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:503
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:208
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:120
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:87
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:371
int GetTextWidth() const
Definition: eda_text.h:199
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition: eda_text.cpp:248
void SetTextWidth(int aWidth)
Definition: eda_text.cpp:355
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:217
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:185
void SetTextHeight(int aHeight)
Definition: eda_text.cpp:363
void SetBold(bool aBold)
Definition: eda_text.cpp:209
void SetTextSize(const VECTOR2I &aNewSize)
Definition: eda_text.cpp:347
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:163
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:193
int GetTextThickness() const
Definition: eda_text.h:112
void SetItalic(bool aItalic)
Definition: eda_text.cpp:201
void SetMultilineAllowed(bool aAllow)
Definition: eda_text.cpp:232
VECTOR2I GetTextSize() const
Definition: eda_text.h:196
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:240
iterator end()
Returns a read/write iterator that points to one past the last element in the EE_RTREE.
Definition: sch_rtree.h:285
iterator begin()
Returns a read/write iterator that points to the first element in the EE_RTREE N.B.
Definition: sch_rtree.h:276
Field object used in symbol libraries.
Definition: lib_field.h:61
void SetName(const wxString &aName)
Set a user definable field name to aName.
Definition: lib_field.cpp:494
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: lib_field.cpp:470
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
The base class for drawable items used by schematic library symbols.
Definition: lib_item.h:61
int GetUnit() const
Definition: lib_item.h:273
void SetPosition(const VECTOR2I &aPosition) override
Definition: lib_item.h:234
void SetUnit(int aUnit)
Definition: lib_item.h:272
void SetNumber(const wxString &aNumber)
Definition: lib_pin.h:124
void SetStroke(const STROKE_PARAMS &aStroke)
Definition: lib_shape.h:53
void AddPoint(const VECTOR2I &aPosition)
Definition: lib_shape.cpp:513
void SetPosition(const VECTOR2I &aPosition) override
Definition: lib_shape.h:86
VECTOR2I GetPosition() const override
Definition: lib_shape.h:85
Define a library symbol object.
Definition: lib_symbol.h:99
void RemoveDrawItem(LIB_ITEM *aItem)
Remove draw aItem from list.
Definition: lib_symbol.cpp:797
void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
Definition: lib_symbol.h:624
LIB_FIELD & GetReferenceField()
Return reference to the reference designator field.
void SetUnitCount(int aCount, bool aDuplicateDrawItems=true)
Set the units per symbol count.
std::vector< struct LIB_SYMBOL_UNIT > GetUnitDrawItems()
Return a list of LIB_ITEM objects separated by unit and convert number.
bool IsPower() const
Definition: lib_symbol.cpp:548
void SetPower()
Definition: lib_symbol.cpp:557
LIB_FIELD & GetFootprintField()
Return reference to the footprint field.
void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition: lib_symbol.h:632
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:508
wxString GetName() const override
Definition: lib_symbol.h:138
void SetDescription(const wxString &aDescription)
Definition: lib_symbol.h:149
void AddDrawItem(LIB_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
Definition: lib_symbol.cpp:823
LIB_FIELD * FindField(const wxString &aFieldName)
Find a field within this symbol matching aFieldName and returns it or NULL if not found.
LIB_FIELD & GetValueField()
Return reference to the value field.
void SetFPFilters(const wxArrayString &aFilters)
Definition: lib_symbol.h:197
size_t GetFieldCount() const
Definition: lib_symbol.h:397
void AddField(LIB_FIELD *aField)
Add a field.
void GetPins(LIB_PINS &aList, int aUnit=0, int aConvert=0) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:834
Define a symbol library graphical text item.
Definition: lib_text.h:40
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: lib_text.cpp:73
VECTOR2I GetPosition() const override
Definition: lib_text.h:93
ITERATOR_BASE< LIB_ITEM, MULTIVECTOR< LIB_ITEM, FIRST_TYPE_VAL, LAST_TYPE_VAL >, typename ITEM_PTR_VECTOR::iterator > ITERATOR
The const iterator.
Definition: multivector.h:164
ITERATOR end(int aType=UNDEFINED_TYPE)
Definition: multivector.h:194
ITERATOR begin(int aType=UNDEFINED_TYPE)
Definition: multivector.h:188
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
void SetWidthMils(int aWidthInMils)
Definition: page_info.cpp:244
void SetHeightMils(int aHeightInMils)
Definition: page_info.cpp:258
const wxSize GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition: page_info.h:162
virtual void SetNumPhases(int aNumPhases)=0
Set the number of phases.
virtual void BeginPhase(int aPhase)=0
Initialize the aPhase virtual zone of the dialog progress bar.
virtual void SetMaxProgress(int aMaxProgress)=0
Fix the value that gives the 100 percent progress bar length (inside the current virtual zone).
Container for project specific data.
Definition: project.h:64
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:126
virtual std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:82
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
Holds all the data relating to one schematic.
Definition: schematic.h:61
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:76
void SetSize(const wxSize &aSize)
Definition: sch_bus_entry.h:72
Class for a wire to bus entry.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:813
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_field.cpp:1041
void SetTextSpinStyle(TEXT_SPIN_STYLE aSpinStyle) override
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_label.cpp:1291
void SetTextSpinStyle(TEXT_SPIN_STYLE aSpinStyle) override
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_label.cpp:1524
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
void SetLayer(SCH_LAYER_ID aLayer)
Set the layer this item is on.
Definition: sch_item.h:253
SCH_ITEM * Duplicate(bool doClone=false) const
Routine to create a new copy of given item.
Definition: sch_item.cpp:93
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_junction.h:103
void SetShape(LABEL_FLAG_SHAPE aShape) override
Definition: sch_label.h:74
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_label.cpp:376
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
void SetStartPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:139
void SetLineWidth(const int aSize)
Definition: sch_line.cpp:285
VECTOR2I GetEndPoint() const
Definition: sch_line.h:143
VECTOR2I GetStartPoint() const
Definition: sch_line.h:138
void SetLineStyle(const PLOT_DASH_TYPE aStyle)
Definition: sch_line.cpp:256
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:144
Helper object to release a SCH_PLUGIN in the context of a potential thrown exception through its dest...
Definition: sch_io_mgr.h:535
const PAGE_INFO & GetPageSettings() const
Definition: sch_screen.h:131
void Update(SCH_ITEM *aItem)
Update aItem's bounding box in the tree.
Definition: sch_screen.cpp:265
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: sch_screen.h:132
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:109
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:110
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:145
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:66
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
Definition: sch_sheet.cpp:365
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:93
bool LocatePathOfScreen(SCH_SCREEN *aScreen, SCH_SHEET_PATH *aList)
Search the existing hierarchy for an instance of screen loaded from aFileName.
Definition: sch_sheet.cpp:755
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:106
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:368
void SetFields(const std::vector< SCH_FIELD > &aFields)
Set multiple schematic fields.
Definition: sch_sheet.cpp:343
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:162
wxSize GetSize() const
Definition: sch_sheet.h:108
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_sheet.cpp:602
static bool ClassOf(const EDA_ITEM *aItem)
Definition: sch_sheet.h:72
Schematic symbol object.
Definition: sch_symbol.h:81
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_symbol.h:713
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:486
SCH_FIELD * FindField(const wxString &aFieldName, bool aIncludeDefaultFields=true)
Search for a SCH_FIELD with aFieldName.
Definition: sch_symbol.cpp:916
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:843
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
Definition: sch_symbol.cpp:335
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
Definition: sch_symbol.cpp:694
void SetOrientation(int aOrientation)
Compute the new transform matrix based on aOrientation for the symbol which is applied to the current...
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
Definition: sch_symbol.cpp:894
BOX2I GetBodyAndPinsBoundingBox() const
Return a bounding box for the symbol body and pins but not the fields.
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:879
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:192
VECTOR2I GetPosition() const override
Definition: sch_text.h:203
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_text.h:204
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_text.cpp:321
virtual void SetTextSpinStyle(TEXT_SPIN_STYLE aSpinStyle)
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_text.cpp:188
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
const SHAPE_LINE_CHAIN ConvertToPolyline(double aAccuracy=DefaultAccuracyForPCB(), double *aEffectiveAccuracy=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
Definition: shape_arc.cpp:470
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
int FindSegment(const VECTOR2I &aP, int aThreshold=1) const
Search for segment containing point aP.
int Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Find all intersection points between our line chain and the segment aSeg.
void Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Replace points with indices in range [start_index, end_index] with a single point aP.
virtual size_t GetPointCount() const override
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
int SegmentCount() const
Return the number of segments in this line chain.
std::vector< INTERSECTION > INTERSECTIONS
const std::vector< VECTOR2I > & CPoints() const
SEG Segment(int aIndex)
Return a copy of the aIndex-th segment in the line chain.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Simple container to manage line stroke parameters.
Definition: stroke_params.h:88
TEXT_SPIN_STYLE MirrorY()
Mirror the label spin style across the Y axis or simply swaps left and right.
Definition: sch_text.cpp:99
TEXT_SPIN_STYLE RotateCCW()
Definition: sch_text.cpp:67
TEXT_SPIN_STYLE MirrorX()
Mirror the label spin style across the X axis or simply swaps up and bottom.
Definition: sch_text.cpp:83
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293
#define DEFAULT_WIRE_WIDTH_MILS
The default bus width in mils. (can be changed in preference menu)
#define _(s)
static constexpr EDA_ANGLE & ANGLE_180
Definition: eda_angle.h:416
static constexpr EDA_ANGLE & ANGLE_HORIZONTAL
Definition: eda_angle.h:408
static constexpr EDA_ANGLE & ANGLE_VERTICAL
Definition: eda_angle.h:409
static constexpr EDA_ANGLE & ANGLE_45
Definition: eda_angle.h:413
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:414
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:412
static constexpr EDA_ANGLE & ANGLE_270
Definition: eda_angle.h:417
static constexpr EDA_ANGLE & ANGLE_135
Definition: eda_angle.h:415
@ FILLED_WITH_BG_BODYCOLOR
@ FILLED_SHAPE
const std::string KiCadSchematicFileExtension
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
SCH_LAYER_ID
Eeschema drawing layers.
Definition: layer_ids.h:341
@ LAYER_WIRE
Definition: layer_ids.h:344
@ LAYER_NOTES
Definition: layer_ids.h:358
@ LAYER_BUS
Definition: layer_ids.h:345
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:54
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition: mirror.h:40
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:99
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:401
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition: pin_type.h:36
@ PT_INPUT
usual pin input: must be connected
@ PT_OUTPUT
usual output
@ PT_BIDI
input or output (like port for a microprocessor)
@ PT_OPENCOLLECTOR
pin type open collector
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ SYM_ORIENT_270
@ SYM_MIRROR_Y
@ SYM_ORIENT_180
@ SYM_ORIENT_90
@ SYM_ORIENT_0
@ SHEETNAME
Definition: sch_sheet.h:45
@ SHEETFILENAME
Definition: sch_sheet.h:46
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
std::vector< SCH_FIELD > SCH_FIELDS
A container for several SCH_FIELD items.
Definition: sch_symbol.h:69
@ L_BIDI
Definition: sch_text.h:99
@ L_UNSPECIFIED
Definition: sch_text.h:101
@ L_OUTPUT
Definition: sch_text.h:98
@ L_INPUT
Definition: sch_text.h:97
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
bool ReplaceIllegalFileNameChars(std::string *aName, int aReplaceChar)
Checks aName for illegal file name characters.
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_LIBID
Definition: string_utils.h:55
PLOT_DASH_TYPE
Dashed line types.
Definition: stroke_params.h:48
std::map< ATTRIBUTE_ID, ATTRCOL > AttributeColors
JUSTIFICATION Justification
Note: Justification has no effect on single lines of text.
ALIGNMENT Alignment
In CADSTAR The default alignment for a TEXT object (when "(No Alignment()" is selected) Bottom Left o...
bool HasLocation
Flag to know if this ATTRIBUTE_VALUE has a location i.e.
std::map< LINECODE_ID, LINECODE > LineCodes
std::map< ATTRIBUTE_ID, ATTRNAME > AttributeNames
std::map< ROUTECODE_ID, ROUTECODE > RouteCodes
std::map< TEXTCODE_ID, TEXTCODE > TextCodes
Represents a cutout in a closed shape (e.g.
long ScaleRatioNumerator
Documentation symbols can be arbitrarily scaled when added to a design.
long ScaleRatioDenominator
Documentation symbols can be arbitrarily scaled when added to a design.
POINT Origin
Origin of the component (this is used as the reference point when placing the component in the design...
LAYER_ID LayerID
Move all objects in the Symdef to this layer.
SYMDEF_ID SymdefID
Normally documentation symbols only have TEXT, FIGURE and TEXT_LOCATION objects which are all drawn o...
long Modifier1
It seems this is related to weight. 400=Normal, 700=Bold.
long Param1
Either Units or X step, depending on Type (see GRID_TYPE for more details)
long Param2
Either Divisor or Y step, depending on Type (see GRID_TYPE for more details)
wxString Name
This is undefined (wxEmptyString) if the net is unnamed.
long SignalNum
This is undefined if the net has been given a name.
std::map< TEXT_FIELD_NAME, wxString > TextFieldToValuesMap
Values for the text field elements used in the CADSTAR design extracted from the text element instanc...
std::map< wxString, wxString > FilenamesToTextMap
CADSTAR doesn't have user defined text fields but does allow loading text from a file.
std::set< TEXT_FIELD_NAME > InconsistentTextFields
Text fields need to be updated in CADSTAR and it is possible that they are not consistent across text...
std::map< PART_ID, PART > PartDefinitions
bool HidePinNames
Specifies whether to display the pin names/identifier in the schematic symbol or not.
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
Some attributes are defined within the part definition, whilst others are defined in the part.
std::map< PART_DEFINITION_PIN_ID, PIN > Pins
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
Some attributes are defined within the part definition, whilst others are defined in the part itself.
Represents a point in x,y coordinates.
SHAPE_POLY_SET ConvertToPolySet(const std::function< VECTOR2I(const VECTOR2I &)> aCadstarToKicadPointCallback, double aAccuracy) const
std::vector< CUTOUT > Cutouts
Not Applicable to OPENSHAPE Type.
std::map< FIGURE_ID, FIGURE > Figures
std::map< ATTRIBUTE_ID, TEXT_LOCATION > TextLocations
This contains location of any attributes, including designator position.
POINT Origin
Origin of the component (this is used as the reference point when placing the component in the design...
wxString Alternate
This is in addition to ReferenceName.
wxString ReferenceName
This is the name which identifies the symbol in the library Multiple components may exist with the sa...
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
These attributes might also have a location.
long Width
Defaults to 0 if using system fonts or, if using CADSTAR font, default to equal height (1:1 aspect ra...
Corresponds to CADSTAR "origin".
ALIGNMENT Alignment
In CADSTAR The default alignment for a TEXT object (when "(No Alignment()" is selected) Bottom Left o...
JUSTIFICATION Justification
Note: Justification has no effect on single lines of text.
< Nodename = "VARIANT" or "VMASTER" (master variant
Represents a vertex in a shape.
TYPE Type
Determines what the associated layer is, whether parent, child or clone.
LAYER_ID LayerID
The sheet block is on (TODO: verify this is true)
LAYER_ID AssocLayerID
Parent or Child linked sheet.
std::map< TERMINAL_ID, TERMINAL > Terminals
LAYER_ID LayerID
Sheet on which bus is located.
std::map< REUSEBLOCK_ID, REUSEBLOCK > ReuseBlocks
std::map< DOCUMENTATION_SYMBOL_ID, DOCUMENTATION_SYMBOL > DocumentationSymbols
std::map< SYMDEF_ID, SYMDEF_SCM > SymbolDefinitions
std::map< NETELEMENT_ID, DANGLER > Danglers
std::map< NETELEMENT_ID, SYM_TERM > Terminals
std::map< NETELEMENT_ID, BUS_TERM > BusTerminals
std::map< NETELEMENT_ID, BLOCK_TERM > BlockTerminals
std::map< NETELEMENT_ID, JUNCTION_SCH > Junctions
std::vector< LAYER_ID > SheetOrder
A vector to also store the order in which sheets are to be displayed.
std::map< LAYER_ID, SHEET_NAME > SheetNames
LAYER_ID LayerID
Sheet on which symbol is located.
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
GATE_ID GateID
The gate this symbol represents within the associated Part.
long ScaleRatioNumerator
Symbols can be arbitrarily scaled in CADSTAR.
std::map< TERMINAL_ID, SYMPINNAME_LABEL > PinNames
Identifier of the pin in the PCB Equivalent to KiCad's Pin Number.
std::map< TERMINAL_ID, PIN_NUM > PinNumbers
This seems to only appear in older designs and is similar to PinNames but only allowing numerical val...
std::map< TERMINAL_ID, PIN_NUM_LABEL_LOC > PinLabelLocations
std::map< TERMINAL_ID, PIN_NUM_LABEL_LOC > PinNumberLocations
std::map< TERMINAL_ID, TERMINAL > Terminals
POINT Position
Pad position within the component's coordinate frame.
constexpr int IUToMils(int iu) const
Definition: base_units.h:100
const double IU_PER_MILS
Definition: base_units.h:78
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
@ LIB_TEXT_T
Definition: typeinfo.h:200
@ SCH_SYMBOL_T
Definition: typeinfo.h:156
@ SCH_FIELD_T
Definition: typeinfo.h:155
@ SCH_LABEL_T
Definition: typeinfo.h:151
@ LIB_SHAPE_T
Definition: typeinfo.h:199
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:153
@ LIB_PIN_T
Definition: typeinfo.h:202
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:157
@ SCH_TEXT_T
Definition: typeinfo.h:150
@ LIB_FIELD_T
Definition: typeinfo.h:208
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:152
int sign(T val)
Definition: util.h:124
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
const int LexicographicalCompare(const VECTOR2< T > &aA, const VECTOR2< T > &aB)
Definition: vector2d.h:569
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618
Definition of file extensions used in Kicad.