KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2023 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
28
29#include <bus_alias.h>
30#include <core/mirror.h>
31#include <core/kicad_algo.h>
32#include <eda_text.h>
33#include <macros.h>
34#include <progress_reporter.h>
35#include <string_utils.h>
36#include <sch_bus_entry.h>
37#include <sch_edit_frame.h> //SYMBOL_ORIENTATION_T
38#include <sch_io/sch_io_mgr.h>
39#include <sch_junction.h>
40#include <sch_line.h>
41#include <sch_screen.h>
42#include <sch_shape.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 <sim/sim_model.h>
49#include <trigo.h>
51
52
53const wxString PartNameFieldName = "Part Name";
54const wxString PartNumberFieldName = "Part Number";
55const wxString PartVersionFieldName = "Part Version";
56const wxString PartAcceptanceFieldName = "Part Acceptance";
57
58
59std::vector<LIB_SYMBOL*> CADSTAR_SCH_ARCHIVE_LOADER::LoadPartsLib( const wxString& aFilename )
60{
62 m_progressReporter->SetNumPhases( 3 ); // (0) Read csa, (1) Parse csa, (3) Load lib
63
64 Parse();
65
67
68 if( !p.CheckFileHeader( aFilename.utf8_string() ) )
70 _( "The selected file does not appear to be a CADSTAR parts Library file" ) );
71
72 // TODO: we could add progress reporting for reading .lib
73 CADSTAR_PARTS_LIB_MODEL csLib = p.ReadFile( aFilename.utf8_string() );
74
76 {
78 long numSteps = csLib.m_PartEntries.size();
80 }
81
82 std::vector<LIB_SYMBOL*> retVal;
83
84 for( const CADSTAR_PART_ENTRY& part : csLib.m_PartEntries )
85 {
86 std::unique_ptr<LIB_SYMBOL> loadedPart = loadLibPart( part );
87
88 checkPoint();
89
90 if( loadedPart )
91 retVal.push_back( loadedPart.release() );
92 }
93
94 return retVal;
95}
96
97
98std::unique_ptr<LIB_SYMBOL>
100{
101 wxString escapedPartName = EscapeString( aPart.m_Name, CTX_LIBID );
102 std::unique_ptr<LIB_SYMBOL> retSym;
103
104 int unit = 0;
105
106 for( const CADSTAR_PART_SYMBOL_ENTRY& sym : aPart.m_Symbols )
107 {
108 ++unit;
109 wxString alternateName = sym.m_SymbolAlternateName.value_or( "" );
110 SYMDEF_ID symbolID = getSymDefFromName( sym.m_SymbolName, alternateName );
111
112 if( !Library.SymbolDefinitions.count( symbolID ) )
113 {
115 wxString::Format( _( "Unable to find symbol %s, referenced by part %s. The "
116 "part was not loaded." ),
117 generateLibName( sym.m_SymbolName, alternateName ),
118 aPart.m_Name ),
120
121 return nullptr;
122 }
123
124 // Load the graphical symbol for this gate
125 std::unique_ptr<LIB_SYMBOL> kiSymDef( loadSymdef( symbolID )->Duplicate() );
126
127 if( (int)sym.m_Pins.size() != kiSymDef->GetPinCount() )
128 {
130 wxString::Format( _( "Inconsistent pin numbers in symbol %s compared to the one "
131 "defined in part %s. The part was not loaded." ),
132 generateLibName( sym.m_SymbolName, alternateName ),
133 aPart.m_Name ),
135
136 return nullptr;
137 }
138
139 wxASSERT( m_symDefTerminalsMap.count( symbolID ) ); //loadSymDef should have populated this
140
141
142 // Update the pin numbers to match those defined in the Cadstar part
143 for( auto& [storedPinNum, termID] : m_symDefTerminalsMap[symbolID] )
144 {
145 wxCHECK( termID > 0 && sym.m_Pins.size() >= size_t( termID ), nullptr );
146 SCH_PIN* pin = kiSymDef->GetPin( storedPinNum );
147 size_t termIdx = size_t( termID ) - 1;
148
149 // For now leave numerical pin number. Otherwise, when loading the
150 // .cpa file we won't be able to link up to the footprint pads, but if
151 // we solve this, we could then load alphanumeric pin numbers as below:
152 //
153 // if( aPart.m_PinNamesMap.count( termID ) )
154 // partPinNum = wxString( aPart.m_PinNamesMap.at( termID ) );
155 //
156 wxString partPinNum = wxString::Format( "%ld", sym.m_Pins[termIdx].m_Identifier );
157 pin->SetNumber( partPinNum );
158
159 if( aPart.m_PinNamesMap.count( termID ) )
160 pin->SetName( HandleTextOverbar( aPart.m_PinNamesMap.at( termID ) ) );
161 else if( aPart.m_PinLabelsMap.count( termID ) )
162 pin->SetName( HandleTextOverbar( aPart.m_PinLabelsMap.at( termID ) ) );
163
164 pin->SetType( getKiCadPinType( sym.m_Pins[termIdx].m_Type ) );
165
166 // @todo: Load pin/gate swapping information once kicad supports this
167 }
168
169 if( unit == 1 )
170 {
171 wxCHECK( kiSymDef->GetUnitCount() == 1, nullptr );
172 // The first unit can just be moved to the part symbol
173 retSym = std::move( kiSymDef );
174
175 retSym->SetUnitCount( aPart.m_Symbols.size(), true );
176
177 retSym->SetName( escapedPartName );
178 retSym->GetReferenceField().SetText( aPart.m_ComponentStem );
179 retSym->GetValueField().SetText( aPart.m_Value.value_or( "" ) );
181 retSym->SetDescription( aPart.m_Description.value_or( "" ) );
182
183 auto addFieldIfHasValue =
184 [&]( const wxString& aFieldName, const std::optional<std::string>& aFieldValue )
185 {
186 if( aFieldValue.has_value() )
187 addNewFieldToSymbol( aFieldName, retSym )->SetText( aFieldValue.value() );
188 };
189
190 addFieldIfHasValue( PartNumberFieldName, aPart.m_Number );
191 addFieldIfHasValue( PartVersionFieldName, aPart.m_Version );
192 addFieldIfHasValue( PartAcceptanceFieldName, aPart.m_AcceptancePartName );
193
195 aPart.m_Pcb_alternate.value_or( "" ) );
196
197 if(aPart.m_SpiceModel.has_value())
198 {
199 wxString modelVal = wxString::Format( "model=\"%s\"", aPart.m_SpiceModel.value() );
200 addNewFieldToSymbol( SIM_DEVICE_FIELD, retSym )->SetText( "SPICE" );
201 addNewFieldToSymbol( SIM_PARAMS_FIELD, retSym )->SetText( modelVal );
202 }
203
204 // Load all part attributes, regardless of original cadstar type, to the symbol
205
206 // @todo some cadstar part attributes have a "read-only" flag. We should load this
207 // when KiCad supports read-only fields.
208
209 for( auto& [fieldName, value] : aPart.m_UserAttributes )
210 addNewFieldToSymbol( fieldName, retSym )->SetText( value );
211
212 for( auto& [fieldName, attrValue] : aPart.m_SchAttributes )
213 addNewFieldToSymbol( fieldName, retSym )->SetText( attrValue.m_Value );
214
215 for( auto& [fieldName, attrValue] : aPart.m_PcbAttributes )
216 addNewFieldToSymbol( fieldName, retSym )->SetText( attrValue.m_Value );
217
218 for( auto& [fieldName, attrValue] : aPart.m_SchAndPcbAttributes )
219 addNewFieldToSymbol( fieldName, retSym )->SetText( attrValue.m_Value );
220
221 for( auto& [fieldName, attrValue] : aPart.m_PartAttributes )
222 addNewFieldToSymbol( fieldName, retSym )->SetText( attrValue.m_Value );
223
224 // Load all hidden pins onto the first unit of the symbol in KiCad
225 // We load them in a spiral sequence, starting at the center of the symbol BBOX
226 VECTOR2I symCenter = retSym->GetBodyBoundingBox( unit, 0, false, false ).GetCenter();
227 symCenter.y = -symCenter.y; // need to invert the y coord for lib symbols.
228
229 VECTOR2I delta( 0, 1 );
230 VECTOR2I direction( 0, -1 );
231 int spacing = schIUScale.MilsToIU( 50 ); // for now, place on a 50mil grid
232
233 for( auto& [signalName, csPinVector] : aPart.m_HiddenPins )
234 {
235 for( const CADSTAR_PART_PIN& csPin : csPinVector )
236 {
237 std::unique_ptr<SCH_PIN> pin = std::make_unique<SCH_PIN>( retSym.get() );
238
239 long pinNum = csPin.m_Identifier;
240 pin->SetNumber( wxString::Format( "%ld", pinNum ) );
241 pin->SetName( signalName );
242 pin->SetType( ELECTRICAL_PINTYPE::PT_POWER_IN );
243
244 pin->SetVisible( false );
245
246 // Generate the coordinate for the pin. We don't want overlapping pins
247 // and ideally close to the center of the symbol, so we load pins
248 // in a spiral sequence around the center
249 if( delta.x == delta.y || ( delta.x < 0 && delta.x == -delta.y )
250 || ( delta.x > 0 && delta.x == 1 - delta.y ) )
251 {
252 // change direction
253 direction = { -direction.y, direction.x };
254 }
255
256 delta += direction;
257 VECTOR2I offset = delta * spacing;
258 pin->SetPosition( symCenter + offset );
259 pin->SetLength( 0 ); //CADSTAR Pins are just a point (have no length)
260 pin->SetShape( GRAPHIC_PINSHAPE::LINE );
261 pin->SetUnit( unit );
262 retSym->AddDrawItem( pin.release() );
263 }
264 }
265 }
266 else
267 { // Source: Dest:
268 copySymbolItems( kiSymDef, retSym, unit, false /* aOverrideFields */ );
269 }
270
271
272 retSym->SetShowPinNames( aPart.m_PinsVisible );
273 retSym->SetShowPinNumbers( aPart.m_PinsVisible );
274 }
275
276
277 return retSym;
278}
279
280
281void CADSTAR_SCH_ARCHIVE_LOADER::copySymbolItems( std::unique_ptr<LIB_SYMBOL>& aSourceSym,
282 std::unique_ptr<LIB_SYMBOL>& aDestSym,
283 int aDestUnit, bool aOverrideFields )
284{
285 // Ensure there are no items on the unit we want to load onto
286 for( SCH_ITEM* item : aDestSym->GetUnitDrawItems( aDestUnit, 0 /*aConvert*/ ) )
287 aDestSym->RemoveDrawItem( item );
288
289 // Copy all draw items
290 for( SCH_ITEM* newItem : aSourceSym->GetUnitDrawItems( 1, 0 /*aConvert*/ ) )
291 {
292 SCH_ITEM* itemCopy = static_cast<SCH_ITEM*>( newItem->Clone() );
293 itemCopy->SetParent( aDestSym.get() );
294 itemCopy->SetUnit( aDestUnit );
295 aDestSym->AddDrawItem( itemCopy );
296 }
297
298 //Copy / override all fields
299 if( aOverrideFields )
300 {
301 std::vector<SCH_FIELD*> fieldsToCopy;
302 aSourceSym->GetFields( fieldsToCopy );
303
304 for( SCH_FIELD* templateField : fieldsToCopy )
305 {
306 SCH_FIELD* appliedField = addNewFieldToSymbol( templateField->GetName(), aDestSym );
307 templateField->Copy( appliedField );
308 }
309 }
310}
311
312
314{
315 wxCHECK( aSchematic, /* void */ );
316
318 m_progressReporter->SetNumPhases( 3 ); // (0) Read file, (1) Parse file, (2) Load file
319
320 Parse();
321
322 checkDesignLimits(); // Throws if error found
323
324 // Assume the center at 0,0 since we are going to be translating the design afterwards anyway
325 m_designCenter = { 0, 0 };
326
327 m_schematic = aSchematic;
328 m_rootSheet = aRootSheet;
329
331 {
333 long numSteps = 11; // one step for each of below functions + one at the end of import
334
335 // Step 4 is by far the longest - add granularity in reporting
336 numSteps += Parts.PartDefinitions.size();
337
339 }
340
341 loadTextVariables(); // Load text variables right at the start to ensure bounding box
342 // calculations work correctly for text items
343 checkPoint(); // Step 1
344 loadSheets();
345 checkPoint(); // Step 2
347 checkPoint(); // Step 3
349 checkPoint(); // Step 4, Subdivided into extra steps
351 checkPoint(); // Step 5
352 loadBusses();
353 checkPoint(); // Step 6
354 loadNets();
355 checkPoint(); // Step 7
356 loadFigures();
357 checkPoint(); // Step 8
358 loadTexts();
359 checkPoint(); // Step 9
361 checkPoint(); // Step 10
362
363 if( Schematic.VariantHierarchy.Variants.size() > 0 )
364 {
365 m_reporter->Report( wxString::Format( _( "The CADSTAR design contains variants which has "
366 "no KiCad equivalent. Only the master variant "
367 "('%s') was loaded." ),
368 Schematic.VariantHierarchy.Variants.at( "V0" ).Name ),
370 }
371
372 if( Schematic.Groups.size() > 0 )
373 {
374 m_reporter->Report( _( "The CADSTAR design contains grouped items which has no KiCad "
375 "equivalent. Any grouped items have been ungrouped." ),
377 }
378
379 if( Schematic.ReuseBlocks.size() > 0 )
380 {
381 m_reporter->Report( _( "The CADSTAR design contains re-use blocks which has no KiCad "
382 "equivalent. The re-use block information has been discarded during "
383 "the import." ),
385 }
386
387
388 // For all sheets, center all elements and re calculate the page size:
389 for( std::pair<LAYER_ID, SCH_SHEET*> sheetPair : m_sheetMap )
390 {
391 SCH_SHEET* sheet = sheetPair.second;
392
393 // Calculate the new sheet size.
394 BOX2I sheetBoundingBox;
395
396 for( SCH_ITEM* item : sheet->GetScreen()->Items() )
397 {
398 BOX2I bbox;
399
400 // Only use the visible fields of the symbols to calculate their bounding box
401 // (hidden fields could be very long and artificially enlarge the sheet bounding box)
402 if( item->Type() == SCH_SYMBOL_T )
403 {
404 SCH_SYMBOL* comp = static_cast<SCH_SYMBOL*>( item );
405 bbox = comp->GetBodyAndPinsBoundingBox();
406
407 for( const SCH_FIELD& field : comp->GetFields() )
408 {
409 if( field.IsVisible() )
410 bbox.Merge( field.GetBoundingBox() );
411 }
412 }
413 else if( item->Type() == SCH_TEXT_T )
414 {
415 SCH_TEXT* txtItem = static_cast<SCH_TEXT*>( item );
416 wxString txt = txtItem->GetText();
417
418 if( txt.Contains( "${" ) )
419 continue; // We can't calculate bounding box of text items with variables
420 else
421 bbox = txtItem->GetBoundingBox();
422 }
423 else
424 {
425 bbox = item->GetBoundingBox();
426 }
427
428 sheetBoundingBox.Merge( bbox );
429 }
430
431 // Find the screen grid of the original CADSTAR design
433
438
440
441 auto roundToNearestGrid =
442 [&]( int aNumber ) -> int
443 {
444 int error = aNumber % grid;
445 int absError = sign( error ) * error;
446
447 if( absError > ( grid / 2 ) )
448 return aNumber + ( sign( error ) * grid ) - error;
449 else
450 return aNumber - error;
451 };
452
453 // When exporting to pdf, CADSTAR applies a margin of 3% of the longest dimension (height
454 // or width) to all 4 sides (top, bottom, left right). For the import, we are also rounding
455 // the margin to the nearest grid, ensuring all items remain on the grid.
456 VECTOR2I targetSheetSize = sheetBoundingBox.GetSize();
457 int longestSide = std::max( targetSheetSize.x, targetSheetSize.y );
458 int margin = ( (double) longestSide * 0.03 );
459 margin = roundToNearestGrid( margin );
460 targetSheetSize += margin * 2;
461
462 // Update page size always
463 PAGE_INFO pageInfo = sheet->GetScreen()->GetPageSettings();
464 pageInfo.SetWidthMils( schIUScale.IUToMils( targetSheetSize.x ) );
465 pageInfo.SetHeightMils( schIUScale.IUToMils( targetSheetSize.y ) );
466
467 // Set the new sheet size.
468 sheet->GetScreen()->SetPageSettings( pageInfo );
469
471 VECTOR2I sheetcentre( pageSizeIU.x / 2, pageSizeIU.y / 2 );
472 VECTOR2I itemsCentre = sheetBoundingBox.Centre();
473
474 // round the translation to nearest point on the grid
475 VECTOR2I translation = sheetcentre - itemsCentre;
476 translation.x = roundToNearestGrid( translation.x );
477 translation.y = roundToNearestGrid( translation.y );
478
479 // Translate the items.
480 std::vector<SCH_ITEM*> allItems;
481
482 std::copy( sheet->GetScreen()->Items().begin(), sheet->GetScreen()->Items().end(),
483 std::back_inserter( allItems ) );
484
485 for( SCH_ITEM* item : allItems )
486 {
487 item->Move( translation );
488 item->ClearFlags();
489 sheet->GetScreen()->Update( item );
490 }
491 }
492
493 checkPoint();
494
495 m_reporter->Report( _( "CADSTAR fonts are different to the ones in KiCad. This will likely "
496 "result in alignment issues. Please review the imported text elements "
497 "carefully and correct manually if required." ),
499
500 m_reporter->Report( _( "The CADSTAR design has been imported successfully.\n"
501 "Please review the import errors and warnings (if any)." ) );
502}
503
504
506{
508
509 //Note: can't use getKiCadPoint() due VECTOR2I being int - need long long to make the check
510 long long designSizeXkicad = (long long) designLimit.x / KiCadUnitDivider;
511 long long designSizeYkicad = (long long) designLimit.y / KiCadUnitDivider;
512
513 // Max size limited by the positive dimension of VECTOR2I (which is an int)
514 constexpr long long maxDesignSizekicad = std::numeric_limits<int>::max();
515
516 if( designSizeXkicad > maxDesignSizekicad || designSizeYkicad > maxDesignSizekicad )
517 {
518 THROW_IO_ERROR( wxString::Format(
519 _( "The design is too large and cannot be imported into KiCad. \n"
520 "Please reduce the maximum design size in CADSTAR by navigating to: \n"
521 "Design Tab -> Properties -> Design Options -> Maximum Design Size. \n"
522 "Current Design size: %.2f, %.2f millimeters. \n"
523 "Maximum permitted design size: %.2f, %.2f millimeters.\n" ),
524 (double) designSizeXkicad / SCH_IU_PER_MM,
525 (double) designSizeYkicad / SCH_IU_PER_MM,
526 (double) maxDesignSizekicad / SCH_IU_PER_MM,
527 (double) maxDesignSizekicad / SCH_IU_PER_MM ) );
528 }
529}
530
531
533{
534 const std::vector<LAYER_ID>& orphanSheets = findOrphanSheets();
535 SCH_SHEET_PATH rootPath;
536 rootPath.push_back( m_rootSheet );
537 rootPath.SetPageNumber( wxT( "1" ) );
538
539 if( orphanSheets.size() > 1 )
540 {
541 int x = 1;
542 int y = 1;
543
544 for( LAYER_ID sheetID : orphanSheets )
545 {
546 VECTOR2I pos( x * schIUScale.MilsToIU( 1000 ), y * schIUScale.MilsToIU( 1000 ) );
547 VECTOR2I siz( schIUScale.MilsToIU( 1000 ), schIUScale.MilsToIU( 1000 ) );
548
549 loadSheetAndChildSheets( sheetID, pos, siz, rootPath );
550
551 x += 2;
552
553 if( x > 10 ) // start next row
554 {
555 x = 1;
556 y += 2;
557 }
558 }
559 }
560 else if( orphanSheets.size() > 0 )
561 {
562 LAYER_ID rootSheetID = orphanSheets.at( 0 );
563
564 wxFileName loadedFilePath = wxFileName( Filename );
565
566 std::string filename = wxString::Format( "%s_%02d", loadedFilePath.GetName(),
567 getSheetNumber( rootSheetID ) )
568 .ToStdString();
569 ReplaceIllegalFileNameChars( &filename );
570 filename += wxT( "." ) + wxString( FILEEXT::KiCadSchematicFileExtension );
571
572 wxFileName fn( m_schematic->Prj().GetProjectPath() + filename );
573 m_rootSheet->GetScreen()->SetFileName( fn.GetFullPath() );
574
575 m_sheetMap.insert( { rootSheetID, m_rootSheet } );
576 loadChildSheets( rootSheetID, rootPath );
577 }
578 else if( Header.Format.Type == "SYMBOL" )
579 {
580 THROW_IO_ERROR( _( "The selected file is a CADSTAR symbol library. It does not contain a "
581 "schematic design so cannot be imported/opened in this way." ) );
582 }
583 else
584 {
585 THROW_IO_ERROR( _( "The CADSTAR schematic might be corrupt: there is no root sheet." ) );
586 }
587}
588
589
591{
592 for( std::pair<BLOCK_ID, BLOCK> blockPair : Schematic.Blocks )
593 {
594 BLOCK& block = blockPair.second;
595 LAYER_ID sheetID = "";
596
597 if( block.Type == BLOCK::TYPE::PARENT )
598 sheetID = block.LayerID;
599 else if( block.Type == BLOCK::TYPE::CHILD )
600 sheetID = block.AssocLayerID;
601 else
602 continue;
603
604 if( m_sheetMap.find( sheetID ) != m_sheetMap.end() )
605 {
606 SCH_SHEET* sheet = m_sheetMap.at( sheetID );
607
608 for( std::pair<TERMINAL_ID, TERMINAL> termPair : block.Terminals )
609 {
610 TERMINAL term = termPair.second;
611 wxString name = "YOU SHOULDN'T SEE THIS TEXT. THIS IS A BUG.";
612
613 SCH_HIERLABEL* sheetPin = nullptr;
614
615 if( block.Type == BLOCK::TYPE::PARENT )
616 sheetPin = new SCH_HIERLABEL();
617 else if( block.Type == BLOCK::TYPE::CHILD )
618 sheetPin = new SCH_SHEET_PIN( sheet );
619
620 sheetPin->SetText( name );
621 sheetPin->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
622 sheetPin->SetSpinStyle( getSpinStyle( term.OrientAngle, false ) );
623 sheetPin->SetPosition( getKiCadPoint( term.Position ) );
624
625 if( sheetPin->Type() == SCH_SHEET_PIN_T )
626 sheet->AddPin( (SCH_SHEET_PIN*) sheetPin );
627 else
628 sheet->GetScreen()->Append( sheetPin );
629
630 BLOCK_PIN_ID blockPinID = std::make_pair( block.ID, term.ID );
631 m_sheetPinMap.insert( { blockPinID, sheetPin } );
632 }
633 }
634 }
635}
636
637
639{
640 for( std::pair<PART_ID, PART> partPair : Parts.PartDefinitions )
641 {
642 PART_ID partID = partPair.first;
643 PART part = partPair.second;
644
645 wxString escapedPartName = EscapeString( part.Name, CTX_LIBID );
646 LIB_SYMBOL* kiSym = new LIB_SYMBOL( escapedPartName );
647
648 kiSym->SetUnitCount( part.Definition.GateSymbols.size() );
649 bool ok = true;
650
651 for( std::pair<GATE_ID, PART::DEFINITION::GATE> gatePair : part.Definition.GateSymbols )
652 {
653 GATE_ID gateID = gatePair.first;
654 PART::DEFINITION::GATE gate = gatePair.second;
655 SYMDEF_ID symbolID = getSymDefFromName( gate.Name, gate.Alternate );
656
657 if( symbolID.IsEmpty() )
658 {
659 m_reporter->Report( wxString::Format( _( "Part definition '%s' references symbol "
660 "'%s' (alternate '%s') which could not be "
661 "found in the symbol library. The part has "
662 "not been loaded into the KiCad library." ),
663 part.Name,
664 gate.Name,
665 gate.Alternate ),
667
668 ok = false;
669 break;
670 }
671
672 m_partSymbolsMap.insert( { { partID, gateID }, symbolID } );
673 loadSymbolGateAndPartFields( symbolID, part, gateID, kiSym );
674 }
675
676 if( ok && part.Definition.GateSymbols.size() != 0 )
677 {
678 m_loadedSymbols.push_back( kiSym );
679 }
680 else
681 {
682 if( part.Definition.GateSymbols.size() == 0 )
683 {
685 wxString::Format( _( "Part definition '%s' has an incomplete definition (no"
686 " symbol definitions are associated with it). The part"
687 " has not been loaded into the KiCad library." ),
688 part.Name ),
690 }
691
692 // Don't save in the library, but still keep it cached as some of the units might have
693 // been loaded correctly (saving us time later on), plus the part definition contains
694 // the part name, which is important to load
695 }
696
697 m_partMap.insert( { partID, kiSym } );
698
699 checkPoint();
700 }
701}
702
703
705{
706 for( std::pair<SYMBOL_ID, SYMBOL> symPair : Schematic.Symbols )
707 {
708 SYMBOL sym = symPair.second;
709
710 if( !sym.VariantID.empty() && sym.VariantParentSymbolID != sym.ID )
711 continue; // Only load master Variant
712
713 if( sym.IsComponent )
714 {
715 if( m_partMap.find( sym.PartRef.RefID ) == m_partMap.end() )
716 {
717 m_reporter->Report( wxString::Format( _( "Symbol '%s' references part '%s' which "
718 "could not be found in the library. The "
719 "symbol was not loaded" ),
721 sym.PartRef.RefID ),
723
724 continue;
725 }
726
727 if( sym.GateID.IsEmpty() )
728 sym.GateID = wxT( "A" ); // Assume Gate "A" if unspecified
729
730 PART_GATE_ID partSymbolID = { sym.PartRef.RefID, sym.GateID };
731 LIB_SYMBOL* kiSym = m_partMap.at( sym.PartRef.RefID );
732 bool copy = false;
733
734 // The symbol definition in the part either does not exist for this gate number
735 // or is different to the symbol instance. We need to reload the gate for this
736 // symbol
737 if( m_partSymbolsMap.find( partSymbolID ) == m_partSymbolsMap.end()
738 || m_partSymbolsMap.at( partSymbolID ) != sym.SymdefID )
739 {
740 kiSym = new LIB_SYMBOL( *kiSym ); // Make a copy
741 copy = true;
742 const PART& part = Parts.PartDefinitions.at( sym.PartRef.RefID );
743 loadSymbolGateAndPartFields( sym.SymdefID, part, sym.GateID, kiSym );
744 }
745
746 LIB_SYMBOL* scaledPart = getScaledLibPart( kiSym, sym.ScaleRatioNumerator,
748
749 EDA_ANGLE symOrient = ANGLE_0;
750 SCH_SYMBOL* symbol = loadSchematicSymbol( sym, *scaledPart, symOrient );
751
752 delete scaledPart;
753
754 if( copy )
755 delete kiSym;
756
757 SCH_FIELD* refField = symbol->GetField( REFERENCE_FIELD );
758
759 sym.ComponentRef.Designator.Replace( wxT( "\n" ), wxT( "\\n" ) );
760 sym.ComponentRef.Designator.Replace( wxT( "\r" ), wxT( "\\r" ) );
761 sym.ComponentRef.Designator.Replace( wxT( "\t" ), wxT( "\\t" ) );
762 sym.ComponentRef.Designator.Replace( wxT( " " ), wxT( "_" ) );
763
764 refField->SetText( sym.ComponentRef.Designator );
765 loadSymbolFieldAttribute( sym.ComponentRef.AttrLoc, symOrient, sym.Mirror, refField );
766
767 if( sym.HasPartRef )
768 {
769 SCH_FIELD* partField = symbol->FindField( PartNameFieldName );
770
771 if( !partField )
772 {
773 int fieldID = symbol->GetFieldCount();
774 partField = symbol->AddField( SCH_FIELD( VECTOR2I(), fieldID, symbol,
776 }
777
778 wxASSERT( partField->GetName() == PartNameFieldName );
779
780 wxString partname = getPart( sym.PartRef.RefID ).Name;
781 partname.Replace( wxT( "\n" ), wxT( "\\n" ) );
782 partname.Replace( wxT( "\r" ), wxT( "\\r" ) );
783 partname.Replace( wxT( "\t" ), wxT( "\\t" ) );
784 partField->SetText( partname );
785
786 loadSymbolFieldAttribute( sym.PartRef.AttrLoc, symOrient, sym.Mirror, partField );
787
789 }
790
791 for( auto& attr : sym.AttributeValues )
792 {
793 ATTRIBUTE_VALUE attrVal = attr.second;
794
795 if( attrVal.HasLocation )
796 {
797 wxString attrName = getAttributeName( attrVal.AttributeID );
798 SCH_FIELD* attrField = symbol->FindField( attrName );
799
800 if( !attrField )
801 {
802 int fieldID = symbol->GetFieldCount();
803 attrField = symbol->AddField(
804 SCH_FIELD( VECTOR2I(), fieldID, symbol, attrName ) );
805 }
806
807 wxASSERT( attrField->GetName() == attrName );
808
809 attrVal.Value.Replace( wxT( "\n" ), wxT( "\\n" ) );
810 attrVal.Value.Replace( wxT( "\r" ), wxT( "\\r" ) );
811 attrVal.Value.Replace( wxT( "\t" ), wxT( "\\t" ) );
812 attrField->SetText( attrVal.Value );
813
814 loadSymbolFieldAttribute( attrVal.AttributeLocation, symOrient, sym.Mirror,
815 attrField );
816 attrField->SetVisible( isAttributeVisible( attrVal.AttributeID ) );
817 }
818 }
819 }
820 else if( sym.IsSymbolVariant )
821 {
823 {
824 THROW_IO_ERROR( wxString::Format(
825 _( "Symbol ID '%s' references library symbol '%s' which could not be "
826 "found in the library. Did you export all items of the design?" ),
827 sym.ID, sym.PartRef.RefID ) );
828 }
829
830 SYMDEF_SCM libSymDef = Library.SymbolDefinitions.at( sym.SymdefID );
831
832 if( libSymDef.Terminals.size() != 1 )
833 {
834 THROW_IO_ERROR( wxString::Format(
835 _( "Symbol ID '%s' is a signal reference or global signal but it has too "
836 "many pins. The expected number of pins is 1 but %d were found." ),
837 sym.ID, libSymDef.Terminals.size() ) );
838 }
839
840 if( sym.SymbolVariant.Type == SYMBOLVARIANT::TYPE::GLOBALSIGNAL )
841 {
842 SYMDEF_ID symID = sym.SymdefID;
843 LIB_SYMBOL* kiPart = nullptr;
844
845 // In CADSTAR "GlobalSignal" is a special type of symbol which defines
846 // a Power Symbol. The "Alternate" name defines the default net name of
847 // the power symbol but this can be overridden in the design itself.
848 wxString libraryNetName = Library.SymbolDefinitions.at( symID ).Alternate;
849
850 // Name of the net that the symbol instance in CADSTAR refers to:
851 wxString symbolInstanceNetName = sym.SymbolVariant.Reference;
852 symbolInstanceNetName = EscapeString( symbolInstanceNetName, CTX_LIBID );
853
854 // Name of the symbol we will use for saving the part in KiCad
855 // Note: In CADSTAR all power symbols will start have the reference name be
856 // "GLOBALSIGNAL" followed by the default net name, so it makes sense to save
857 // the symbol in KiCad as the default net name as well.
858 wxString libPartName = libraryNetName;
859
860 // In CADSTAR power symbol instances can refer to a different net to that defined
861 // in the library. This causes problems in KiCad v6 as it breaks connectivity when
862 // the user decides to update all symbols from library. We handle this by creating
863 // individual versions of the power symbol for each net name.
864 if( libPartName != symbolInstanceNetName )
865 {
866 libPartName += wxT( " (" ) + symbolInstanceNetName + wxT( ")" );
867 }
868
869 if( m_powerSymLibMap.find( libPartName ) == m_powerSymLibMap.end() )
870 {
871 const LIB_SYMBOL* templatePart = loadSymdef( symID );
872 wxCHECK( templatePart, /*void*/ );
873
874 kiPart = new LIB_SYMBOL( *templatePart );
875 kiPart->SetPower();
876 kiPart->SetName( libPartName );
877 kiPart->GetValueField().SetText( symbolInstanceNetName );
878 kiPart->SetShowPinNames( false );
879 kiPart->SetShowPinNumbers( false );
880
881 std::vector<SCH_PIN*> pins = kiPart->GetAllLibPins();
882 wxCHECK( pins.size() == 1, /*void*/ );
883
884 pins.at( 0 )->SetType( ELECTRICAL_PINTYPE::PT_POWER_IN );
885 pins.at( 0 )->SetName( symbolInstanceNetName );
886
887 if( libSymDef.TextLocations.find( SIGNALNAME_ORIGIN_ATTRID )
888 != libSymDef.TextLocations.end() )
889 {
890 TEXT_LOCATION& txtLoc =
892
893 VECTOR2I valPos = getKiCadLibraryPoint( txtLoc.Position, libSymDef.Origin );
894
895 kiPart->GetValueField().SetPosition( valPos );
896 kiPart->GetValueField().SetVisible( true );
897 }
898 else
899 {
900 kiPart->GetValueField().SetVisible( false );
901 }
902
903 kiPart->GetReferenceField().SetText( "#PWR" );
904 kiPart->GetReferenceField().SetVisible( false );
905 m_loadedSymbols.push_back( kiPart );
906 m_powerSymLibMap.insert( { libPartName, kiPart } );
907 }
908 else
909 {
910 kiPart = m_powerSymLibMap.at( libPartName );
911 wxASSERT( kiPart->GetValueField().GetText() == symbolInstanceNetName );
912 }
913
914 LIB_SYMBOL* scaledPart = getScaledLibPart( kiPart, sym.ScaleRatioNumerator,
916
917 EDA_ANGLE returnedOrient = ANGLE_0;
918 SCH_SYMBOL* symbol = loadSchematicSymbol( sym, *scaledPart, returnedOrient );
919 m_powerSymMap.insert( { sym.ID, symbol } );
920
921 delete scaledPart;
922 }
923 else if( sym.SymbolVariant.Type == SYMBOLVARIANT::TYPE::SIGNALREF )
924 {
925 // There should only be one pin and we'll use that to set the position
926 TERMINAL& symbolTerminal = libSymDef.Terminals.begin()->second;
927 VECTOR2I terminalPosOffset = symbolTerminal.Position - libSymDef.Origin;
928 EDA_ANGLE rotate = getAngle( sym.OrientAngle );
929
930 if( sym.Mirror )
931 rotate += ANGLE_180;
932
933 RotatePoint( terminalPosOffset, -rotate );
934
935 SCH_GLOBALLABEL* netLabel = new SCH_GLOBALLABEL;
936 netLabel->SetPosition( getKiCadPoint( (VECTOR2I)sym.Origin + terminalPosOffset ) );
937 netLabel->SetText( "***UNKNOWN NET****" ); // This should be later updated when we load the netlist
938 netLabel->SetTextSize( VECTOR2I( schIUScale.MilsToIU( 50 ), schIUScale.MilsToIU( 50 ) ) );
939
940 SYMDEF_SCM symbolDef = Library.SymbolDefinitions.at( sym.SymdefID );
941
942 if( symbolDef.TextLocations.count( LINK_ORIGIN_ATTRID ) )
943 {
944 TEXT_LOCATION linkOrigin = symbolDef.TextLocations.at( LINK_ORIGIN_ATTRID );
945 applyTextSettings( netLabel, linkOrigin.TextCodeID, linkOrigin.Alignment,
946 linkOrigin.Justification );
947 }
948
949 netLabel->SetSpinStyle( getSpinStyle( sym.OrientAngle, sym.Mirror ) );
950
951 if( libSymDef.Alternate.Lower().Contains( "in" ) )
952 netLabel->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
953 else if( libSymDef.Alternate.Lower().Contains( "bi" ) )
954 netLabel->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
955 else if( libSymDef.Alternate.Lower().Contains( "out" ) )
956 netLabel->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
957 else
958 netLabel->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
959
960 SCH_SCREEN* screen = m_sheetMap.at( sym.LayerID )->GetScreen();
961
962 // autoplace intersheet refs
963 netLabel->AutoplaceFields( screen, false );
964
965 screen->Append( netLabel );
966 m_globalLabelsMap.insert( { sym.ID, netLabel } );
967 }
968 else
969 {
970 wxASSERT_MSG( false, "Unknown Symbol Variant." );
971 }
972 }
973 else
974 {
975 m_reporter->Report( wxString::Format( _( "Symbol ID '%s' is of an unknown type. It is "
976 "neither a symbol or a net power / symbol. "
977 "The symbol was not loaded." ),
978 sym.ID ),
980 }
981
982 if( sym.ScaleRatioDenominator != 1 || sym.ScaleRatioNumerator != 1 )
983 {
984 wxString symbolName = sym.ComponentRef.Designator;
985
986 if( symbolName.empty() )
987 symbolName = wxString::Format( "ID: %s", sym.ID );
988 else
989 symbolName += sym.GateID;
990
991 m_reporter->Report( wxString::Format( _( "Symbol '%s' is scaled in the original "
992 "CADSTAR schematic but this is not supported "
993 "in KiCad. When the symbol is reloaded from "
994 "the library, it will revert to the original "
995 "1:1 scale." ),
996 symbolName,
997 sym.PartRef.RefID ),
999 }
1000 }
1001}
1002
1003
1005{
1006 for( std::pair<BUS_ID, BUS> busPair : Schematic.Buses )
1007 {
1008 BUS bus = busPair.second;
1009 bool firstPt = true;
1010 VERTEX last;
1011
1012 if( bus.LayerID != wxT( "NO_SHEET" ) )
1013 {
1014 SCH_SCREEN* screen = m_sheetMap.at( bus.LayerID )->GetScreen();
1015 std::shared_ptr<BUS_ALIAS> kiBusAlias = std::make_shared<BUS_ALIAS>();
1016
1017 kiBusAlias->SetName( bus.Name );
1018 kiBusAlias->SetParent( screen );
1019 screen->AddBusAlias( kiBusAlias );
1020 m_busesMap.insert( { bus.ID, kiBusAlias } );
1021
1022 SCH_LABEL* label = new SCH_LABEL();
1023
1024 wxString busname = HandleTextOverbar( bus.Name );
1025
1026 label->SetText( wxT( "{" ) + busname + wxT( "}" ) );
1027 label->SetVisible( true );
1028 screen->Append( label );
1029
1030 SHAPE_LINE_CHAIN busLineChain; // to compute nearest segment to bus label
1031
1032 for( const VERTEX& cur : bus.Shape.Vertices )
1033 {
1034 busLineChain.Append( getKiCadPoint( cur.End ) );
1035
1036 if( firstPt )
1037 {
1038 last = cur;
1039 firstPt = false;
1040
1041 if( !bus.HasBusLabel )
1042 {
1043 // Add a bus label on the starting point if the original CADSTAR design
1044 // does not have an explicit label
1045 label->SetPosition( getKiCadPoint( last.End ) );
1046 }
1047
1048 continue;
1049 }
1050
1051
1052 SCH_LINE* kiBus = new SCH_LINE();
1053
1054 kiBus->SetStartPoint( getKiCadPoint( last.End ) );
1055 kiBus->SetEndPoint( getKiCadPoint( cur.End ) );
1056 kiBus->SetLayer( LAYER_BUS );
1057 kiBus->SetLineWidth( getLineThickness( bus.LineCodeID ) );
1058 screen->Append( kiBus );
1059
1060 last = cur;
1061 }
1062
1063 if( bus.HasBusLabel )
1064 {
1065 //lets find the closest point in the busline to the label
1066 VECTOR2I busLabelLoc = getKiCadPoint( bus.BusLabel.Position );
1067 VECTOR2I nearestPt = busLineChain.NearestPoint( busLabelLoc );
1068
1069 label->SetPosition( nearestPt );
1070
1072 bus.BusLabel.Justification );
1073
1074 // Re-set bus name as it might have been "double-escaped" after applyTextSettings
1075 label->SetText( wxT( "{" ) + busname + wxT( "}" ) );
1076
1077 // Note orientation of the bus label will be determined in loadNets
1078 // (the position of the wire will determine how best to place the bus label)
1079 }
1080 }
1081 }
1082}
1083
1084
1086{
1087 for( std::pair<NET_ID, NET_SCH> netPair : Schematic.Nets )
1088 {
1089 NET_SCH net = netPair.second;
1090 wxString netName = net.Name;
1091 std::map<NETELEMENT_ID, SCH_LABEL*> netlabels;
1092
1093 if( netName.IsEmpty() )
1094 netName = wxString::Format( "$%ld", net.SignalNum );
1095
1096 netName = HandleTextOverbar( netName );
1097
1098 for( std::pair<NETELEMENT_ID, NET_SCH::SYM_TERM> terminalPair : net.Terminals )
1099 {
1100 NET_SCH::SYM_TERM netTerm = terminalPair.second;
1101
1102 if( m_powerSymMap.find( netTerm.SymbolID ) != m_powerSymMap.end() )
1103 {
1104 SCH_FIELD* val = m_powerSymMap.at( netTerm.SymbolID )->GetField( VALUE_FIELD );
1105 val->SetText( netName );
1106 val->SetBold( false );
1107 val->SetVisible( false );
1108
1109 if( netTerm.HasNetLabel )
1110 {
1111 val->SetVisible( true );
1112 val->SetPosition( getKiCadPoint( netTerm.NetLabel.Position ) );
1113
1114 applyTextSettings( val, netTerm.NetLabel.TextCodeID, netTerm.NetLabel.Alignment,
1115 netTerm.NetLabel.Justification, netTerm.NetLabel.OrientAngle,
1116 netTerm.NetLabel.Mirror );
1117 }
1118 }
1119 else if( m_globalLabelsMap.find( netTerm.SymbolID ) != m_globalLabelsMap.end() )
1120 {
1121 m_globalLabelsMap.at( netTerm.SymbolID )->SetText( netName );
1122
1123 LAYER_ID sheet = Schematic.Symbols.at( netTerm.SymbolID ).LayerID;
1124
1125 if( m_sheetMap.count( sheet ) )
1126 {
1127 SCH_SCREEN* screen = m_sheetMap.at( sheet )->GetScreen();
1128
1129 // autoplace intersheet refs again since we've changed the name
1130 m_globalLabelsMap.at( netTerm.SymbolID )->AutoplaceFields( screen, false );
1131 }
1132 }
1133 else if( !net.Name.IsEmpty() && Schematic.Symbols.count( netTerm.SymbolID )
1134 && netTerm.HasNetLabel )
1135 {
1136 // This is a named net that connects to a schematic symbol pin - we need to put a label
1137 SCH_LABEL* label = new SCH_LABEL();
1138 label->SetText( netName );
1139
1140 POINT pinLocation = getLocationOfNetElement( net, netTerm.ID );
1141 label->SetPosition( getKiCadPoint( pinLocation ) );
1142 label->SetVisible( true );
1143
1144 applyTextSettings( label, netTerm.NetLabel.TextCodeID, netTerm.NetLabel.Alignment,
1145 netTerm.NetLabel.Justification );
1146
1147 netlabels.insert( { netTerm.ID, label } );
1148
1149 LAYER_ID sheet = Schematic.Symbols.at( netTerm.SymbolID ).LayerID;
1150 m_sheetMap.at( sheet )->GetScreen()->Append( label );
1151 }
1152 }
1153
1154 auto getHierarchicalLabel =
1155 [&]( NETELEMENT_ID aNode ) -> SCH_HIERLABEL*
1156 {
1157 if( aNode.Contains( "BLKT" ) )
1158 {
1159 NET_SCH::BLOCK_TERM blockTerm = net.BlockTerminals.at( aNode );
1160 BLOCK_PIN_ID blockPinID = std::make_pair( blockTerm.BlockID,
1161 blockTerm.TerminalID );
1162
1163 if( m_sheetPinMap.find( blockPinID ) != m_sheetPinMap.end() )
1164 return m_sheetPinMap.at( blockPinID );
1165 }
1166
1167 return nullptr;
1168 };
1169
1170 //Add net name to all hierarchical pins (block terminals in CADSTAR)
1171 for( std::pair<NETELEMENT_ID, NET_SCH::BLOCK_TERM> blockPair : net.BlockTerminals )
1172 {
1173 SCH_HIERLABEL* label = getHierarchicalLabel( blockPair.first );
1174
1175 if( label )
1176 label->SetText( netName );
1177 }
1178
1179 // Load all bus entries and add net label if required
1180 for( std::pair<NETELEMENT_ID, NET_SCH::BUS_TERM> busPair : net.BusTerminals )
1181 {
1182 NET_SCH::BUS_TERM busTerm = busPair.second;
1183 BUS bus = Schematic.Buses.at( busTerm.BusID );
1184
1185 if( !alg::contains( m_busesMap.at( bus.ID )->Members(), netName ) )
1186 m_busesMap.at( bus.ID )->Members().emplace_back( netName );
1187
1188 SCH_BUS_WIRE_ENTRY* busEntry =
1189 new SCH_BUS_WIRE_ENTRY( getKiCadPoint( busTerm.FirstPoint ), false );
1190
1191 VECTOR2I size =
1192 getKiCadPoint( busTerm.SecondPoint ) - getKiCadPoint( busTerm.FirstPoint );
1193 busEntry->SetSize( VECTOR2I( size.x, size.y ) );
1194
1195 m_sheetMap.at( bus.LayerID )->GetScreen()->Append( busEntry );
1196
1197 // Always add a label at bus terminals to ensure connectivity.
1198 // If the original design does not have a label, just make it very small
1199 // to keep connectivity but make the design look visually similar to
1200 // the original.
1201 SCH_LABEL* label = new SCH_LABEL();
1202 label->SetText( netName );
1203 label->SetPosition( getKiCadPoint( busTerm.SecondPoint ) );
1204 label->SetVisible( true );
1205
1206 if( busTerm.HasNetLabel )
1207 {
1208 applyTextSettings( label, busTerm.NetLabel.TextCodeID, busTerm.NetLabel.Alignment,
1209 busTerm.NetLabel.Justification );
1210 }
1211 else
1212 {
1214 }
1215
1216 netlabels.insert( { busTerm.ID, label } );
1217 m_sheetMap.at( bus.LayerID )->GetScreen()->Append( label );
1218 }
1219
1220 for( std::pair<NETELEMENT_ID, NET_SCH::DANGLER> danglerPair : net.Danglers )
1221 {
1222 NET_SCH::DANGLER dangler = danglerPair.second;
1223
1224 SCH_LABEL* label = new SCH_LABEL();
1225 label->SetPosition( getKiCadPoint( dangler.Position ) );
1226 label->SetVisible( true );
1227
1228 if( dangler.HasNetLabel )
1229 {
1230 applyTextSettings( label, dangler.NetLabel.TextCodeID, dangler.NetLabel.Alignment,
1231 dangler.NetLabel.Justification );
1232 }
1233
1234 label->SetText( netName ); // set text after applying settings to avoid double-escaping
1235 netlabels.insert( { dangler.ID, label } );
1236
1237 m_sheetMap.at( dangler.LayerID )->GetScreen()->Append( label );
1238 }
1239
1240 for( NET_SCH::CONNECTION_SCH conn : net.Connections )
1241 {
1242 if( conn.LayerID == wxT( "NO_SHEET" ) )
1243 continue; // No point loading virtual connections. KiCad handles that internally
1244
1245 POINT start = getLocationOfNetElement( net, conn.StartNode );
1246 POINT end = getLocationOfNetElement( net, conn.EndNode );
1247
1248 if( start.x == UNDEFINED_VALUE || end.x == UNDEFINED_VALUE )
1249 continue;
1250
1251 // Connections in CADSTAR are always implied between symbols even if the route
1252 // doesn't start and end exactly at the connection points
1253 if( conn.Path.size() < 1 || conn.Path.front() != start )
1254 conn.Path.insert( conn.Path.begin(), start );
1255
1256 if( conn.Path.size() < 2 || conn.Path.back() != end )
1257 conn.Path.push_back( end );
1258
1259 bool firstPt = true;
1260 bool secondPt = false;
1261 VECTOR2I last;
1262 SCH_LINE* wire = nullptr;
1263
1264 SHAPE_LINE_CHAIN wireChain; // Create a temp. line chain representing the connection
1265
1266 for( POINT pt : conn.Path )
1267 {
1268 wireChain.Append( getKiCadPoint( pt ) );
1269 }
1270
1271 // AUTO-FIX SHEET PINS
1272 //--------------------
1273 // KiCad constrains the sheet pin on the edge of the sheet object whereas in
1274 // CADSTAR it can be anywhere. Let's find the intersection of the wires with the sheet
1275 // and place the hierarchical
1276 std::vector<NETELEMENT_ID> nodes;
1277 nodes.push_back( conn.StartNode );
1278 nodes.push_back( conn.EndNode );
1279
1280 for( NETELEMENT_ID node : nodes )
1281 {
1282 SCH_HIERLABEL* sheetPin = getHierarchicalLabel( node );
1283
1284 if( sheetPin )
1285 {
1286 if( sheetPin->Type() == SCH_SHEET_PIN_T
1287 && SCH_SHEET::ClassOf( sheetPin->GetParent() ) )
1288 {
1289 SCH_SHEET* parentSheet = static_cast<SCH_SHEET*>( sheetPin->GetParent() );
1290 VECTOR2I sheetSize = parentSheet->GetSize();
1291 VECTOR2I sheetPosition = parentSheet->GetPosition();
1292
1293 int leftSide = sheetPosition.x;
1294 int rightSide = sheetPosition.x + sheetSize.x;
1295 int topSide = sheetPosition.y;
1296 int botSide = sheetPosition.y + sheetSize.y;
1297
1298 SHAPE_LINE_CHAIN sheetEdge;
1299
1300 sheetEdge.Append( leftSide, topSide );
1301 sheetEdge.Append( rightSide, topSide );
1302 sheetEdge.Append( rightSide, botSide );
1303 sheetEdge.Append( leftSide, botSide );
1304 sheetEdge.Append( leftSide, topSide );
1305
1306 SHAPE_LINE_CHAIN::INTERSECTIONS wireToSheetIntersects;
1307
1308 if( !wireChain.Intersect( sheetEdge, wireToSheetIntersects ) )
1309 {
1310 // The block terminal is outside the block shape in the original
1311 // CADSTAR design. Since KiCad's Sheet Pin will already be constrained
1312 // on the edge, we will simply join to it with a straight line.
1313 if( node == conn.StartNode )
1314 wireChain = wireChain.Reverse();
1315
1316 wireChain.Append( sheetPin->GetPosition() );
1317
1318 if( node == conn.StartNode )
1319 wireChain = wireChain.Reverse();
1320 }
1321 else
1322 {
1323 // The block terminal is either inside or on the shape edge. Lets use
1324 // the first intersection point.
1325 VECTOR2I intsctPt = wireToSheetIntersects.at( 0 ).p;
1326 int intsctIndx = wireChain.FindSegment( intsctPt );
1327 wxASSERT_MSG( intsctIndx != -1, "Can't find intersecting segment" );
1328
1329 if( node == conn.StartNode )
1330 wireChain.Replace( 0, intsctIndx, intsctPt );
1331 else
1332 wireChain.Replace( intsctIndx + 1, /*end index*/ -1, intsctPt );
1333
1334 sheetPin->SetPosition( intsctPt );
1335 }
1336 }
1337 }
1338 }
1339
1340 auto fixNetLabelsAndSheetPins =
1341 [&]( const EDA_ANGLE& aWireAngle, NETELEMENT_ID& aNetEleID )
1342 {
1343 SPIN_STYLE spin = getSpinStyle( aWireAngle );
1344
1345 if( netlabels.find( aNetEleID ) != netlabels.end() )
1346 netlabels.at( aNetEleID )->SetSpinStyle( spin.MirrorY() );
1347
1348 SCH_HIERLABEL* sheetPin = getHierarchicalLabel( aNetEleID );
1349
1350 if( sheetPin )
1351 sheetPin->SetSpinStyle( spin.MirrorX() );
1352 };
1353
1354 // Now we can load the wires and fix the label orientations
1355 for( const VECTOR2I& pt : wireChain.CPoints() )
1356 {
1357 if( firstPt )
1358 {
1359 last = pt;
1360 firstPt = false;
1361 secondPt = true;
1362 continue;
1363 }
1364
1365 if( secondPt )
1366 {
1367 secondPt = false;
1368
1369 EDA_ANGLE wireAngle( last - pt );
1370 fixNetLabelsAndSheetPins( wireAngle, conn.StartNode );
1371 }
1372
1373 wire = new SCH_LINE();
1374
1375 wire->SetStartPoint( last );
1376 wire->SetEndPoint( pt );
1377 wire->SetLayer( LAYER_WIRE );
1378
1379 if( !conn.ConnectionLineCode.IsEmpty() )
1380 wire->SetLineWidth( getLineThickness( conn.ConnectionLineCode ) );
1381
1382 last = pt;
1383
1384 m_sheetMap.at( conn.LayerID )->GetScreen()->Append( wire );
1385 }
1386
1387 //Fix labels on the end wire
1388 if( wire )
1389 {
1390 EDA_ANGLE wireAngle( wire->GetEndPoint() - wire->GetStartPoint() );
1391 fixNetLabelsAndSheetPins( wireAngle, conn.EndNode );
1392 }
1393 }
1394
1395 for( std::pair<NETELEMENT_ID, NET_SCH::JUNCTION_SCH> juncPair : net.Junctions )
1396 {
1397 NET_SCH::JUNCTION_SCH junc = juncPair.second;
1398
1399 SCH_JUNCTION* kiJunc = new SCH_JUNCTION();
1400
1401 kiJunc->SetPosition( getKiCadPoint( junc.Location ) );
1402 m_sheetMap.at( junc.LayerID )->GetScreen()->Append( kiJunc );
1403
1404 if( junc.HasNetLabel )
1405 {
1406 // In CADSTAR the label can be placed anywhere, but in KiCad it has to be placed
1407 // in the same location as the junction for it to be connected to it.
1408 SCH_LABEL* label = new SCH_LABEL();
1409 label->SetText( netName );
1410 label->SetPosition( getKiCadPoint( junc.Location ) );
1411 label->SetVisible( true );
1412
1413 EDA_ANGLE labelAngle = getAngle( junc.NetLabel.OrientAngle );
1414 SPIN_STYLE spin = getSpinStyle( labelAngle );
1415
1416 label->SetSpinStyle( spin );
1417
1418 m_sheetMap.at( junc.LayerID )->GetScreen()->Append( label );
1419 }
1420 }
1421 }
1422}
1423
1424
1426{
1427 for( std::pair<FIGURE_ID, FIGURE> figPair : Schematic.Figures )
1428 {
1429 FIGURE fig = figPair.second;
1430
1431 loadFigure( fig, fig.LayerID, LAYER_NOTES );
1432 }
1433}
1434
1435
1437{
1438 for( std::pair<TEXT_ID, TEXT> textPair : Schematic.Texts )
1439 {
1440 TEXT txt = textPair.second;
1441
1442 SCH_TEXT* kiTxt = getKiCadSchText( txt );
1443 loadItemOntoKiCadSheet( txt.LayerID, kiTxt );
1444 }
1445}
1446
1447
1449{
1450 for( std::pair<DOCUMENTATION_SYMBOL_ID, DOCUMENTATION_SYMBOL> docSymPair :
1452 {
1453 DOCUMENTATION_SYMBOL docSym = docSymPair.second;
1454
1455 if( Library.SymbolDefinitions.find( docSym.SymdefID ) == Library.SymbolDefinitions.end() )
1456 {
1457 m_reporter->Report( wxString::Format( _( "Documentation Symbol '%s' refers to symbol "
1458 "definition ID '%s' which does not exist in "
1459 "the library. The symbol was not loaded." ),
1460 docSym.ID,
1461 docSym.SymdefID ),
1463 continue;
1464 }
1465
1466 SYMDEF_SCM docSymDef = Library.SymbolDefinitions.at( docSym.SymdefID );
1467 VECTOR2I moveVector = getKiCadPoint( docSym.Origin ) - getKiCadPoint( docSymDef.Origin );
1468 EDA_ANGLE rotationAngle = getAngle( docSym.OrientAngle );
1469 double scalingFactor = (double) docSym.ScaleRatioNumerator
1470 / (double) docSym.ScaleRatioDenominator;
1471 VECTOR2I centreOfTransform = getKiCadPoint( docSymDef.Origin );
1472 bool mirrorInvert = docSym.Mirror;
1473
1474 for( std::pair<FIGURE_ID, FIGURE> figPair : docSymDef.Figures )
1475 {
1476 FIGURE fig = figPair.second;
1477
1478 loadFigure( fig, docSym.LayerID, LAYER_NOTES, moveVector, rotationAngle, scalingFactor,
1479 centreOfTransform, mirrorInvert );
1480 }
1481
1482 for( std::pair<TEXT_ID, TEXT> textPair : docSymDef.Texts )
1483 {
1484 TEXT txt = textPair.second;
1485
1486 txt.Mirror = ( txt.Mirror ) ? !mirrorInvert : mirrorInvert;
1487 txt.OrientAngle = docSym.OrientAngle - txt.OrientAngle;
1488
1489 SCH_TEXT* kiTxt = getKiCadSchText( txt );
1490
1491 VECTOR2I newPosition = applyTransform( kiTxt->GetPosition(), moveVector, rotationAngle,
1492 scalingFactor, centreOfTransform, mirrorInvert );
1493
1494 int newTxtWidth = KiROUND( kiTxt->GetTextWidth() * scalingFactor );
1495 int newTxtHeight = KiROUND( kiTxt->GetTextHeight() * scalingFactor );
1496 int newTxtThickness = KiROUND( kiTxt->GetTextThickness() * scalingFactor );
1497
1498 kiTxt->SetPosition( newPosition );
1499 kiTxt->SetTextWidth( newTxtWidth );
1500 kiTxt->SetTextHeight( newTxtHeight );
1501 kiTxt->SetTextThickness( newTxtThickness );
1502
1503 loadItemOntoKiCadSheet( docSym.LayerID, kiTxt );
1504 }
1505 }
1506}
1507
1508
1510{
1511 auto findAndReplaceTextField =
1512 [&]( TEXT_FIELD_NAME aField, wxString aValue )
1513 {
1514 if( m_context.TextFieldToValuesMap.find( aField ) != m_context.TextFieldToValuesMap.end() )
1515 {
1516 if( m_context.TextFieldToValuesMap.at( aField ) != aValue )
1517 {
1518 m_context.TextFieldToValuesMap.at( aField ) = aValue;
1519 m_context.InconsistentTextFields.insert( aField );
1520 return false;
1521 }
1522 }
1523 else
1524 {
1525 m_context.TextFieldToValuesMap.insert( { aField, aValue } );
1526 }
1527
1528 return true;
1529 };
1530
1531 PROJECT* pj = &m_schematic->Prj();
1532
1533 if( pj )
1534 {
1535 std::map<wxString, wxString>& txtVars = pj->GetTextVars();
1536
1537 // Most of the design text fields can be derived from other elements
1538 if( Schematic.VariantHierarchy.Variants.size() > 0 )
1539 {
1540 VARIANT loadedVar = Schematic.VariantHierarchy.Variants.begin()->second;
1541
1542 findAndReplaceTextField( TEXT_FIELD_NAME::VARIANT_NAME, loadedVar.Name );
1543 findAndReplaceTextField( TEXT_FIELD_NAME::VARIANT_DESCRIPTION, loadedVar.Description );
1544 }
1545
1546 findAndReplaceTextField( TEXT_FIELD_NAME::DESIGN_TITLE, Header.JobTitle );
1547
1548 for( std::pair<TEXT_FIELD_NAME, wxString> txtvalue : m_context.TextFieldToValuesMap )
1549 {
1550 wxString varName = CADSTAR_TO_KICAD_FIELDS.at( txtvalue.first );
1551 wxString varValue = txtvalue.second;
1552
1553 txtVars.insert( { varName, varValue } );
1554 }
1555
1556 for( std::pair<wxString, wxString> txtvalue : m_context.FilenamesToTextMap )
1557 {
1558 wxString varName = txtvalue.first;
1559 wxString varValue = txtvalue.second;
1560
1561 txtVars.insert( { varName, varValue } );
1562 }
1563 }
1564 else
1565 {
1566 m_reporter->Report( _( "Text Variables could not be set as there is no project attached." ),
1568 }
1569}
1570
1571
1572SCH_FIELD*
1574 std::unique_ptr<LIB_SYMBOL>& aKiCadSymbol )
1575{
1576 // First Check if field already exists
1577 SCH_FIELD* existingField = aKiCadSymbol->FindField( aFieldName );
1578
1579 if( existingField != nullptr )
1580 return existingField;
1581
1582 int newfieldID = aKiCadSymbol->GetFieldCount();
1583 SCH_FIELD* newfield = new SCH_FIELD( aKiCadSymbol.get(), newfieldID );
1584 newfield->SetName( aFieldName );
1585 newfield->SetVisible( false );
1586 aKiCadSymbol->AddField( newfield );
1587 /*
1588 @todo we should load that a field is a URL by checking if it starts with "Link"
1589 e.g.:
1590 if( aFieldName.Lower().StartsWith( "link" ) )
1591 newfield->SetAsURL*/
1592
1593 return newfield;
1594}
1595
1596
1598{
1599 wxCHECK( Library.SymbolDefinitions.find( aSymdefID ) != Library.SymbolDefinitions.end(), nullptr );
1600
1601 if( m_symDefMap.count( aSymdefID ) )
1602 return m_symDefMap.at( aSymdefID ).get(); // return a non-owning ptr
1603
1604 SYMDEF_SCM csSym = Library.SymbolDefinitions.at( aSymdefID );
1605 std::unique_ptr<LIB_SYMBOL> kiSym = std::make_unique<LIB_SYMBOL>( csSym.BuildLibName() );
1606 const int gateNumber = 1; // Always load to gate "A" - we will change the unit later
1607
1608 // Load Graphical Figures
1609 for( std::pair<FIGURE_ID, FIGURE> figPair : csSym.Figures )
1610 {
1611 FIGURE fig = figPair.second;
1612 int lineThickness = getLineThickness( fig.LineCodeID );
1613 LINE_STYLE linestyle = getLineStyle( fig.LineCodeID );
1614
1615 if( fig.Shape.Type == SHAPE_TYPE::OPENSHAPE )
1616 {
1617 loadLibrarySymbolShapeVertices( fig.Shape.Vertices, csSym.Origin, kiSym.get(),
1618 gateNumber,
1619 lineThickness );
1620 }
1621 else
1622 {
1623 SCH_SHAPE* shape = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE );
1624
1626 [&]( const VECTOR2I& aPt )
1627 {
1628 return getKiCadLibraryPoint( aPt, csSym.Origin );
1629 },
1630 ARC_ACCURACY ) );
1631
1632 shape->SetUnit( gateNumber );
1633
1634 shape->SetStroke( STROKE_PARAMS( lineThickness, linestyle ) );
1635
1636 if( fig.Shape.Type == SHAPE_TYPE::SOLID )
1637 shape->SetFillMode( FILL_T::FILLED_SHAPE );
1638 else if( fig.Shape.Type == SHAPE_TYPE::OUTLINE )
1639 shape->SetFillMode( FILL_T::NO_FILL );
1640 else if( fig.Shape.Type == SHAPE_TYPE::HATCHED ) // We don't have an equivalent
1641 shape->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
1642
1643 kiSym->AddDrawItem( shape );
1644 }
1645 }
1646
1647 PINNUM_TO_TERMINAL_MAP pinNumToTerminals;
1648
1649 // Load Pins
1650 for( std::pair<TERMINAL_ID, TERMINAL> termPair : csSym.Terminals )
1651 {
1652 TERMINAL term = termPair.second;
1653 wxString pinNum = wxString::Format( "%ld", term.ID );
1654 wxString pinName = wxEmptyString;
1655 std::unique_ptr<SCH_PIN> pin = std::make_unique<SCH_PIN>( kiSym.get() );
1656
1657 // Assume passive pin for now (we will set it later once we load the parts)
1658 pin->SetType( ELECTRICAL_PINTYPE::PT_PASSIVE );
1659
1660 pin->SetPosition( getKiCadLibraryPoint( term.Position, csSym.Origin ) );
1661 pin->SetLength( 0 ); //CADSTAR Pins are just a point (have no length)
1662 pin->SetShape( GRAPHIC_PINSHAPE::LINE );
1663 pin->SetUnit( gateNumber );
1664 pin->SetNumber( pinNum );
1665 pin->SetName( pinName );
1666
1667 // TC0 is the default CADSTAR text size for name/number if none specified
1668 int pinNumberHeight = getTextHeightFromTextCode( wxT( "TC0" ) );
1669 int pinNameHeight = getTextHeightFromTextCode( wxT( "TC0" ) );
1670
1671 if( csSym.PinNumberLocations.count( term.ID ) )
1672 {
1673 PIN_NUM_LABEL_LOC pinNumLocation = csSym.PinNumberLocations.at( term.ID );
1674 pinNumberHeight = getTextHeightFromTextCode( pinNumLocation.TextCodeID );
1675 }
1676
1677 if( csSym.PinLabelLocations.count( term.ID ) )
1678 {
1679 PIN_NUM_LABEL_LOC pinNameLocation = csSym.PinLabelLocations.at( term.ID );
1680 pinNameHeight = getTextHeightFromTextCode( pinNameLocation.TextCodeID );
1681 }
1682
1683 pin->SetNumberTextSize( pinNumberHeight );
1684 pin->SetNameTextSize( pinNameHeight );
1685
1686 pinNumToTerminals.insert( { pin->GetNumber(), term.ID } );
1687 kiSym->AddDrawItem( pin.release() );
1688 }
1689
1690 m_symDefTerminalsMap.insert( { aSymdefID, pinNumToTerminals } );
1691 fixUpLibraryPins( kiSym.get(), gateNumber );
1692
1693
1694 // Load Text items
1695 for( std::pair<TEXT_ID, TEXT> textPair : csSym.Texts )
1696 {
1697 TEXT csText = textPair.second;
1698 VECTOR2I pos = getKiCadLibraryPoint( csText.Position, csSym.Origin );
1699 auto libtext = std::make_unique<SCH_TEXT>( pos, csText.Text, LAYER_DEVICE );
1700
1701 libtext->SetUnit( gateNumber );
1702 libtext->SetPosition( getKiCadLibraryPoint( csText.Position, csSym.Origin ) );
1703 libtext->SetMultilineAllowed( true ); // temporarily so that we calculate bbox correctly
1704
1705 applyTextSettings( libtext.get(), csText.TextCodeID, csText.Alignment, csText.Justification,
1706 csText.OrientAngle, csText.Mirror, true );
1707
1708 // Split out multi line text items into individual text elements
1709 if( csText.Text.Contains( "\n" ) )
1710 {
1711 wxArrayString strings;
1712 wxStringSplit( csText.Text, strings, '\n' );
1713 wxPoint firstLinePos;
1714
1715 for( size_t ii = 0; ii < strings.size(); ++ii )
1716 {
1717 BOX2I bbox = libtext->GetTextBox( ii, true );
1718 VECTOR2I linePos = { bbox.GetLeft(), -bbox.GetBottom() };
1719
1720 RotatePoint( linePos, libtext->GetTextPos(), -libtext->GetTextAngle() );
1721
1722 SCH_TEXT* textLine = static_cast<SCH_TEXT*>( libtext->Duplicate() );
1723 textLine->SetText( strings[ii] );
1726 textLine->SetTextPos( linePos );
1727
1728 // Multiline text not allowed in LIB_TEXT
1729 textLine->SetMultilineAllowed( false );
1730 kiSym->AddDrawItem( textLine );
1731 }
1732 }
1733 else
1734 {
1735 // Multiline text not allowed in LIB_TEXT
1736 libtext->SetMultilineAllowed( false );
1737 kiSym->AddDrawItem( libtext.release() );
1738 }
1739 }
1740
1741 // CADSTAR uses TC1 when fields don't have explicit text/attribute location
1742 static const TEXTCODE_ID defaultTextCode = "TC1";
1743
1744 // Load field locations (Attributes in CADSTAR)
1745
1746 // Symbol name (e.g. R1)
1747 if( csSym.TextLocations.count( SYMBOL_NAME_ATTRID ) )
1748 {
1749 TEXT_LOCATION& textLoc = csSym.TextLocations.at( SYMBOL_NAME_ATTRID );
1750 applyToLibraryFieldAttribute( textLoc, csSym.Origin, &kiSym->GetReferenceField() );
1751 }
1752 else
1753 {
1754 applyTextCodeIfExists( &kiSym->GetReferenceField(), defaultTextCode );
1755 }
1756
1757 // Always add the part name field (even if it doesn't have a specific location defined)
1758 SCH_FIELD* partField = addNewFieldToSymbol( PartNameFieldName, kiSym );
1759 wxCHECK( partField, nullptr );
1760 wxASSERT( partField->GetName() == PartNameFieldName );
1761
1762 if( csSym.TextLocations.count( PART_NAME_ATTRID ) )
1763 {
1764 TEXT_LOCATION& textLoc = csSym.TextLocations.at( PART_NAME_ATTRID );
1765 applyToLibraryFieldAttribute( textLoc, csSym.Origin, partField );
1766 }
1767 else
1768 {
1769 applyTextCodeIfExists( partField, defaultTextCode );
1770 }
1771
1773
1774
1775 for( auto& [attributeId, textLocation] : csSym.TextLocations )
1776 {
1777 if( attributeId == PART_NAME_ATTRID || attributeId == SYMBOL_NAME_ATTRID
1778 || attributeId == SIGNALNAME_ORIGIN_ATTRID || attributeId == LINK_ORIGIN_ATTRID )
1779 {
1780 continue;
1781 }
1782
1783 wxString attributeName = getAttributeName( attributeId );
1784 SCH_FIELD* field = addNewFieldToSymbol( attributeName, kiSym );
1785 applyToLibraryFieldAttribute( textLocation, csSym.Origin, field );
1786 }
1787
1788
1789 for( auto& [attributeId, attrValue] : csSym.AttributeValues )
1790 {
1791 if( attributeId == PART_NAME_ATTRID || attributeId == SYMBOL_NAME_ATTRID
1792 || attributeId == SIGNALNAME_ORIGIN_ATTRID || attributeId == LINK_ORIGIN_ATTRID )
1793 {
1794 continue;
1795 }
1796
1797 wxString attributeName = getAttributeName( attributeId );
1798 SCH_FIELD* field = addNewFieldToSymbol( attributeName, kiSym );
1799
1800 if( attrValue.HasLocation )
1801 applyToLibraryFieldAttribute( attrValue.AttributeLocation, csSym.Origin, field );
1802 else
1803 applyTextCodeIfExists( field, defaultTextCode );
1804 }
1805
1806
1807 m_symDefMap.insert( { aSymdefID, std::move( kiSym ) } );
1808
1809 return m_symDefMap.at( aSymdefID ).get(); // return a non-owning ptr
1810}
1811
1812
1814 const PART& aCadstarPart,
1815 const GATE_ID& aGateID,
1816 LIB_SYMBOL* aSymbol )
1817{
1818 wxCHECK( Library.SymbolDefinitions.find( aSymdefID ) != Library.SymbolDefinitions.end(), /*void*/ );
1819
1820 std::unique_ptr<LIB_SYMBOL> kiSymDef( loadSymdef( aSymdefID )->Duplicate() );
1821 wxCHECK( kiSymDef, /*void*/ );
1822
1823 //todo: need to use unique_ptr more. For now just create it here and release at end of function
1824 std::unique_ptr<LIB_SYMBOL> tempSymbol( aSymbol );
1825
1826 // Update the pin numbers to match those defined in the Cadstar part
1827 TERMINAL_TO_PINNUM_MAP pinNumMap;
1828
1829 for( auto&& [storedPinNum, termID] : m_symDefTerminalsMap[aSymdefID] )
1830 {
1831 PART::DEFINITION::PIN csPin = getPartDefinitionPin( aCadstarPart, aGateID, termID );
1832 SCH_PIN* pin = kiSymDef->GetPin( storedPinNum );
1833
1834 wxString pinName = HandleTextOverbar( csPin.Label );
1835 wxString pinNum = HandleTextOverbar( csPin.Name );
1836
1837 if( pinNum.IsEmpty() )
1838 {
1839 if( !csPin.Identifier.IsEmpty() )
1840 pinNum = csPin.Identifier;
1841 else if( csPin.ID == UNDEFINED_VALUE )
1842 pinNum = wxString::Format( "%ld", termID );
1843 else
1844 pinNum = wxString::Format( "%ld", csPin.ID );
1845 }
1846
1847 pin->SetType( getKiCadPinType( csPin.Type ) );
1848 pin->SetNumber( pinNum );
1849 pin->SetName( pinName );
1850
1851 pinNumMap.insert( { termID, pinNum } );
1852 }
1853
1854 m_pinNumsMap.insert( { aCadstarPart.ID + aGateID, pinNumMap } );
1855
1856 // COPY ITEMS
1857 int gateNumber = getKiCadUnitNumberFromGate( aGateID );
1858 copySymbolItems( kiSymDef, tempSymbol, gateNumber );
1859
1860 // Hide the value field for now (it might get unhidden if an attribute exists in the cadstar
1861 // design with the text "Value"
1862 tempSymbol->GetValueField().SetVisible( false );
1863
1864
1865 SCH_FIELD* partNameField = tempSymbol->FindField( PartNameFieldName );
1866
1867 if( partNameField )
1868 partNameField->SetText( EscapeFieldText( aCadstarPart.Name ) );
1869
1870 const POINT& symDefOrigin = Library.SymbolDefinitions.at( aSymdefID ).Origin;
1871 wxString footprintRefName = wxEmptyString;
1872 wxString footprintAlternateName = wxEmptyString;
1873
1874 auto loadLibraryField = [&]( const ATTRIBUTE_VALUE& aAttributeVal )
1875 {
1876 wxString attrName = getAttributeName( aAttributeVal.AttributeID );
1877
1878 // Remove invalid field characters
1879 wxString attributeValue = aAttributeVal.Value;
1880 attributeValue.Replace( wxT( "\n" ), wxT( "\\n" ) );
1881 attributeValue.Replace( wxT( "\r" ), wxT( "\\r" ) );
1882 attributeValue.Replace( wxT( "\t" ), wxT( "\\t" ) );
1883
1884 //TODO: Handle "links": In cadstar a field can be a "link" if its name starts
1885 // with the characters "Link ". Need to figure out how to convert them to
1886 // equivalent in KiCad.
1887
1888 if( attrName == wxT( "(PartDefinitionNameStem)" ) )
1889 {
1890 //Space not allowed in Reference field
1891 attributeValue.Replace( wxT( " " ), "_" );
1892 tempSymbol->GetReferenceField().SetText( attributeValue );
1893 return;
1894 }
1895 else if( attrName == wxT( "(PartDescription)" ) )
1896 {
1897 tempSymbol->SetDescription( attributeValue );
1898 return;
1899 }
1900 else if( attrName == wxT( "(PartDefinitionReferenceName)" ) )
1901 {
1902 footprintRefName = attributeValue;
1903 return;
1904 }
1905 else if( attrName == wxT( "(PartDefinitionAlternateName)" ) )
1906 {
1907 footprintAlternateName = attributeValue;
1908 return;
1909 }
1910
1911 bool attrIsNew = tempSymbol->FindField( attrName ) == nullptr;
1912 SCH_FIELD* attrField = addNewFieldToSymbol( attrName, tempSymbol );
1913
1914 wxASSERT( attrField->GetName() == attrName );
1915 attrField->SetText( aAttributeVal.Value );
1916 attrField->SetUnit( gateNumber );
1917
1918 const ATTRIBUTE_ID& attrid = aAttributeVal.AttributeID;
1919 attrField->SetVisible( isAttributeVisible( attrid ) );
1920
1921 if( aAttributeVal.HasLocation )
1922 {
1923 // Check if the part itself defined a location for the field
1924 applyToLibraryFieldAttribute( aAttributeVal.AttributeLocation, symDefOrigin,
1925 attrField );
1926 }
1927 else if( attrIsNew )
1928 {
1929 attrField->SetVisible( false );
1930 applyTextSettings( attrField, wxT( "TC1" ), ALIGNMENT::NO_ALIGNMENT,
1931 JUSTIFICATION::LEFT, false, true );
1932 }
1933 };
1934
1935 // Load all attributes in the Part Definition
1936 for( auto& [attrId, attrVal] : aCadstarPart.Definition.AttributeValues )
1937 loadLibraryField( attrVal );
1938
1939 // Load all attributes in the Part itself.
1940 for( auto& [attrId, attrVal] : aCadstarPart.AttributeValues )
1941 loadLibraryField( attrVal );
1942
1943 setFootprintOnSymbol( tempSymbol, footprintRefName, footprintAlternateName );
1944
1945 if( aCadstarPart.Definition.HidePinNames )
1946 {
1947 tempSymbol->SetShowPinNames( false );
1948 tempSymbol->SetShowPinNumbers( false );
1949 }
1950
1951 aSymbol = tempSymbol.release();
1952}
1953
1954
1955void CADSTAR_SCH_ARCHIVE_LOADER::setFootprintOnSymbol( std::unique_ptr<LIB_SYMBOL>& aKiCadSymbol,
1956 const wxString& aFootprintName,
1957 const wxString& aFootprintAlternate )
1958{
1959 wxString fpNameInLibrary = generateLibName( aFootprintName, aFootprintAlternate );
1960
1961 if( !fpNameInLibrary.IsEmpty() )
1962 {
1963 wxArrayString fpFilters;
1964 fpFilters.Add( aFootprintName ); // In cadstar one footprint has several "alternates"
1965
1966 if( !aFootprintAlternate.IsEmpty() )
1967 fpFilters.Add( fpNameInLibrary );
1968
1969 aKiCadSymbol->SetFPFilters( fpFilters );
1970
1971 LIB_ID libID( m_footprintLibName, fpNameInLibrary );
1972 aKiCadSymbol->GetFootprintField().SetText( libID.Format() );
1973 }
1974}
1975
1976
1977void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
1978 const VECTOR2I& aSymbolOrigin,
1979 LIB_SYMBOL* aSymbol,
1980 int aGateNumber,
1981 int aLineThickness )
1982{
1983 const VERTEX* prev = &aCadstarVertices.at( 0 );
1984 const VERTEX* cur;
1985
1986 wxASSERT_MSG( prev->Type == VERTEX_TYPE::POINT, "First vertex should always be a point." );
1987
1988 for( size_t i = 1; i < aCadstarVertices.size(); i++ )
1989 {
1990 cur = &aCadstarVertices.at( i );
1991
1992 SCH_SHAPE* shape = nullptr;
1993 bool cw = false;
1994 VECTOR2I startPoint = getKiCadLibraryPoint( prev->End, aSymbolOrigin );
1995 VECTOR2I endPoint = getKiCadLibraryPoint( cur->End, aSymbolOrigin );
1996 VECTOR2I centerPoint;
1997
2000 {
2001 centerPoint = ( startPoint + endPoint ) / 2;
2002 }
2003 else
2004 {
2005 centerPoint = getKiCadLibraryPoint( cur->Center, aSymbolOrigin );
2006 }
2007
2008
2009 switch( cur->Type )
2010 {
2011 case VERTEX_TYPE::POINT:
2012 shape = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE );
2013 shape->AddPoint( startPoint );
2014 shape->AddPoint( endPoint );
2015 break;
2016
2019 cw = true;
2021
2024 shape = new SCH_SHAPE( SHAPE_T::ARC, LAYER_DEVICE );
2025
2026 shape->SetPosition( centerPoint );
2027
2028 if( cw )
2029 {
2030 shape->SetStart( endPoint );
2031 shape->SetEnd( startPoint );
2032 }
2033 else
2034 {
2035 shape->SetStart( startPoint );
2036 shape->SetEnd( endPoint );
2037 }
2038
2039 break;
2040 }
2041
2042 shape->SetUnit( aGateNumber );
2043 shape->SetStroke( STROKE_PARAMS( aLineThickness, LINE_STYLE::SOLID ) );
2044 aSymbol->AddDrawItem( shape, false );
2045
2046 prev = cur;
2047 }
2048
2049 aSymbol->GetDrawItems().sort();
2050}
2051
2052
2054 const VECTOR2I& aSymbolOrigin,
2055 SCH_FIELD* aKiCadField )
2056{
2057 aKiCadField->SetTextPos( getKiCadLibraryPoint( aCadstarAttrLoc.Position, aSymbolOrigin ) );
2058
2059 applyTextSettings( aKiCadField, aCadstarAttrLoc.TextCodeID, aCadstarAttrLoc.Alignment,
2060 aCadstarAttrLoc.Justification, aCadstarAttrLoc.OrientAngle,
2061 aCadstarAttrLoc.Mirror, true );
2062}
2063
2064
2066 const LIB_SYMBOL& aKiCadPart,
2067 EDA_ANGLE& aComponentOrientation )
2068{
2069 LIB_ID libId;
2070 libId.SetLibItemName( aKiCadPart.GetName() );
2071
2072 int unit = getKiCadUnitNumberFromGate( aCadstarSymbol.GateID );
2073
2074 SCH_SHEET_PATH sheetpath;
2075 SCH_SHEET* kiSheet = m_sheetMap.at( aCadstarSymbol.LayerID );
2076 m_rootSheet->LocatePathOfScreen( kiSheet->GetScreen(), &sheetpath );
2077
2078 SCH_SYMBOL* symbol = new SCH_SYMBOL( aKiCadPart, libId, &sheetpath, unit );
2079
2080 if( aCadstarSymbol.IsComponent )
2081 {
2082 symbol->SetRef( &sheetpath, aCadstarSymbol.ComponentRef.Designator );
2083 }
2084
2085 symbol->SetPosition( getKiCadPoint( aCadstarSymbol.Origin ) );
2086
2087 EDA_ANGLE compAngle = getAngle( aCadstarSymbol.OrientAngle );
2088 int compOrientation = 0;
2089
2090 if( aCadstarSymbol.Mirror )
2091 {
2092 compAngle = -compAngle;
2093 compOrientation += SYMBOL_ORIENTATION_T::SYM_MIRROR_Y;
2094 }
2095
2096 compOrientation += getComponentOrientation( compAngle, aComponentOrientation );
2097 EDA_ANGLE test1( compAngle );
2098 EDA_ANGLE test2( aComponentOrientation );
2099
2100 if( test1.Normalize180() != test2.Normalize180() )
2101 {
2102 m_reporter->Report( wxString::Format( _( "Symbol '%s' is rotated by an angle of %.1f "
2103 "degrees in the original CADSTAR design but "
2104 "KiCad only supports rotation angles multiples "
2105 "of 90 degrees. The connecting wires will need "
2106 "manual fixing." ),
2107 aCadstarSymbol.ComponentRef.Designator,
2108 compAngle.AsDegrees() ),
2110 }
2111
2112 symbol->SetOrientation( compOrientation );
2113
2114 if( m_sheetMap.find( aCadstarSymbol.LayerID ) == m_sheetMap.end() )
2115 {
2116 m_reporter->Report( wxString::Format( _( "Symbol '%s' references sheet ID '%s' which does "
2117 "not exist in the design. The symbol was not "
2118 "loaded." ),
2119 aCadstarSymbol.ComponentRef.Designator,
2120 aCadstarSymbol.LayerID ),
2122
2123 delete symbol;
2124 return nullptr;
2125 }
2126
2127 wxString gate = ( aCadstarSymbol.GateID.IsEmpty() ) ? wxString( wxT( "A" ) ) : aCadstarSymbol.GateID;
2128 wxString partGateIndex = aCadstarSymbol.PartRef.RefID + gate;
2129
2130 //Handle pin swaps
2131 if( m_pinNumsMap.find( partGateIndex ) != m_pinNumsMap.end() )
2132 {
2133 TERMINAL_TO_PINNUM_MAP termNumMap = m_pinNumsMap.at( partGateIndex );
2134
2135 std::map<wxString, SCH_PIN*> pinNumToLibPinMap;
2136
2137 for( auto& term : termNumMap )
2138 {
2139 wxString pinNum = term.second;
2140 pinNumToLibPinMap.insert( { pinNum,
2141 symbol->GetLibSymbolRef()->GetPin( term.second ) } );
2142 }
2143
2144 auto replacePinNumber =
2145 [&]( wxString aOldPinNum, wxString aNewPinNum )
2146 {
2147 if( aOldPinNum == aNewPinNum )
2148 return;
2149
2150 SCH_PIN* libpin = pinNumToLibPinMap.at( aOldPinNum );
2151 libpin->SetNumber( HandleTextOverbar( aNewPinNum ) );
2152 };
2153
2154 //Older versions of Cadstar used pin numbers
2155 for( auto& pinPair : aCadstarSymbol.PinNumbers )
2156 {
2157 SYMBOL::PIN_NUM pin = pinPair.second;
2158
2159 replacePinNumber( termNumMap.at( pin.TerminalID ),
2160 wxString::Format( "%ld", pin.PinNum ) );
2161 }
2162
2163 //Newer versions of Cadstar use pin names
2164 for( auto& pinPair : aCadstarSymbol.PinNames )
2165 {
2166 SYMPINNAME_LABEL pin = pinPair.second;
2167 replacePinNumber( termNumMap.at( pin.TerminalID ), pin.NameOrLabel );
2168 }
2169
2170 symbol->UpdatePins();
2171 }
2172
2173 kiSheet->GetScreen()->Append( symbol );
2174
2175 return symbol;
2176}
2177
2178
2180 const EDA_ANGLE& aComponentOrientation,
2181 bool aIsMirrored,
2182 SCH_FIELD* aKiCadField )
2183{
2184 aKiCadField->SetPosition( getKiCadPoint( aCadstarAttrLoc.Position ) );
2185 aKiCadField->SetVisible( true );
2186
2187 ALIGNMENT alignment = aCadstarAttrLoc.Alignment;
2188 EDA_ANGLE textAngle = getAngle( aCadstarAttrLoc.OrientAngle );
2189
2190 if( aIsMirrored )
2191 {
2192 // We need to change the aligment when the symbol is mirrored based on the text orientation
2193 // To ensure the anchor point is the same in KiCad.
2194
2195 int textIsVertical = KiROUND( textAngle.AsDegrees() / 90.0 ) % 2;
2196
2197 if( textIsVertical )
2198 alignment = rotate180( alignment );
2199
2200 alignment = mirrorX( alignment );
2201 }
2202
2203 applyTextSettings( aKiCadField, aCadstarAttrLoc.TextCodeID, alignment,
2204 aCadstarAttrLoc.Justification,
2205 getCadstarAngle( textAngle - aComponentOrientation ),
2206 aCadstarAttrLoc.Mirror );
2207}
2208
2209
2211 EDA_ANGLE& aReturnedOrientation )
2212{
2213 int compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_0;
2214
2215 EDA_ANGLE oDeg = aOrientAngle;
2216 oDeg.Normalize180();
2217
2218 if( oDeg >= -ANGLE_45 && oDeg <= ANGLE_45 )
2219 {
2220 compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_0;
2221 aReturnedOrientation = ANGLE_0;
2222 }
2223 else if( oDeg >= ANGLE_45 && oDeg <= ANGLE_135 )
2224 {
2225 compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_90;
2226 aReturnedOrientation = ANGLE_90;
2227 }
2228 else if( oDeg >= ANGLE_135 || oDeg <= -ANGLE_135 )
2229 {
2230 compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_180;
2231 aReturnedOrientation = ANGLE_180;
2232 }
2233 else
2234 {
2235 compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_270;
2236 aReturnedOrientation = ANGLE_270;
2237 }
2238
2239 return compOrientation;
2240}
2241
2242
2245 const NETELEMENT_ID& aNetElementID )
2246{
2247 // clang-format off
2248 auto logUnknownNetElementError =
2249 [&]()
2250 {
2251 m_reporter->Report( wxString::Format( _( "Net %s references unknown net element %s. "
2252 "The net was not properly loaded and may "
2253 "require manual fixing." ),
2254 getNetName( aNet ),
2255 aNetElementID ),
2257
2258 return POINT();
2259 };
2260 // clang-format on
2261
2262 if( aNetElementID.Contains( "J" ) ) // Junction
2263 {
2264 if( aNet.Junctions.find( aNetElementID ) == aNet.Junctions.end() )
2265 return logUnknownNetElementError();
2266
2267 return aNet.Junctions.at( aNetElementID ).Location;
2268 }
2269 else if( aNetElementID.Contains( "P" ) ) // Terminal/Pin of a symbol
2270 {
2271 if( aNet.Terminals.find( aNetElementID ) == aNet.Terminals.end() )
2272 return logUnknownNetElementError();
2273
2274 SYMBOL_ID symid = aNet.Terminals.at( aNetElementID ).SymbolID;
2275 TERMINAL_ID termid = aNet.Terminals.at( aNetElementID ).TerminalID;
2276
2277 if( Schematic.Symbols.find( symid ) == Schematic.Symbols.end() )
2278 return logUnknownNetElementError();
2279
2280 SYMBOL sym = Schematic.Symbols.at( symid );
2281 SYMDEF_ID symdefid = sym.SymdefID;
2282 VECTOR2I symbolOrigin = sym.Origin;
2283
2284 if( Library.SymbolDefinitions.find( symdefid ) == Library.SymbolDefinitions.end() )
2285 return logUnknownNetElementError();
2286
2287 VECTOR2I libpinPosition =
2288 Library.SymbolDefinitions.at( symdefid ).Terminals.at( termid ).Position;
2289 VECTOR2I libOrigin = Library.SymbolDefinitions.at( symdefid ).Origin;
2290
2291 VECTOR2I pinOffset = libpinPosition - libOrigin;
2292 pinOffset.x = ( pinOffset.x * sym.ScaleRatioNumerator ) / sym.ScaleRatioDenominator;
2293 pinOffset.y = ( pinOffset.y * sym.ScaleRatioNumerator ) / sym.ScaleRatioDenominator;
2294
2295 VECTOR2I pinPosition = symbolOrigin + pinOffset;
2296 EDA_ANGLE compAngle = getAngle( sym.OrientAngle );
2297
2298 if( sym.Mirror )
2299 pinPosition.x = ( 2 * symbolOrigin.x ) - pinPosition.x;
2300
2301 EDA_ANGLE adjustedOrientation;
2302 getComponentOrientation( compAngle, adjustedOrientation );
2303
2304 RotatePoint( pinPosition, symbolOrigin, -adjustedOrientation );
2305
2306 POINT retval;
2307 retval.x = pinPosition.x;
2308 retval.y = pinPosition.y;
2309
2310 return retval;
2311 }
2312 else if( aNetElementID.Contains( "BT" ) ) // Bus Terminal
2313 {
2314 if( aNet.BusTerminals.find( aNetElementID ) == aNet.BusTerminals.end() )
2315 return logUnknownNetElementError();
2316
2317 return aNet.BusTerminals.at( aNetElementID ).SecondPoint;
2318 }
2319 else if( aNetElementID.Contains( "BLKT" ) ) // Block Terminal (sheet hierarchy connection)
2320 {
2321 if( aNet.BlockTerminals.find( aNetElementID ) == aNet.BlockTerminals.end() )
2322 return logUnknownNetElementError();
2323
2324 BLOCK_ID blockid = aNet.BlockTerminals.at( aNetElementID ).BlockID;
2325 TERMINAL_ID termid = aNet.BlockTerminals.at( aNetElementID ).TerminalID;
2326
2327 if( Schematic.Blocks.find( blockid ) == Schematic.Blocks.end() )
2328 return logUnknownNetElementError();
2329
2330 return Schematic.Blocks.at( blockid ).Terminals.at( termid ).Position;
2331 }
2332 else if( aNetElementID.Contains( "D" ) ) // Dangler
2333 {
2334 if( aNet.Danglers.find( aNetElementID ) == aNet.Danglers.end() )
2335 return logUnknownNetElementError();
2336
2337 return aNet.Danglers.at( aNetElementID ).Position;
2338 }
2339 else
2340 {
2341 return logUnknownNetElementError();
2342 }
2343}
2344
2345
2347{
2348 wxString netname = aNet.Name;
2349
2350 if( netname.IsEmpty() )
2351 netname = wxString::Format( "$%ld", aNet.SignalNum );
2352
2353 return netname;
2354}
2355
2356
2357void CADSTAR_SCH_ARCHIVE_LOADER::loadShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
2358 LINECODE_ID aCadstarLineCodeID,
2359 LAYER_ID aCadstarSheetID,
2360 SCH_LAYER_ID aKiCadSchLayerID,
2361 const VECTOR2I& aMoveVector,
2362 const EDA_ANGLE& aRotation,
2363 const double& aScalingFactor,
2364 const VECTOR2I& aTransformCentre,
2365 const bool& aMirrorInvert )
2366{
2367 int lineWidth = KiROUND( getLineThickness( aCadstarLineCodeID ) * aScalingFactor );
2368 LINE_STYLE lineStyle = getLineStyle( aCadstarLineCodeID );
2369
2370 const VERTEX* prev = &aCadstarVertices.at( 0 );
2371 const VERTEX* cur;
2372
2373 wxASSERT_MSG( prev->Type == VERTEX_TYPE::POINT,
2374 "First vertex should always be a point vertex" );
2375
2376 auto pointTransform =
2377 [&]( const VECTOR2I& aV )
2378 {
2379 return applyTransform( getKiCadPoint( aV ), aMoveVector, aRotation,
2380 aScalingFactor, aTransformCentre, aMirrorInvert );
2381 };
2382
2383 for( size_t ii = 1; ii < aCadstarVertices.size(); ii++ )
2384 {
2385 cur = &aCadstarVertices.at( ii );
2386
2387 VECTOR2I transformedStartPoint = pointTransform( prev->End );
2388 VECTOR2I transformedEndPoint = pointTransform( cur->End );
2389
2390 switch( cur->Type )
2391 {
2396 {
2397 SHAPE_ARC tempArc = cur->BuildArc( transformedStartPoint, pointTransform );
2398
2399 SCH_SHAPE* arcShape = new SCH_SHAPE( SHAPE_T::ARC, LAYER_NOTES, lineWidth );
2400 arcShape->SetArcGeometry( tempArc.GetP0(), tempArc.GetArcMid(), tempArc.GetP1() );
2401
2402 loadItemOntoKiCadSheet( aCadstarSheetID, arcShape );
2403 break;
2404 }
2405
2406 case VERTEX_TYPE::POINT:
2407 {
2408 SCH_LINE* segment = new SCH_LINE();
2409
2410 segment->SetLayer( aKiCadSchLayerID );
2411 segment->SetLineWidth( lineWidth );
2412 segment->SetLineStyle( lineStyle );
2413
2414 segment->SetStartPoint( transformedStartPoint );
2415 segment->SetEndPoint( transformedEndPoint );
2416
2417 loadItemOntoKiCadSheet( aCadstarSheetID, segment );
2418 break;
2419 }
2420
2421 default:
2422 wxFAIL_MSG( "Unknown CADSTAR Vertex type" );
2423 }
2424
2425 prev = cur;
2426 }
2427}
2428
2429
2431 const LAYER_ID& aCadstarSheetIDOverride,
2432 SCH_LAYER_ID aKiCadSchLayerID,
2433 const VECTOR2I& aMoveVector,
2434 const EDA_ANGLE& aRotation,
2435 const double& aScalingFactor,
2436 const VECTOR2I& aTransformCentre,
2437 const bool& aMirrorInvert )
2438{
2439 loadShapeVertices( aCadstarFigure.Shape.Vertices, aCadstarFigure.LineCodeID,
2440 aCadstarSheetIDOverride, aKiCadSchLayerID, aMoveVector, aRotation,
2441 aScalingFactor, aTransformCentre, aMirrorInvert );
2442
2443 for( CUTOUT cutout : aCadstarFigure.Shape.Cutouts )
2444 {
2445 loadShapeVertices( cutout.Vertices, aCadstarFigure.LineCodeID, aCadstarSheetIDOverride,
2446 aKiCadSchLayerID, aMoveVector, aRotation, aScalingFactor,
2447 aTransformCentre, aMirrorInvert );
2448 }
2449}
2450
2451
2453 const VECTOR2I& aPosition,
2454 VECTOR2I aSheetSize,
2455 const SCH_SHEET_PATH& aParentSheet )
2456{
2457 wxCHECK_MSG( m_sheetMap.find( aCadstarSheetID ) == m_sheetMap.end(), ,
2458 "Sheet already loaded!" );
2459
2460 SCH_SHEET* sheet = new SCH_SHEET(
2461 /* aParent */ aParentSheet.Last(),
2462 /* aPosition */ aPosition,
2463 /* aSize */ VECTOR2I( aSheetSize ) );
2464 SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
2465 SCH_SHEET_PATH instance( aParentSheet );
2466
2467 sheet->SetScreen( screen );
2468
2469 wxString name = Sheets.SheetNames.at( aCadstarSheetID );
2470
2471 SCH_FIELD& sheetNameField = sheet->GetFields()[SHEETNAME];
2472 SCH_FIELD& filenameField = sheet->GetFields()[SHEETFILENAME];
2473
2474 sheetNameField.SetText( name );
2475
2476 int sheetNum = getSheetNumber( aCadstarSheetID );
2477 wxString loadedFilename = wxFileName( Filename ).GetName();
2478 std::string filename = wxString::Format( "%s_%02d", loadedFilename, sheetNum ).ToStdString();
2479
2480 ReplaceIllegalFileNameChars( &filename );
2481 filename += wxT( "." ) + wxString( FILEEXT::KiCadSchematicFileExtension );
2482
2483 filenameField.SetText( filename );
2484
2485 wxFileName fn( m_schematic->Prj().GetProjectPath() + filename );
2486 sheet->GetScreen()->SetFileName( fn.GetFullPath() );
2487 aParentSheet.Last()->GetScreen()->Append( sheet );
2488 instance.push_back( sheet );
2489
2490 wxString pageNumStr = wxString::Format( "%d", getSheetNumber( aCadstarSheetID ) );
2491 instance.SetPageNumber( pageNumStr );
2492
2493 sheet->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
2494
2495 m_sheetMap.insert( { aCadstarSheetID, sheet } );
2496
2497 loadChildSheets( aCadstarSheetID, instance );
2498}
2499
2500
2502 const SCH_SHEET_PATH& aSheet )
2503{
2504 wxCHECK_MSG( m_sheetMap.find( aCadstarSheetID ) != m_sheetMap.end(), ,
2505 "FIXME! Parent sheet should be loaded before attempting to load subsheets" );
2506
2507 for( std::pair<BLOCK_ID, BLOCK> blockPair : Schematic.Blocks )
2508 {
2509 BLOCK& block = blockPair.second;
2510
2511 if( block.LayerID == aCadstarSheetID && block.Type == BLOCK::TYPE::CHILD )
2512 {
2513 if( block.AssocLayerID == wxT( "NO_LINK" ) )
2514 {
2515 if( block.Figures.size() > 0 )
2516 {
2517 m_reporter->Report( wxString::Format( _( "The block ID %s (Block name: '%s') "
2518 "is drawn on sheet '%s' but is not "
2519 "linked to another sheet in the "
2520 "design. KiCad requires all sheet "
2521 "symbols to be associated to a sheet, "
2522 "so the block was not loaded." ),
2523 block.ID, block.Name,
2524 Sheets.SheetNames.at( aCadstarSheetID ) ),
2526 }
2527
2528 continue;
2529 }
2530
2531 // In KiCad you can only draw rectangular shapes whereas in Cadstar arbitrary shapes
2532 // are allowed. We will calculate the extents of the Cadstar shape and draw a rectangle
2533
2534 std::pair<VECTOR2I, VECTOR2I> blockExtents;
2535
2536 if( block.Figures.size() > 0 )
2537 {
2538 blockExtents = getFigureExtentsKiCad( block.Figures.begin()->second );
2539 }
2540 else
2541 {
2542 THROW_IO_ERROR( wxString::Format( _( "The CADSTAR schematic might be corrupt: "
2543 "Block %s references a child sheet but has no "
2544 "Figure defined." ),
2545 block.ID ) );
2546 }
2547
2548 loadSheetAndChildSheets( block.AssocLayerID, blockExtents.first, blockExtents.second,
2549 aSheet );
2550
2551 // Hide all KiCad sheet properties (sheet name/filename is not applicable in CADSTAR)
2552 SCH_SHEET* loadedSheet = m_sheetMap.at( block.AssocLayerID );
2553 SCH_FIELDS fields = loadedSheet->GetFields();
2554
2555 for( SCH_FIELD& field : fields )
2556 {
2557 field.SetVisible( false );
2558 }
2559
2560 if( block.HasBlockLabel )
2561 {
2562 //@todo use below code when KiCad supports multi-line fields
2563 /*
2564 // Add the block label as a separate field
2565 SCH_FIELD blockNameField( getKiCadPoint( block.BlockLabel.Position ), 2,
2566 loadedSheet, wxString( "Block name" ) );
2567 blockNameField.SetText( block.Name );
2568 blockNameField.SetVisible( true );
2569
2570 applyTextSettings( &blockNameField,
2571 block.BlockLabel.TextCodeID,
2572 block.BlockLabel.Alignment,
2573 block.BlockLabel.Justification,
2574 block.BlockLabel.OrientAngle,
2575 block.BlockLabel.Mirror );
2576
2577 fields.push_back( blockNameField );*/
2578
2579 // For now as as a text item (supports multi-line properly)
2580 SCH_TEXT* kiTxt = new SCH_TEXT();
2581
2582 kiTxt->SetParent( m_schematic );
2583 kiTxt->SetPosition( getKiCadPoint( block.BlockLabel.Position ) );
2584 kiTxt->SetText( block.Name );
2585
2588 block.BlockLabel.Mirror );
2589
2590 loadItemOntoKiCadSheet( aCadstarSheetID, kiTxt );
2591 }
2592
2593 loadedSheet->SetFields( fields );
2594 }
2595 }
2596}
2597
2598
2599std::vector<CADSTAR_SCH_ARCHIVE_LOADER::LAYER_ID> CADSTAR_SCH_ARCHIVE_LOADER::findOrphanSheets()
2600{
2601 std::vector<LAYER_ID> childSheets, orphanSheets;
2602
2603 //Find all sheets that are child of another
2604 for( std::pair<BLOCK_ID, BLOCK> blockPair : Schematic.Blocks )
2605 {
2606 BLOCK& block = blockPair.second;
2607 LAYER_ID& assocSheetID = block.AssocLayerID;
2608
2609 if( block.Type == BLOCK::TYPE::CHILD )
2610 childSheets.push_back( assocSheetID );
2611 }
2612
2613 //Add sheets that do not have a parent
2614 for( LAYER_ID sheetID : Sheets.SheetOrder )
2615 {
2616 if( std::find( childSheets.begin(), childSheets.end(), sheetID ) == childSheets.end() )
2617 orphanSheets.push_back( sheetID );
2618 }
2619
2620 return orphanSheets;
2621}
2622
2623
2625{
2626 int i = 1;
2627
2628 for( LAYER_ID sheetID : Sheets.SheetOrder )
2629 {
2630 if( sheetID == aCadstarSheetID )
2631 return i;
2632
2633 ++i;
2634 }
2635
2636 return -1;
2637}
2638
2639
2641{
2642 wxCHECK_MSG( aItem, /*void*/, wxT( "aItem is null" ) );
2643
2644 if( aCadstarSheetID == "ALL_SHEETS" )
2645 {
2646 SCH_ITEM* duplicateItem = nullptr;
2647
2648 for( std::pair<LAYER_ID, SHEET_NAME> sheetPair : Sheets.SheetNames )
2649 {
2650 LAYER_ID sheetID = sheetPair.first;
2651 duplicateItem = aItem->Duplicate();
2652 m_sheetMap.at( sheetID )->GetScreen()->Append( aItem->Duplicate() );
2653 }
2654
2655 //Get rid of the extra copy:
2656 delete aItem;
2657 aItem = duplicateItem;
2658 }
2659 else if( aCadstarSheetID == "NO_SHEET" )
2660 {
2661 wxFAIL_MSG( wxT( "Trying to add an item to NO_SHEET? This might be a documentation symbol." ) );
2662 }
2663 else
2664 {
2665 if( m_sheetMap.find( aCadstarSheetID ) != m_sheetMap.end() )
2666 {
2667 m_sheetMap.at( aCadstarSheetID )->GetScreen()->Append( aItem );
2668 }
2669 else
2670 {
2671 delete aItem;
2672 wxFAIL_MSG( wxT( "Unknown Sheet ID." ) );
2673 }
2674 }
2675}
2676
2677
2680 const wxString& aSymDefAlternate )
2681{
2682 if( m_SymDefNamesCache.size() != Library.SymbolDefinitions.size() )
2683 {
2684 // Re-initialise
2685 m_SymDefNamesCache.clear();
2687
2688 // Create a lower case cache to avoid searching each time
2689 for( auto& [id, symdef] : Library.SymbolDefinitions )
2690 {
2691 wxString refKey = symdef.ReferenceName.Lower();
2692 wxString altKey = symdef.Alternate.Lower();
2693
2694 m_SymDefNamesCache[{ refKey, altKey }] = id;
2695
2696 // Secondary cache to find symbols just by the Name (e.g. if the alternate
2697 // does not exist, we still want to return a symbo - the same behaviour
2698 // as CADSTAR
2699
2700 if( !m_DefaultSymDefNamesCache.count( refKey ) )
2701 {
2702 m_DefaultSymDefNamesCache.insert( { refKey, id } );
2703 }
2704 else if( altKey.IsEmpty() )
2705 {
2706 // Always use the empty alternate if it exists
2707 m_DefaultSymDefNamesCache[refKey] = id;
2708 }
2709 }
2710 }
2711
2712 wxString refKeyToFind = aSymdefName.Lower();
2713 wxString altKeyToFind = aSymDefAlternate.Lower();
2714
2715 if( m_SymDefNamesCache.count( { refKeyToFind, altKeyToFind } ) )
2716 {
2717 return m_SymDefNamesCache[{ refKeyToFind, altKeyToFind }];
2718 }
2719 else if( m_DefaultSymDefNamesCache.count( refKeyToFind ) )
2720 {
2721 return m_DefaultSymDefNamesCache[refKeyToFind];
2722 }
2723
2724
2725 return SYMDEF_ID();
2726}
2727
2728
2730{
2731 // Use CADSTAR visibility settings to determine if an attribute is visible
2732 if( AttrColors.AttributeColors.find( aCadstarAttributeID ) != AttrColors.AttributeColors.end() )
2733 {
2734 return AttrColors.AttributeColors.at( aCadstarAttributeID ).IsVisible;
2735 }
2736
2737 return false; // If there is no visibility setting, assume not displayed
2738}
2739
2740
2742{
2743 wxCHECK( Assignments.Codedefs.LineCodes.find( aCadstarLineCodeID )
2746
2747 return getKiCadLength( Assignments.Codedefs.LineCodes.at( aCadstarLineCodeID ).Width );
2748}
2749
2750
2752{
2753 wxCHECK( Assignments.Codedefs.LineCodes.find( aCadstarLineCodeID )
2755 LINE_STYLE::SOLID );
2756
2757 // clang-format off
2758 switch( Assignments.Codedefs.LineCodes.at( aCadstarLineCodeID ).Style )
2759 {
2760 case LINESTYLE::DASH: return LINE_STYLE::DASH;
2761 case LINESTYLE::DASHDOT: return LINE_STYLE::DASHDOT;
2762 case LINESTYLE::DASHDOTDOT: return LINE_STYLE::DASHDOT; //TODO: update in future
2763 case LINESTYLE::DOT: return LINE_STYLE::DOT;
2764 case LINESTYLE::SOLID: return LINE_STYLE::SOLID;
2765 default: return LINE_STYLE::DEFAULT;
2766 }
2767 // clang-format on
2768}
2769
2770
2773{
2774 wxCHECK( Assignments.Codedefs.TextCodes.find( aCadstarTextCodeID )
2776 TEXTCODE() );
2777
2778 return Assignments.Codedefs.TextCodes.at( aCadstarTextCodeID );
2779}
2780
2781
2783{
2784 TEXTCODE txtCode = getTextCode( aCadstarTextCodeID );
2785
2786 return KiROUND( (double) getKiCadLength( txtCode.Height ) * TXT_HEIGHT_RATIO );
2787}
2788
2789
2791{
2792 wxCHECK( Assignments.Codedefs.AttributeNames.find( aCadstarAttributeID )
2794 aCadstarAttributeID );
2795
2796 return Assignments.Codedefs.AttributeNames.at( aCadstarAttributeID ).Name;
2797}
2798
2799
2802{
2803 wxCHECK( Parts.PartDefinitions.find( aCadstarPartID ) != Parts.PartDefinitions.end(), PART() );
2804
2805 return Parts.PartDefinitions.at( aCadstarPartID );
2806}
2807
2808
2811{
2812 wxCHECK( Assignments.Codedefs.RouteCodes.find( aCadstarRouteCodeID )
2814 ROUTECODE() );
2815
2816 return Assignments.Codedefs.RouteCodes.at( aCadstarRouteCodeID );
2817}
2818
2819
2820CADSTAR_SCH_ARCHIVE_LOADER::PART::DEFINITION::PIN
2822 const TERMINAL_ID& aTerminalID )
2823{
2824 for( std::pair<PART_DEFINITION_PIN_ID, PART::DEFINITION::PIN> pinPair :
2825 aCadstarPart.Definition.Pins )
2826 {
2827 PART::DEFINITION::PIN partPin = pinPair.second;
2828
2829 if( partPin.TerminalGate == aGateID && partPin.TerminalPin == aTerminalID )
2830 return partPin;
2831 }
2832
2833 return PART::DEFINITION::PIN();
2834}
2835
2836
2838{
2839 switch( aPinType )
2840 {
2841 case CADSTAR_PIN_TYPE::UNCOMMITTED: return ELECTRICAL_PINTYPE::PT_PASSIVE;
2842 case CADSTAR_PIN_TYPE::INPUT: return ELECTRICAL_PINTYPE::PT_INPUT;
2843 case CADSTAR_PIN_TYPE::OUTPUT_OR: return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
2844 case CADSTAR_PIN_TYPE::OUTPUT_NOT_OR: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2845 case CADSTAR_PIN_TYPE::OUTPUT_NOT_NORM_OR: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2846 case CADSTAR_PIN_TYPE::POWER: return ELECTRICAL_PINTYPE::PT_POWER_IN;
2847 case CADSTAR_PIN_TYPE::GROUND: return ELECTRICAL_PINTYPE::PT_POWER_IN;
2848 case CADSTAR_PIN_TYPE::TRISTATE_BIDIR: return ELECTRICAL_PINTYPE::PT_BIDI;
2849 case CADSTAR_PIN_TYPE::TRISTATE_INPUT: return ELECTRICAL_PINTYPE::PT_INPUT;
2850 case CADSTAR_PIN_TYPE::TRISTATE_DRIVER: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2851 }
2852
2853 return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
2854}
2855
2857{
2858 if( aCadstarGateID.IsEmpty() )
2859 return 1;
2860
2861 return (int) aCadstarGateID.Upper().GetChar( 0 ) - (int) wxUniChar( 'A' ) + 1;
2862}
2863
2864
2865SPIN_STYLE CADSTAR_SCH_ARCHIVE_LOADER::getSpinStyle( const long long& aCadstarOrientation,
2866 bool aMirror )
2867{
2868 EDA_ANGLE orientation = getAngle( aCadstarOrientation );
2869 SPIN_STYLE spinStyle = getSpinStyle( orientation );
2870
2871 if( aMirror )
2872 {
2873 spinStyle = spinStyle.RotateCCW();
2874 spinStyle = spinStyle.RotateCCW();
2875 }
2876
2877 return spinStyle;
2878}
2879
2880
2882{
2883 SPIN_STYLE spinStyle = SPIN_STYLE::LEFT;
2884
2885 EDA_ANGLE oDeg = aOrientation;
2886 oDeg.Normalize180();
2887
2888 if( oDeg >= -ANGLE_45 && oDeg <= ANGLE_45 )
2889 spinStyle = SPIN_STYLE::RIGHT; // 0deg
2890 else if( oDeg >= ANGLE_45 && oDeg <= ANGLE_135 )
2891 spinStyle = SPIN_STYLE::UP; // 90deg
2892 else if( oDeg >= ANGLE_135 || oDeg <= -ANGLE_135 )
2893 spinStyle = SPIN_STYLE::LEFT; // 180deg
2894 else
2895 spinStyle = SPIN_STYLE::BOTTOM; // 270deg
2896
2897 return spinStyle;
2898}
2899
2900
2903{
2904 switch( aCadstarAlignment )
2905 {
2906 // Change left to right:
2911
2912 //Change right to left:
2916
2917 // Center alignment does not mirror:
2920 case ALIGNMENT::TOPCENTER: return aCadstarAlignment;
2921
2922 // Shouldn't be here
2923 default: wxFAIL_MSG( "Unknown Cadstar Alignment" ); return aCadstarAlignment;
2924 }
2925}
2926
2927
2930{
2931 switch( aCadstarAlignment )
2932 {
2943
2944 // Shouldn't be here
2945 default: wxFAIL_MSG( "Unknown Cadstar Alignment" ); return aCadstarAlignment;
2946 }
2947}
2948
2949
2951 const TEXTCODE_ID& aCadstarTextCodeID )
2952{
2953 // Ensure we have no Cadstar overbar characters
2954 wxString escapedText = HandleTextOverbar( aKiCadTextItem->GetText() );
2955 aKiCadTextItem->SetText( escapedText );
2956
2957 if( !Assignments.Codedefs.TextCodes.count( aCadstarTextCodeID ) )
2958 return;
2959
2960 TEXTCODE textCode = getTextCode( aCadstarTextCodeID );
2961 int textHeight = KiROUND( (double) getKiCadLength( textCode.Height ) * TXT_HEIGHT_RATIO );
2962 int textWidth = getKiCadLength( textCode.Width );
2963
2964 // The width is zero for all non-cadstar fonts. Using a width equal to 2/3 the height seems
2965 // to work well for most fonts.
2966 if( textWidth == 0 )
2967 textWidth = getKiCadLength( 2LL * textCode.Height / 3LL );
2968
2969 aKiCadTextItem->SetTextWidth( textWidth );
2970 aKiCadTextItem->SetTextHeight( textHeight );
2971
2972#if 0
2973 // EEschema currently supports only normal vs bold for text thickness.
2974 aKiCadTextItem->SetTextThickness( getKiCadLength( textCode.LineWidth ) );
2975#endif
2976
2977 // Must come after SetTextSize()
2978 aKiCadTextItem->SetBold( textCode.Font.Modifier1 == FONT_BOLD );
2979 aKiCadTextItem->SetItalic( textCode.Font.Italic );
2980}
2981
2982
2984 const TEXTCODE_ID& aCadstarTextCodeID,
2985 const ALIGNMENT& aCadstarAlignment,
2986 const JUSTIFICATION& aCadstarJustification,
2987 const long long aCadstarOrientAngle,
2988 bool aMirrored,
2989 bool aInvertY )
2990{
2991 applyTextCodeIfExists( aKiCadTextItem, aCadstarTextCodeID );
2992 aKiCadTextItem->SetTextAngle( getAngle( aCadstarOrientAngle ) );
2993
2994 // Justification ignored for now as not supported in Eeschema, but leaving this code in
2995 // place for future upgrades.
2996 // TODO update this when Eeschema supports justification independent of anchor position.
2997 ALIGNMENT textAlignment = aCadstarAlignment;
2998
2999 // KiCad mirrors the justification and alignment when the symbol is mirrored but CADSTAR
3000 // specifies it post-mirroring. In contrast, if the text item itself is mirrored (not
3001 // supported in KiCad), CADSTAR specifies the alignment and justification pre-mirroring
3002 if( aMirrored )
3003 textAlignment = mirrorX( aCadstarAlignment );
3004
3005 auto setAlignment =
3006 [&]( EDA_TEXT* aText, ALIGNMENT aAlignment )
3007 {
3008 switch( aAlignment )
3009 {
3010 case ALIGNMENT::NO_ALIGNMENT: // Bottom left of the first line
3011 //No exact KiCad equivalent, so lets move the position of the text
3012 FixTextPositionNoAlignment( aText, aInvertY );
3017 break;
3018
3022 break;
3023
3027 break;
3028
3032 break;
3033
3037 break;
3038
3042 break;
3043
3044 case ALIGNMENT::TOPLEFT:
3047 break;
3048
3052 break;
3053
3057 break;
3058 }
3059 };
3060
3061 SPIN_STYLE spin = getSpinStyle( aCadstarOrientAngle, aMirrored );
3062 EDA_ITEM* textEdaItem = dynamic_cast<EDA_ITEM*>( aKiCadTextItem );
3063 wxCHECK( textEdaItem, /* void */ ); // ensure this is a EDA_ITEM
3064
3065 if( textEdaItem->Type() == SCH_FIELD_T || aInvertY )
3066 {
3067 // Spin style not used. All text justifications are permitted. However, only orientations
3068 // of 0 deg or 90 deg are supported
3069 EDA_ANGLE angle = aKiCadTextItem->GetTextAngle();
3070 angle.Normalize();
3071
3072 int quadrant = KiROUND( angle.AsDegrees() / 90.0 );
3073 quadrant %= 4;
3074
3075 switch( quadrant )
3076 {
3077 case 0:
3078 angle = ANGLE_HORIZONTAL;
3079 break;
3080 case 1:
3081 angle = ANGLE_VERTICAL;
3082 break;
3083 case 2:
3084 angle = ANGLE_HORIZONTAL;
3085 textAlignment = rotate180( textAlignment );
3086 break;
3087 case 3:
3088 angle = ANGLE_VERTICAL;
3089 textAlignment = rotate180( textAlignment );
3090 break;
3091 default:
3092 wxFAIL_MSG( "Unknown Quadrant" );
3093 }
3094
3095 aKiCadTextItem->SetTextAngle( angle );
3096 setAlignment( aKiCadTextItem, textAlignment );
3097 }
3098 else if( textEdaItem->Type() == SCH_TEXT_T )
3099 {
3100 // Note spin style in a SCH_TEXT results in a vertical alignment GR_TEXT_V_ALIGN_BOTTOM
3101 // so need to adjust the location of the text element based on Cadstar's original text
3102 // alignment (anchor position).
3103 setAlignment( aKiCadTextItem, textAlignment );
3104 BOX2I bb = textEdaItem->GetBoundingBox();
3105 int off = static_cast<SCH_TEXT*>( aKiCadTextItem )->GetTextOffset();
3106 VECTOR2I pos;
3107
3108 // Change the anchor point of the text item to make it match the same bounding box
3109 // And correct the error introduced by the text offsetting in KiCad
3110 switch( spin )
3111 {
3112 case SPIN_STYLE::BOTTOM: pos = { bb.GetRight() - off, bb.GetTop() }; break;
3113 case SPIN_STYLE::UP: pos = { bb.GetRight() - off, bb.GetBottom() }; break;
3114 case SPIN_STYLE::LEFT: pos = { bb.GetRight() , bb.GetBottom() + off }; break;
3115 case SPIN_STYLE::RIGHT: pos = { bb.GetLeft() , bb.GetBottom() + off }; break;
3116 default: wxFAIL_MSG( "Unexpected Spin Style" ); break;
3117 }
3118
3119 aKiCadTextItem->SetTextPos( pos );
3120
3121 switch( spin )
3122 {
3123 case SPIN_STYLE::RIGHT: // Horiz Normal Orientation
3124 aKiCadTextItem->SetTextAngle( ANGLE_HORIZONTAL );
3125 aKiCadTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
3126 break;
3127
3128 case SPIN_STYLE::UP: // Vert Orientation UP
3129 aKiCadTextItem->SetTextAngle( ANGLE_VERTICAL );
3130 aKiCadTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
3131 break;
3132
3133 case SPIN_STYLE::LEFT: // Horiz Orientation - Right justified
3134 aKiCadTextItem->SetTextAngle( ANGLE_HORIZONTAL );
3135 aKiCadTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
3136 break;
3137
3138 case SPIN_STYLE::BOTTOM: // Vert Orientation BOTTOM
3139 aKiCadTextItem->SetTextAngle( ANGLE_VERTICAL );
3140 aKiCadTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
3141 break;
3142
3143 default:
3144 wxFAIL_MSG( "Unexpected Spin Style" );
3145 break;
3146 }
3147
3148 aKiCadTextItem->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
3149 }
3150 else if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( aKiCadTextItem ) )
3151 {
3152 // We don't want to change position of net labels as that would break connectivity
3153 label->SetSpinStyle( spin );
3154 }
3155 else
3156 {
3157 wxFAIL_MSG( "Unexpected item type" );
3158 }
3159}
3160
3161
3163{
3164 SCH_TEXT* kiTxt = new SCH_TEXT();
3165
3166 kiTxt->SetParent( m_schematic ); // set to the schematic for now to avoid asserts
3167 kiTxt->SetPosition( getKiCadPoint( aCadstarTextElement.Position ) );
3168 kiTxt->SetText( aCadstarTextElement.Text );
3169
3170 applyTextSettings( kiTxt, aCadstarTextElement.TextCodeID, aCadstarTextElement.Alignment,
3171 aCadstarTextElement.Justification, aCadstarTextElement.OrientAngle,
3172 aCadstarTextElement.Mirror );
3173
3174 return kiTxt;
3175}
3176
3177
3179 long long aScalingFactorNumerator,
3180 long long aScalingFactorDenominator )
3181{
3182 LIB_SYMBOL* retval = new LIB_SYMBOL( *aSymbol );
3183
3184 if( aScalingFactorNumerator == aScalingFactorDenominator )
3185 return retval; // 1:1 scale, nothing to do
3186
3187 auto scaleLen =
3188 [&]( int aLength ) -> int
3189 {
3190 return( aLength * aScalingFactorNumerator ) / aScalingFactorDenominator;
3191 };
3192
3193 auto scalePt =
3194 [&]( VECTOR2I aCoord ) -> VECTOR2I
3195 {
3196 return VECTOR2I( scaleLen( aCoord.x ), scaleLen( aCoord.y ) );
3197 };
3198
3199 auto scaleSize =
3200 [&]( VECTOR2I aSize ) -> VECTOR2I
3201 {
3202 return VECTOR2I( scaleLen( aSize.x ), scaleLen( aSize.y ) );
3203 };
3204
3205 LIB_ITEMS_CONTAINER& items = retval->GetDrawItems();
3206
3207 for( SCH_ITEM& item : items )
3208 {
3209 switch( item.Type() )
3210 {
3211 case KICAD_T::SCH_SHAPE_T:
3212 {
3213 SCH_SHAPE& shape = static_cast<SCH_SHAPE&>( item );
3214
3215 if( shape.GetShape() == SHAPE_T::ARC )
3216 {
3217 shape.SetPosition( scalePt( shape.GetPosition() ) );
3218 shape.SetStart( scalePt( shape.GetStart() ) );
3219 shape.SetEnd( scalePt( shape.GetEnd() ) );
3220 }
3221 else if( shape.GetShape() == SHAPE_T::POLY )
3222 {
3223 SHAPE_LINE_CHAIN& poly = shape.GetPolyShape().Outline( 0 );
3224
3225 for( size_t ii = 0; ii < poly.GetPointCount(); ++ii )
3226 poly.SetPoint( ii, scalePt( poly.CPoint( ii ) ) );
3227 }
3228 break;
3229 }
3230
3231 case KICAD_T::SCH_PIN_T:
3232 {
3233 SCH_PIN& pin = static_cast<SCH_PIN&>( item );
3234
3235 pin.SetPosition( scalePt( pin.GetPosition() ) );
3236 pin.SetLength( scaleLen( pin.GetLength() ) );
3237 break;
3238 }
3239
3240 case KICAD_T::SCH_TEXT_T:
3241 {
3242 SCH_TEXT& txt = static_cast<SCH_TEXT&>( item );
3243
3244 txt.SetPosition( scalePt( txt.GetPosition() ) );
3245 txt.SetTextSize( scaleSize( txt.GetTextSize() ) );
3246 break;
3247 }
3248
3249 default:
3250 break;
3251 }
3252
3253 }
3254
3255 return retval;
3256}
3257
3258
3259void CADSTAR_SCH_ARCHIVE_LOADER::fixUpLibraryPins( LIB_SYMBOL* aSymbolToFix, int aGateNumber )
3260{
3261 auto compLambda = []( const VECTOR2I& aA, const VECTOR2I& aB )
3262 {
3263 return LexicographicalCompare( aA, aB ) < 0;
3264 };
3265
3266 // Store a list of vertical or horizontal segments in the symbol
3267 // Note: Need the custom comparison function to ensure the map is sorted correctly
3268 std::map<VECTOR2I, SHAPE_LINE_CHAIN, decltype( compLambda )> uniqueSegments( compLambda );
3269
3270 LIB_ITEMS_CONTAINER::ITERATOR shapeIt = aSymbolToFix->GetDrawItems().begin( SCH_SHAPE_T );
3271
3272 for( ; shapeIt != aSymbolToFix->GetDrawItems().end( SCH_SHAPE_T ); ++shapeIt )
3273 {
3274 SCH_SHAPE& shape = static_cast<SCH_SHAPE&>( *shapeIt );
3275
3276 if( aGateNumber > 0 && shape.GetUnit() != aGateNumber )
3277 continue;
3278
3279 if( shape.GetShape() != SHAPE_T::POLY )
3280 continue;
3281
3282 SHAPE_LINE_CHAIN poly = shape.GetPolyShape().Outline( 0 );
3283
3284 if( poly.GetPointCount() == 2 )
3285 {
3286 VECTOR2I pt0 = poly.CPoint( 0 );
3287 VECTOR2I pt1 = poly.CPoint( 1 );
3288
3289 if( pt0 != pt1 && uniqueSegments.count( pt0 ) == 0 && uniqueSegments.count( pt1 ) == 0 )
3290 {
3291 // we are only interested in vertical or horizontal segments
3292 if( pt0.x == pt1.x || pt0.y == pt1.y )
3293 {
3294 uniqueSegments.insert( { pt0, poly } );
3295 uniqueSegments.insert( { pt1, poly } );
3296 }
3297 }
3298 }
3299 }
3300
3301 for( SCH_PIN* pin : aSymbolToFix->GetPins( aGateNumber ) )
3302 {
3303 auto setPinOrientation =
3304 [&]( const EDA_ANGLE& aAngle )
3305 {
3306 EDA_ANGLE angle( aAngle );
3307 angle.Normalize180();
3308
3309 if( angle >= -ANGLE_45 && angle <= ANGLE_45 )
3310 pin->SetOrientation( PIN_ORIENTATION::PIN_RIGHT ); // 0 degrees
3311 else if( angle >= ANGLE_45 && angle <= ANGLE_135 )
3312 pin->SetOrientation( PIN_ORIENTATION::PIN_UP ); // 90 degrees
3313 else if( angle >= ANGLE_135 || angle <= -ANGLE_135 )
3314 pin->SetOrientation( PIN_ORIENTATION::PIN_LEFT ); // 180 degrees
3315 else
3316 pin->SetOrientation( PIN_ORIENTATION::PIN_DOWN ); // -90 degrees
3317 };
3318
3319 if( uniqueSegments.count( pin->GetPosition() ) )
3320 {
3321 SHAPE_LINE_CHAIN& poly = uniqueSegments.at( pin->GetPosition() );
3322
3323 VECTOR2I otherPt = poly.CPoint( 0 );
3324
3325 if( otherPt == pin->GetPosition() )
3326 otherPt = poly.CPoint( 1 );
3327
3328 VECTOR2I vec( otherPt - pin->GetPosition() );
3329
3330 pin->SetLength( vec.EuclideanNorm() );
3331 setPinOrientation( EDA_ANGLE( vec ) );
3332 }
3333 }
3334}
3335
3336
3337std::pair<VECTOR2I, VECTOR2I>
3339{
3340 VECTOR2I upperLeft( Assignments.Settings.DesignLimit.x, 0 );
3341 VECTOR2I lowerRight( 0, Assignments.Settings.DesignLimit.y );
3342
3343 for( const VERTEX& v : aCadstarFigure.Shape.Vertices )
3344 {
3345 if( upperLeft.x > v.End.x )
3346 upperLeft.x = v.End.x;
3347
3348 if( upperLeft.y < v.End.y )
3349 upperLeft.y = v.End.y;
3350
3351 if( lowerRight.x < v.End.x )
3352 lowerRight.x = v.End.x;
3353
3354 if( lowerRight.y > v.End.y )
3355 lowerRight.y = v.End.y;
3356 }
3357
3358 for( CUTOUT cutout : aCadstarFigure.Shape.Cutouts )
3359 {
3360 for( const VERTEX& v : aCadstarFigure.Shape.Vertices )
3361 {
3362 if( upperLeft.x > v.End.x )
3363 upperLeft.x = v.End.x;
3364
3365 if( upperLeft.y < v.End.y )
3366 upperLeft.y = v.End.y;
3367
3368 if( lowerRight.x < v.End.x )
3369 lowerRight.x = v.End.x;
3370
3371 if( lowerRight.y > v.End.y )
3372 lowerRight.y = v.End.y;
3373 }
3374 }
3375
3376 VECTOR2I upperLeftKiCad = getKiCadPoint( upperLeft );
3377 VECTOR2I lowerRightKiCad = getKiCadPoint( lowerRight );
3378
3379 VECTOR2I size = lowerRightKiCad - upperLeftKiCad;
3380
3381 return { upperLeftKiCad, VECTOR2I( abs( size.x ), abs( size.y ) ) };
3382}
3383
3384
3386{
3387 VECTOR2I retval;
3388
3389 retval.x = getKiCadLength( aCadstarPoint.x - m_designCenter.x );
3390 retval.y = -getKiCadLength( aCadstarPoint.y - m_designCenter.y );
3391
3392 return retval;
3393}
3394
3395
3397 const VECTOR2I& aCadstarCentre )
3398{
3399 VECTOR2I retval;
3400
3401 retval.x = getKiCadLength( aCadstarPoint.x - aCadstarCentre.x );
3402 retval.y = getKiCadLength( aCadstarPoint.y - aCadstarCentre.y );
3403
3404 return retval;
3405}
3406
3407
3409 const VECTOR2I& aMoveVector,
3410 const EDA_ANGLE& aRotation,
3411 const double& aScalingFactor,
3412 const VECTOR2I& aTransformCentre,
3413 const bool& aMirrorInvert )
3414{
3415 VECTOR2I retVal = aPoint;
3416
3417 if( aScalingFactor != 1.0 )
3418 {
3419 //scale point
3420 retVal -= aTransformCentre;
3421 retVal.x = KiROUND( retVal.x * aScalingFactor );
3422 retVal.y = KiROUND( retVal.y * aScalingFactor );
3423 retVal += aTransformCentre;
3424 }
3425
3426 if( aMirrorInvert )
3427 MIRROR( retVal.x, aTransformCentre.x );
3428
3429 if( !aRotation.IsZero() )
3430 RotatePoint( retVal, aTransformCentre, aRotation );
3431
3432 if( aMoveVector != VECTOR2I{ 0, 0 } )
3433 retVal += aMoveVector;
3434
3435 return retVal;
3436}
3437
3438
3440{
3441 return sqrt( ( (double) aPoint.x * (double) aPoint.x )
3442 + ( (double) aPoint.y * (double) aPoint.y ) );
3443}
const char * name
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
constexpr double SCH_IU_PER_MM
Definition: base_units.h:72
CADSTAR_PIN_TYPE
file: cadstar_archive_objects.h Contains common object definitions
#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 PartAcceptanceFieldName
const wxString PartNumberFieldName
const wxString PartNameFieldName
const wxString PartVersionFieldName
Loads a csa file into a KiCad SCHEMATIC object.
const SizeVec & GetSize() const
Definition: box2.h:196
coord_type GetTop() const
Definition: box2.h:219
Vec Centre() const
Definition: box2.h:87
coord_type GetRight() const
Definition: box2.h:207
coord_type GetLeft() const
Definition: box2.h:218
coord_type GetBottom() const
Definition: box2.h:212
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:623
static wxString EscapeFieldText(const wxString &aFieldText)
@ 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
static void FixTextPositionNoAlignment(EDA_TEXT *aKiCadTextItem, bool aInvertY=false)
Corrects the position of a text element that had NO_ALIGNMENT in CADSTAR.
static wxString generateLibName(const wxString &aRefName, const wxString &aAlternateName)
wxString LAYER_ID
ID of a Sheet (if schematic) or board Layer (if PCB)
@ 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
bool CheckFileHeader(const std::filesystem::path &aPath) const
CADSTAR_PARTS_LIB_MODEL ReadFile(const std::filesystem::path &aPath) const
static SCH_FIELD * addNewFieldToSymbol(const wxString &aFieldName, std::unique_ptr< LIB_SYMBOL > &aKiCadSymbol)
void Load(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet)
Loads a CADSTAR Schematic Archive file into the KiCad SCHEMATIC object given.
ROUTECODE getRouteCode(const ROUTECODE_ID &aCadstarRouteCodeID)
std::map< BLOCK_PIN_ID, SCH_HIERLABEL * > m_sheetPinMap
Cadstar->KiCad Sheet 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
Cadstar->KiCad Global Labels.
SCH_SYMBOL * loadSchematicSymbol(const SYMBOL &aCadstarSymbol, const LIB_SYMBOL &aKiCadPart, EDA_ANGLE &aComponentOrientation)
wxString getAttributeName(const ATTRIBUTE_ID &aCadstarAttributeID)
std::vector< LIB_SYMBOL * > m_loadedSymbols
Loaded symbols so far.
PART getPart(const PART_ID &aCadstarPartID)
std::vector< LAYER_ID > findOrphanSheets()
std::map< BUS_ID, std::shared_ptr< BUS_ALIAS > > m_busesMap
Cadstar->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
Cadstar->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)
std::map< wxString, TERMINAL_ID > PINNUM_TO_TERMINAL_MAP
std::map< SYMDEF_ID, PINNUM_TO_TERMINAL_MAP > m_symDefTerminalsMap
int getTextHeightFromTextCode(const TEXTCODE_ID &aCadstarTextCodeID)
void applyToLibraryFieldAttribute(const ATTRIBUTE_LOCATION &aCadstarAttrLoc, const VECTOR2I &aSymbolOrigin, SCH_FIELD *aKiCadField)
double getPolarRadius(const VECTOR2I &aPoint)
void setFootprintOnSymbol(std::unique_ptr< LIB_SYMBOL > &aKiCadSymbol, const wxString &aFootprintName, const wxString &aFootprintAlternate)
void applyTextCodeIfExists(EDA_TEXT *aKiCadTextItem, const TEXTCODE_ID &aCadstarTextCodeID)
void copySymbolItems(std::unique_ptr< LIB_SYMBOL > &aSourceSym, std::unique_ptr< LIB_SYMBOL > &aDestSym, int aDestUnit, bool aOverrideFields=true)
int getLineThickness(const LINECODE_ID &aCadstarLineCodeID)
TEXTCODE getTextCode(const TEXTCODE_ID &aCadstarTextCodeID)
SPIN_STYLE getSpinStyle(const long long &aCadstarOrientation, bool aMirror)
std::map< wxString, LIB_SYMBOL * > m_powerSymLibMap
NetName->KiCad Power Lib Symbol.
std::map< std::pair< wxString, wxString >, SYMDEF_ID > m_SymDefNamesCache
Cache storing symbol names and alternates to symdef IDs.
std::map< PART_ID, TERMINAL_TO_PINNUM_MAP > m_pinNumsMap
Cadstar Part->KiCad Pin number map.
void loadSheetAndChildSheets(LAYER_ID aCadstarSheetID, const VECTOR2I &aPosition, VECTOR2I aSheetSize, const SCH_SHEET_PATH &aParentSheet)
std::vector< LIB_SYMBOL * > LoadPartsLib(const wxString &aFilename)
ELECTRICAL_PINTYPE getKiCadPinType(const CADSTAR_PIN_TYPE &aPinType)
wxString m_footprintLibName
Name of the footprint library to prepend all footprints with.
void loadItemOntoKiCadSheet(LAYER_ID aCadstarSheetID, SCH_ITEM *aItem)
int getKiCadLength(long long aCadstarLength)
std::map< PART_ID, LIB_SYMBOL * > m_partMap
Cadstar->KiCad Parts.
bool isAttributeVisible(const ATTRIBUTE_ID &aCadstarAttributeID)
VECTOR2I getKiCadPoint(const VECTOR2I &aCadstarPoint)
EDA_ANGLE getAngle(const long long &aCadstarAngle)
std::map< wxString, SYMDEF_ID > m_DefaultSymDefNamesCache
Cache storing symbol names (default alternate) to symdef IDs.
void loadSymbolGateAndPartFields(const SYMDEF_ID &aSymdefID, const PART &aCadstarPart, const GATE_ID &aGateID, LIB_SYMBOL *aSymbol)
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)
std::map< PART_GATE_ID, SYMDEF_ID > m_partSymbolsMap
Map holding the symbols loaded so far for a particular PART_ID and GATE_ID.
LIB_SYMBOL * getScaledLibPart(const LIB_SYMBOL *aSymbol, long long aScalingFactorNumerator, long long aScalingFactorDenominator)
SYMDEF_ID getSymDefFromName(const wxString &aSymdefName, const wxString &aSymDefAlternate)
std::pair< VECTOR2I, VECTOR2I > getFigureExtentsKiCad(const FIGURE &aCadstarFigure)
std::map< LAYER_ID, SCH_SHEET * > m_sheetMap
Cadstar->KiCad Sheets.
void applyTextSettings(EDA_TEXT *aKiCadTextItem, const TEXTCODE_ID &aCadstarTextCodeID, const ALIGNMENT &aCadstarAlignment, const JUSTIFICATION &aCadstarJustification, const long long aCadstarOrientAngle=0, bool aMirrored=false, bool aInvertY=false)
POINT getLocationOfNetElement(const NET_SCH &aNet, const NETELEMENT_ID &aNetElementID)
void fixUpLibraryPins(LIB_SYMBOL *aSymbolToFix, int aGateNumber)
std::map< SYMDEF_ID, std::unique_ptr< const LIB_SYMBOL > > m_symDefMap
Cadstar->KiCad Lib Symbols loaded so far.
std::unique_ptr< LIB_SYMBOL > loadLibPart(const CADSTAR_PART_ENTRY &aPart)
ALIGNMENT rotate180(const ALIGNMENT &aCadstarAlignment)
long long getCadstarAngle(const EDA_ANGLE &aAngle)
void loadLibrarySymbolShapeVertices(const std::vector< VERTEX > &aCadstarVertices, const VECTOR2I &aSymbolOrigin, LIB_SYMBOL *aSymbol, int aGateNumber, int aLineThickness)
LINE_STYLE getLineStyle(const LINECODE_ID &aCadstarLineCodeID)
void loadChildSheets(LAYER_ID aCadstarSheetID, const SCH_SHEET_PATH &aSheet)
VECTOR2I m_designCenter
Required for calculating the offset to apply to the Cadstar design so that it fits in the KiCad canva...
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)
const LIB_SYMBOL * loadSymdef(const SYMDEF_ID &aSymdefID)
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:255
double AsDegrees() const
Definition: eda_angle.h:155
bool IsZero() const
Definition: eda_angle.h:175
EDA_ANGLE Normalize180()
Definition: eda_angle.h:294
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:88
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:100
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:103
EDA_ITEM * GetParent() const
Definition: eda_item.h:102
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:262
SHAPE_T GetShape() const
Definition: eda_shape.h:120
void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition: eda_shape.h:270
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:150
void SetStart(const VECTOR2I &aStart)
Definition: eda_shape.h:129
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:125
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:154
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
Definition: eda_shape.cpp:623
void SetFillMode(FILL_T aFill)
Definition: eda_shape.h:101
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:83
int GetTextHeight() const
Definition: eda_text.h:228
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:374
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:419
int GetTextWidth() const
Definition: eda_text.h:225
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition: eda_text.cpp:276
void SetTextWidth(int aWidth)
Definition: eda_text.cpp:397
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:245
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:197
void SetTextHeight(int aHeight)
Definition: eda_text.cpp:408
void SetBold(bool aBold)
Definition: eda_text.cpp:221
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:183
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:205
int GetTextThickness() const
Definition: eda_text.h:126
void SetItalic(bool aItalic)
Definition: eda_text.cpp:213
void SetMultilineAllowed(bool aAllow)
Definition: eda_text.cpp:260
VECTOR2I GetTextSize() const
Definition: eda_text.h:222
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:268
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
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int SetLibItemName(const UTF8 &aLibItemName)
Override the library item name portion of the LIB_ID to aLibItemName.
Definition: lib_id.cpp:110
UTF8 Format() const
Definition: lib_id.cpp:118
Define a library symbol object.
Definition: lib_symbol.h:77
void SetUnitCount(int aCount, bool aDuplicateDrawItems=true)
Set the units per symbol count.
std::vector< SCH_PIN * > GetPins(int aUnit=0, int aBodyStyle=0) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:982
SCH_FIELD & GetValueField() const
Return reference to the value field.
std::vector< SCH_PIN * > GetAllLibPins() const
Return a list of pin pointers for all units / converts.
void SetPower()
Definition: lib_symbol.cpp:679
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:486
wxString GetName() const override
Definition: lib_symbol.h:136
SCH_FIELD & GetReferenceField() const
Return reference to the reference designator field.
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
Definition: lib_symbol.cpp:969
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:563
void sort()
Definition: multivector.h:248
ITERATOR_BASE< SCH_ITEM, MULTIVECTOR< SCH_ITEM, FIRST_TYPE_VAL, LAST_TYPE_VAL >, typename ITEM_PTR_VECTOR::iterator > ITERATOR
The const iterator.
Definition: multivector.h:165
ITERATOR end(int aType=UNDEFINED_TYPE)
Definition: multivector.h:195
ITERATOR begin(int aType=UNDEFINED_TYPE)
Definition: multivector.h:189
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:59
void SetHeightMils(double aHeightInMils)
Definition: page_info.cpp:261
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition: page_info.h:171
void SetWidthMils(double aWidthInMils)
Definition: page_info.cpp:247
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:62
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:135
virtual std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:84
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:75
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:90
void SetSize(const VECTOR2I &aSize)
Definition: sch_bus_entry.h:74
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:1149
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_field.cpp:1387
void SetName(const wxString &aName)
Definition: sch_field.cpp:1128
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1138
void SetSpinStyle(SPIN_STYLE aSpinStyle) override
Definition: sch_label.cpp:1903
void SetSpinStyle(SPIN_STYLE aSpinStyle) override
Definition: sch_label.cpp:2084
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:174
int GetUnit() const
Definition: sch_item.h:237
void SetLayer(SCH_LAYER_ID aLayer)
Definition: sch_item.h:290
virtual void SetUnit(int aUnit)
Definition: sch_item.h:236
SCH_ITEM * Duplicate(bool doClone=false) const
Routine to create a new copy of given item.
Definition: sch_item.cpp:120
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_junction.h:108
void SetShape(LABEL_FLAG_SHAPE aShape)
Definition: sch_label.h:173
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_label.cpp:412
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_label.cpp:639
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Definition: sch_label.cpp:338
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:136
void SetLineWidth(const int aSize)
Definition: sch_line.cpp:321
VECTOR2I GetEndPoint() const
Definition: sch_line.h:140
VECTOR2I GetStartPoint() const
Definition: sch_line.h:135
void SetLineStyle(const LINE_STYLE aStyle)
Definition: sch_line.cpp:292
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:141
void SetNumber(const wxString &aNumber)
Definition: sch_pin.cpp:465
const PAGE_INFO & GetPageSettings() const
Definition: sch_screen.h:131
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:150
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:115
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
Definition: sch_screen.cpp:313
void SetPosition(const VECTOR2I &aPos) override
Definition: sch_shape.h:71
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: sch_shape.cpp:63
void AddPoint(const VECTOR2I &aPosition)
Definition: sch_shape.cpp:642
VECTOR2I GetPosition() const override
Definition: sch_shape.h:70
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:372
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:764
VECTOR2I GetSize() const
Definition: sch_sheet.h:112
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:110
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:376
void SetFields(const std::vector< SCH_FIELD > &aFields)
Set multiple schematic fields.
Definition: sch_sheet.cpp:352
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:162
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_sheet.cpp:609
static bool ClassOf(const EDA_ITEM *aItem)
Definition: sch_sheet.h:72
Schematic symbol object.
Definition: sch_symbol.h:108
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_symbol.h:783
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:571
SCH_FIELD * FindField(const wxString &aFieldName, bool aIncludeDefaultFields=true, bool aCaseInsensitive=false)
Search for a SCH_FIELD with aFieldName.
Definition: sch_symbol.cpp:993
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:910
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
Definition: sch_symbol.cpp:310
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:750
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:973
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:958
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:216
VECTOR2I GetPosition() const override
Definition: sch_text.h:141
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_text.h:142
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_text.cpp:422
const VECTOR2I & GetArcMid() const
Definition: shape_arc.h:115
const VECTOR2I & GetP1() const
Definition: shape_arc.h:114
const VECTOR2I & GetP0() const
Definition: shape_arc.h:113
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.
std::vector< INTERSECTION > INTERSECTIONS
const std::vector< VECTOR2I > & CPoints() const
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
SPIN_STYLE MirrorX()
Mirror the label spin style across the X axis or simply swaps up and bottom.
Definition: sch_label.cpp:173
SPIN_STYLE MirrorY()
Mirror the label spin style across the Y axis or simply swaps left and right.
Definition: sch_label.cpp:189
SPIN_STYLE RotateCCW()
Definition: sch_label.cpp:157
Simple container to manage line stroke parameters.
Definition: stroke_params.h:81
void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
Definition: symbol.h:123
void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition: symbol.h:129
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:265
#define DEFAULT_WIRE_WIDTH_MILS
The default bus width in mils. (can be changed in preference menu)
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:435
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:437
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition: eda_angle.h:432
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition: eda_angle.h:431
static constexpr EDA_ANGLE ANGLE_45
Definition: eda_angle.h:436
static constexpr EDA_ANGLE ANGLE_270
Definition: eda_angle.h:440
static constexpr EDA_ANGLE ANGLE_180
Definition: eda_angle.h:439
static constexpr EDA_ANGLE ANGLE_135
Definition: eda_angle.h:438
static const std::string KiCadSchematicFileExtension
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:39
SCH_LAYER_ID
Eeschema drawing layers.
Definition: layer_ids.h:353
@ LAYER_DEVICE
Definition: layer_ids.h:370
@ LAYER_WIRE
Definition: layer_ids.h:356
@ LAYER_NOTES
Definition: layer_ids.h:371
@ LAYER_BUS
Definition: layer_ids.h:357
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
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition: pin_type.h:36
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ 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
#define SIM_DEVICE_FIELD
Definition: sim_model.h:52
#define SIM_PARAMS_FIELD
Definition: sim_model.h:55
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:54
LINE_STYLE
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.
GRID ScreenGrid
From CADSTAR Help: "There is one Screen Grid, which is visible as dots on the screen.
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.
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.
SHAPE_ARC BuildArc(const VECTOR2I &aPrevPoint, const std::function< VECTOR2I(const VECTOR2I &)> aCadstarToKicadPointCallback) const
CADSTAR Parts Library (*.lib) model - a data structure describing the contents of the file format.
std::vector< CADSTAR_PART_ENTRY > m_PartEntries
std::string m_ComponentStem
std::map< std::string, std::vector< CADSTAR_PART_PIN > > m_HiddenPins
Pins with an implied electrical connection to a net, not part of any symbol (Note: we probably will n...
std::map< std::string, CADSTAR_ATTRIBUTE_VALUE > m_SchAttributes
Dollar sign ($) line $[!]<SCM Attribute name>(<Attribute value>) Attributes related to the schematic ...
std::map< std::string, CADSTAR_ATTRIBUTE_VALUE > m_SchAndPcbAttributes
At symbol (@) line [@[!]<SCM/PCB Attribute name>(<Attribute value>)] Attributes related to the PCB co...
std::vector< CADSTAR_PART_SYMBOL_ENTRY > m_Symbols
Symbols that form this part.
std::map< std::string, std::string > m_UserAttributes
Star (*) line *<User-defined name> This line is ignored by CADSTAR.
std::map< long, std::string > m_PinNamesMap
Map of pin identifiers to alphanumeric pin names Pin names can be a maximum of 10 characters (Typical...
std::optional< std::string > m_AcceptancePartName
bool m_PinsVisible
std::optional< std::string > m_Pcb_alternate
std::optional< std::string > m_Version
std::string m_Name
std::optional< std::string > m_Description
std::optional< std::string > m_Number
std::string m_Pcb_component
std::optional< std::string > m_SpiceModel
std::map< std::string, CADSTAR_ATTRIBUTE_VALUE > m_PcbAttributes
Percentage sign (%) line %[!]<PCB Attribute name>(<Attribute value>) Attributes related to the PCB co...
std::optional< std::string > m_Value
std::map< std::string, CADSTAR_ATTRIBUTE_VALUE > m_PartAttributes
Tilde (~) line ~[!]<Parts Library Attribute Name>(<Attribute Value>) Attributes related to the Part i...
std::map< long, std::string > m_PinLabelsMap
Map of pin identifiers to alphanumeric pin labels.
std::string m_SymbolName
std::vector< CADSTAR_PART_PIN > m_Pins
std::optional< std::string > m_SymbolAlternateName
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:99
const double IU_PER_MILS
Definition: base_units.h:77
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
constexpr int delta
@ 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)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:228
@ SCH_SYMBOL_T
Definition: typeinfo.h:172
@ SCH_FIELD_T
Definition: typeinfo.h:150
@ SCH_SHAPE_T
Definition: typeinfo.h:149
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:173
@ SCH_TEXT_T
Definition: typeinfo.h:151
int sign(T val)
Definition: util.h:168
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:118
int LexicographicalCompare(const VECTOR2< T > &aA, const VECTOR2< T > &aB)
Definition: vector2d.h:539
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588
Definition of file extensions used in Kicad.