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 <lib_shape.h>
34#include <lib_text.h>
35#include <macros.h>
36#include <progress_reporter.h>
37#include <string_utils.h>
38#include <sch_bus_entry.h>
39#include <sch_edit_frame.h> //SYMBOL_ORIENTATION_T
40#include <sch_io_mgr.h>
41#include <sch_junction.h>
42#include <sch_line.h>
43#include <sch_screen.h>
44#include <sch_shape.h>
45#include <sch_sheet.h>
46#include <sch_sheet_path.h>
47#include <sch_sheet_pin.h>
48#include <sch_label.h>
49#include <schematic.h>
50#include <sim/sim_model.h>
51#include <trigo.h>
53
54
55const wxString PartNameFieldName = "Part Name";
56const wxString PartNumberFieldName = "Part Number";
57const wxString PartVersionFieldName = "Part Version";
58const wxString PartAcceptanceFieldName = "Part Acceptance";
59
60
61std::vector<LIB_SYMBOL*> CADSTAR_SCH_ARCHIVE_LOADER::LoadPartsLib( const wxString& aFilename )
62{
64 m_progressReporter->SetNumPhases( 3 ); // (0) Read csa, (1) Parse csa, (3) Load lib
65
66 Parse();
67
69
70 if( !p.CheckFileHeader( aFilename.utf8_string() ) )
72 _( "The selected file does not appear to be a CADSTAR parts Library file" ) );
73
74 // TODO: we could add progress reporting for reading .lib
75 CADSTAR_PARTS_LIB_MODEL csLib = p.ReadFile( aFilename.utf8_string() );
76
78 {
80 long numSteps = csLib.m_PartEntries.size();
82 }
83
84 std::vector<LIB_SYMBOL*> retVal;
85
86 for( const CADSTAR_PART_ENTRY& part : csLib.m_PartEntries )
87 {
88 std::unique_ptr<LIB_SYMBOL> loadedPart = loadLibPart( part );
89
90 checkPoint();
91
92 if( loadedPart )
93 retVal.push_back( loadedPart.release() );
94 }
95
96 return retVal;
97}
98
99
100std::unique_ptr<LIB_SYMBOL>
102{
103 wxString escapedPartName = EscapeString( aPart.m_Name, CTX_LIBID );
104 std::unique_ptr<LIB_SYMBOL> retSym;
105
106 int unit = 0;
107
108 for( const CADSTAR_PART_SYMBOL_ENTRY& sym : aPart.m_Symbols )
109 {
110 ++unit;
111 wxString alternateName = sym.m_SymbolAlternateName.value_or( "" );
112 SYMDEF_ID symbolID = getSymDefFromName( sym.m_SymbolName, alternateName );
113
114 if( !Library.SymbolDefinitions.count( symbolID ) )
115 {
117 wxString::Format( _( "Unable to find symbol %s, referenced by part %s. The "
118 "part was not loaded." ),
119 generateLibName( sym.m_SymbolName, alternateName ),
120 aPart.m_Name ),
122
123 return nullptr;
124 }
125
126 // Load the graphical symbol for this gate
127 std::unique_ptr<LIB_SYMBOL> kiSymDef( loadSymdef( symbolID )->Duplicate() );
128
129 if( sym.m_Pins.size() != kiSymDef->GetPinCount() )
130 {
132 wxString::Format( _( "Inconsitent pin numbers in symbol %s compared to the one "
133 "defined in part %s. The part was not loaded." ),
134 generateLibName( sym.m_SymbolName, alternateName ),
135 aPart.m_Name ),
137
138 return nullptr;
139 }
140
141 wxASSERT( m_symDefTerminalsMap.count( symbolID ) ); //loadSymDef should have populated this
142
143
144 // Update the pin numbers to match those defined in the Cadstar part
145 for( auto& [storedPinNum, termID] : m_symDefTerminalsMap[symbolID] )
146 {
147 wxCHECK( termID > 0 && sym.m_Pins.size() >= size_t( termID ), nullptr );
148 LIB_PIN* pin = kiSymDef->GetPin( storedPinNum );
149 size_t termIdx = size_t( termID ) - 1;
150
151 // For now leave numerical pin number. Otherwise, when loading the
152 // .cpa file we won't be able to link up to the footprint pads, but if
153 // we solve this, we could then load alphanumeric pin numbers as below:
154 //
155 // if( aPart.m_PinNamesMap.count( termID ) )
156 // partPinNum = wxString( aPart.m_PinNamesMap.at( termID ) );
157 //
158 wxString partPinNum = wxString::Format( "%ld", sym.m_Pins[termIdx].m_Identifier );
159 pin->SetNumber( partPinNum );
160
161 if( aPart.m_PinNamesMap.count( termID ) )
162 pin->SetName( HandleTextOverbar( aPart.m_PinNamesMap.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() );
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<LIB_PIN> pin = std::make_unique<LIB_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( LIB_ITEM* item : aDestSym->GetUnitDrawItems( aDestUnit, 0 /*aConvert*/ ) )
287 aDestSym->RemoveDrawItem( item );
288
289 // Copy all draw items
290 for( LIB_ITEM* newItem : aSourceSym->GetUnitDrawItems( 1, 0 /*aConvert*/ ) )
291 {
292 LIB_ITEM* itemCopy = static_cast<LIB_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<LIB_FIELD*> fieldsToCopy;
302 aSourceSym->GetFields( fieldsToCopy );
303
304 for( LIB_FIELD* templateField : fieldsToCopy )
305 {
306 LIB_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( "." ) + 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->SetTextSpinStyle( 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 LIB_PINS 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->SetTextSpinStyle( 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
1071 applyTextSettings( label,
1072 bus.BusLabel.TextCodeID,
1073 bus.BusLabel.Alignment,
1074 bus.BusLabel.Justification );
1075
1076 // Re-set bus name as it might have been "double-escaped" after applyTextSettings
1077 label->SetText( wxT( "{" ) + busname + wxT( "}" ) );
1078
1079 // Note orientation of the bus label will be determined in loadNets
1080 // (the position of the wire will determine how best to place the bus label)
1081 }
1082 }
1083 }
1084}
1085
1086
1088{
1089 for( std::pair<NET_ID, NET_SCH> netPair : Schematic.Nets )
1090 {
1091 NET_SCH net = netPair.second;
1092 wxString netName = net.Name;
1093 std::map<NETELEMENT_ID, SCH_LABEL*> netlabels;
1094
1095 if( netName.IsEmpty() )
1096 netName = wxString::Format( "$%ld", net.SignalNum );
1097
1098 netName = HandleTextOverbar( netName );
1099
1100 for( std::pair<NETELEMENT_ID, NET_SCH::SYM_TERM> terminalPair : net.Terminals )
1101 {
1102 NET_SCH::SYM_TERM netTerm = terminalPair.second;
1103
1104 if( m_powerSymMap.find( netTerm.SymbolID ) != m_powerSymMap.end() )
1105 {
1106 SCH_FIELD* val = m_powerSymMap.at( netTerm.SymbolID )->GetField( VALUE_FIELD );
1107 val->SetText( netName );
1108 val->SetBold( false );
1109 val->SetVisible( false );
1110
1111 if( netTerm.HasNetLabel )
1112 {
1113 val->SetVisible( true );
1114 val->SetPosition( getKiCadPoint( netTerm.NetLabel.Position ) );
1115
1116 applyTextSettings( val,
1117 netTerm.NetLabel.TextCodeID,
1118 netTerm.NetLabel.Alignment,
1119 netTerm.NetLabel.Justification,
1120 netTerm.NetLabel.OrientAngle,
1121 netTerm.NetLabel.Mirror );
1122 }
1123 }
1124 else if( m_globalLabelsMap.find( netTerm.SymbolID ) != m_globalLabelsMap.end() )
1125 {
1126 m_globalLabelsMap.at( netTerm.SymbolID )->SetText( netName );
1127
1128 LAYER_ID sheet = Schematic.Symbols.at( netTerm.SymbolID ).LayerID;
1129
1130 if( m_sheetMap.count( sheet ) )
1131 {
1132 SCH_SCREEN* screen = m_sheetMap.at( sheet )->GetScreen();
1133
1134 // autoplace intersheet refs again since we've changed the name
1135 m_globalLabelsMap.at( netTerm.SymbolID )->AutoplaceFields( screen, false );
1136 }
1137 }
1138 else if( !net.Name.IsEmpty() && Schematic.Symbols.count( netTerm.SymbolID )
1139 && netTerm.HasNetLabel )
1140 {
1141 // This is a named net that connects to a schematic symbol pin - we need to put a label
1142 SCH_LABEL* label = new SCH_LABEL();
1143 label->SetText( netName );
1144
1145 POINT pinLocation = getLocationOfNetElement( net, netTerm.ID );
1146 label->SetPosition( getKiCadPoint( pinLocation ) );
1147 label->SetVisible( true );
1148
1149 applyTextSettings( label, netTerm.NetLabel.TextCodeID, netTerm.NetLabel.Alignment,
1150 netTerm.NetLabel.Justification );
1151
1152 netlabels.insert( { netTerm.ID, label } );
1153
1154 LAYER_ID sheet = Schematic.Symbols.at( netTerm.SymbolID ).LayerID;
1155 m_sheetMap.at( sheet )->GetScreen()->Append( label );
1156 }
1157 }
1158
1159 auto getHierarchicalLabel =
1160 [&]( NETELEMENT_ID aNode ) -> SCH_HIERLABEL*
1161 {
1162 if( aNode.Contains( "BLKT" ) )
1163 {
1164 NET_SCH::BLOCK_TERM blockTerm = net.BlockTerminals.at( aNode );
1165 BLOCK_PIN_ID blockPinID = std::make_pair( blockTerm.BlockID,
1166 blockTerm.TerminalID );
1167
1168 if( m_sheetPinMap.find( blockPinID ) != m_sheetPinMap.end() )
1169 return m_sheetPinMap.at( blockPinID );
1170 }
1171
1172 return nullptr;
1173 };
1174
1175 //Add net name to all hierarchical pins (block terminals in CADSTAR)
1176 for( std::pair<NETELEMENT_ID, NET_SCH::BLOCK_TERM> blockPair : net.BlockTerminals )
1177 {
1178 SCH_HIERLABEL* label = getHierarchicalLabel( blockPair.first );
1179
1180 if( label )
1181 label->SetText( netName );
1182 }
1183
1184 // Load all bus entries and add net label if required
1185 for( std::pair<NETELEMENT_ID, NET_SCH::BUS_TERM> busPair : net.BusTerminals )
1186 {
1187 NET_SCH::BUS_TERM busTerm = busPair.second;
1188 BUS bus = Schematic.Buses.at( busTerm.BusID );
1189
1190 if( !alg::contains( m_busesMap.at( bus.ID )->Members(), netName ) )
1191 m_busesMap.at( bus.ID )->Members().emplace_back( netName );
1192
1193 SCH_BUS_WIRE_ENTRY* busEntry =
1194 new SCH_BUS_WIRE_ENTRY( getKiCadPoint( busTerm.FirstPoint ), false );
1195
1196 VECTOR2I size =
1197 getKiCadPoint( busTerm.SecondPoint ) - getKiCadPoint( busTerm.FirstPoint );
1198 busEntry->SetSize( VECTOR2I( size.x, size.y ) );
1199
1200 m_sheetMap.at( bus.LayerID )->GetScreen()->Append( busEntry );
1201
1202 // Always add a label at bus terminals to ensure connectivity.
1203 // If the original design does not have a label, just make it very small
1204 // to keep connectivity but make the design look visually similar to
1205 // the original.
1206 SCH_LABEL* label = new SCH_LABEL();
1207 label->SetText( netName );
1208 label->SetPosition( getKiCadPoint( busTerm.SecondPoint ) );
1209 label->SetVisible( true );
1210
1211 if( busTerm.HasNetLabel )
1212 {
1213 applyTextSettings( label,
1214 busTerm.NetLabel.TextCodeID,
1215 busTerm.NetLabel.Alignment,
1216 busTerm.NetLabel.Justification );
1217 }
1218 else
1219 {
1221 }
1222
1223 netlabels.insert( { busTerm.ID, label } );
1224 m_sheetMap.at( bus.LayerID )->GetScreen()->Append( label );
1225 }
1226
1227 for( std::pair<NETELEMENT_ID, NET_SCH::DANGLER> danglerPair : net.Danglers )
1228 {
1229 NET_SCH::DANGLER dangler = danglerPair.second;
1230
1231 SCH_LABEL* label = new SCH_LABEL();
1232 label->SetPosition( getKiCadPoint( dangler.Position ) );
1233 label->SetVisible( true );
1234
1235 if( dangler.HasNetLabel )
1236 {
1237 applyTextSettings( label,
1238 dangler.NetLabel.TextCodeID,
1239 dangler.NetLabel.Alignment,
1240 dangler.NetLabel.Justification );
1241 }
1242
1243 label->SetText( netName ); // set text after applying settings to avoid double-escaping
1244 netlabels.insert( { dangler.ID, label } );
1245
1246 m_sheetMap.at( dangler.LayerID )->GetScreen()->Append( label );
1247 }
1248
1249 for( NET_SCH::CONNECTION_SCH conn : net.Connections )
1250 {
1251 if( conn.LayerID == wxT( "NO_SHEET" ) )
1252 continue; // No point loading virtual connections. KiCad handles that internally
1253
1254 POINT start = getLocationOfNetElement( net, conn.StartNode );
1255 POINT end = getLocationOfNetElement( net, conn.EndNode );
1256
1257 if( start.x == UNDEFINED_VALUE || end.x == UNDEFINED_VALUE )
1258 continue;
1259
1260 // Connections in CADSTAR are always implied between symbols even if the route
1261 // doesn't start and end exactly at the connection points
1262 if( conn.Path.size() < 1 || conn.Path.front() != start )
1263 conn.Path.insert( conn.Path.begin(), start );
1264
1265 if( conn.Path.size() < 2 || conn.Path.back() != end )
1266 conn.Path.push_back( end );
1267
1268 bool firstPt = true;
1269 bool secondPt = false;
1270 VECTOR2I last;
1271 SCH_LINE* wire = nullptr;
1272
1273 SHAPE_LINE_CHAIN wireChain; // Create a temp. line chain representing the connection
1274
1275 for( POINT pt : conn.Path )
1276 {
1277 wireChain.Append( getKiCadPoint( pt ) );
1278 }
1279
1280 // AUTO-FIX SHEET PINS
1281 //--------------------
1282 // KiCad constrains the sheet pin on the edge of the sheet object whereas in
1283 // CADSTAR it can be anywhere. Let's find the intersection of the wires with the sheet
1284 // and place the hierarchical
1285 std::vector<NETELEMENT_ID> nodes;
1286 nodes.push_back( conn.StartNode );
1287 nodes.push_back( conn.EndNode );
1288
1289 for( NETELEMENT_ID node : nodes )
1290 {
1291 SCH_HIERLABEL* sheetPin = getHierarchicalLabel( node );
1292
1293 if( sheetPin )
1294 {
1295 if( sheetPin->Type() == SCH_SHEET_PIN_T
1296 && SCH_SHEET::ClassOf( sheetPin->GetParent() ) )
1297 {
1298 SCH_SHEET* parentSheet = static_cast<SCH_SHEET*>( sheetPin->GetParent() );
1299 VECTOR2I sheetSize = parentSheet->GetSize();
1300 VECTOR2I sheetPosition = parentSheet->GetPosition();
1301
1302 int leftSide = sheetPosition.x;
1303 int rightSide = sheetPosition.x + sheetSize.x;
1304 int topSide = sheetPosition.y;
1305 int botSide = sheetPosition.y + sheetSize.y;
1306
1307 SHAPE_LINE_CHAIN sheetEdge;
1308
1309 sheetEdge.Append( leftSide, topSide );
1310 sheetEdge.Append( rightSide, topSide );
1311 sheetEdge.Append( rightSide, botSide );
1312 sheetEdge.Append( leftSide, botSide );
1313 sheetEdge.Append( leftSide, topSide );
1314
1315 SHAPE_LINE_CHAIN::INTERSECTIONS wireToSheetIntersects;
1316
1317 if( !wireChain.Intersect( sheetEdge, wireToSheetIntersects ) )
1318 {
1319 // The block terminal is outside the block shape in the original
1320 // CADSTAR design. Since KiCad's Sheet Pin will already be constrained
1321 // on the edge, we will simply join to it with a straight line.
1322 if( node == conn.StartNode )
1323 wireChain = wireChain.Reverse();
1324
1325 wireChain.Append( sheetPin->GetPosition() );
1326
1327 if( node == conn.StartNode )
1328 wireChain = wireChain.Reverse();
1329 }
1330 else
1331 {
1332 // The block terminal is either inside or on the shape edge. Lets use
1333 // the first intersection point.
1334 VECTOR2I intsctPt = wireToSheetIntersects.at( 0 ).p;
1335 int intsctIndx = wireChain.FindSegment( intsctPt );
1336 wxASSERT_MSG( intsctIndx != -1, "Can't find intersecting segment" );
1337
1338 if( node == conn.StartNode )
1339 wireChain.Replace( 0, intsctIndx, intsctPt );
1340 else
1341 wireChain.Replace( intsctIndx + 1, /*end index*/ -1, intsctPt );
1342
1343 sheetPin->SetPosition( intsctPt );
1344 }
1345 }
1346 }
1347 }
1348
1349 auto fixNetLabelsAndSheetPins =
1350 [&]( const EDA_ANGLE& aWireAngle, NETELEMENT_ID& aNetEleID )
1351 {
1352 TEXT_SPIN_STYLE spin = getSpinStyle( aWireAngle );
1353
1354 if( netlabels.find( aNetEleID ) != netlabels.end() )
1355 netlabels.at( aNetEleID )->SetTextSpinStyle( spin.MirrorY() );
1356
1357 SCH_HIERLABEL* sheetPin = getHierarchicalLabel( aNetEleID );
1358
1359 if( sheetPin )
1360 sheetPin->SetTextSpinStyle( spin.MirrorX() );
1361 };
1362
1363 // Now we can load the wires and fix the label orientations
1364 for( const VECTOR2I& pt : wireChain.CPoints() )
1365 {
1366 if( firstPt )
1367 {
1368 last = pt;
1369 firstPt = false;
1370 secondPt = true;
1371 continue;
1372 }
1373
1374 if( secondPt )
1375 {
1376 secondPt = false;
1377
1378 EDA_ANGLE wireAngle( last - pt );
1379 fixNetLabelsAndSheetPins( wireAngle, conn.StartNode );
1380 }
1381
1382 wire = new SCH_LINE();
1383
1384 wire->SetStartPoint( last );
1385 wire->SetEndPoint( pt );
1386 wire->SetLayer( LAYER_WIRE );
1387
1388 if( !conn.ConnectionLineCode.IsEmpty() )
1389 wire->SetLineWidth( getLineThickness( conn.ConnectionLineCode ) );
1390
1391 last = pt;
1392
1393 m_sheetMap.at( conn.LayerID )->GetScreen()->Append( wire );
1394 }
1395
1396 //Fix labels on the end wire
1397 if( wire )
1398 {
1399 EDA_ANGLE wireAngle( wire->GetEndPoint() - wire->GetStartPoint() );
1400 fixNetLabelsAndSheetPins( wireAngle, conn.EndNode );
1401 }
1402 }
1403
1404 for( std::pair<NETELEMENT_ID, NET_SCH::JUNCTION_SCH> juncPair : net.Junctions )
1405 {
1406 NET_SCH::JUNCTION_SCH junc = juncPair.second;
1407
1408 SCH_JUNCTION* kiJunc = new SCH_JUNCTION();
1409
1410 kiJunc->SetPosition( getKiCadPoint( junc.Location ) );
1411 m_sheetMap.at( junc.LayerID )->GetScreen()->Append( kiJunc );
1412
1413 if( junc.HasNetLabel )
1414 {
1415 // In CADSTAR the label can be placed anywhere, but in KiCad it has to be placed
1416 // in the same location as the junction for it to be connected to it.
1417 SCH_LABEL* label = new SCH_LABEL();
1418 label->SetText( netName );
1419 label->SetPosition( getKiCadPoint( junc.Location ) );
1420 label->SetVisible( true );
1421
1422 EDA_ANGLE labelAngle = getAngle( junc.NetLabel.OrientAngle );
1423 TEXT_SPIN_STYLE spin = getSpinStyle( labelAngle );
1424 label->SetTextSpinStyle( spin );
1425
1426 m_sheetMap.at( junc.LayerID )->GetScreen()->Append( label );
1427 }
1428 }
1429 }
1430}
1431
1432
1434{
1435 for( std::pair<FIGURE_ID, FIGURE> figPair : Schematic.Figures )
1436 {
1437 FIGURE fig = figPair.second;
1438
1439 loadFigure( fig, fig.LayerID, LAYER_NOTES );
1440 }
1441}
1442
1443
1445{
1446 for( std::pair<TEXT_ID, TEXT> textPair : Schematic.Texts )
1447 {
1448 TEXT txt = textPair.second;
1449
1450 SCH_TEXT* kiTxt = getKiCadSchText( txt );
1451 loadItemOntoKiCadSheet( txt.LayerID, kiTxt );
1452 }
1453}
1454
1455
1457{
1458 for( std::pair<DOCUMENTATION_SYMBOL_ID, DOCUMENTATION_SYMBOL> docSymPair :
1460 {
1461 DOCUMENTATION_SYMBOL docSym = docSymPair.second;
1462
1463 if( Library.SymbolDefinitions.find( docSym.SymdefID ) == Library.SymbolDefinitions.end() )
1464 {
1465 m_reporter->Report( wxString::Format( _( "Documentation Symbol '%s' refers to symbol "
1466 "definition ID '%s' which does not exist in "
1467 "the library. The symbol was not loaded." ),
1468 docSym.ID,
1469 docSym.SymdefID ),
1471 continue;
1472 }
1473
1474 SYMDEF_SCM docSymDef = Library.SymbolDefinitions.at( docSym.SymdefID );
1475 VECTOR2I moveVector = getKiCadPoint( docSym.Origin ) - getKiCadPoint( docSymDef.Origin );
1476 EDA_ANGLE rotationAngle = getAngle( docSym.OrientAngle );
1477 double scalingFactor = (double) docSym.ScaleRatioNumerator
1478 / (double) docSym.ScaleRatioDenominator;
1479 VECTOR2I centreOfTransform = getKiCadPoint( docSymDef.Origin );
1480 bool mirrorInvert = docSym.Mirror;
1481
1482 for( std::pair<FIGURE_ID, FIGURE> figPair : docSymDef.Figures )
1483 {
1484 FIGURE fig = figPair.second;
1485
1486 loadFigure( fig, docSym.LayerID, LAYER_NOTES, moveVector, rotationAngle, scalingFactor,
1487 centreOfTransform, mirrorInvert );
1488 }
1489
1490 for( std::pair<TEXT_ID, TEXT> textPair : docSymDef.Texts )
1491 {
1492 TEXT txt = textPair.second;
1493
1494 txt.Mirror = ( txt.Mirror ) ? !mirrorInvert : mirrorInvert;
1495 txt.OrientAngle = docSym.OrientAngle - txt.OrientAngle;
1496
1497 SCH_TEXT* kiTxt = getKiCadSchText( txt );
1498
1499 VECTOR2I newPosition = applyTransform( kiTxt->GetPosition(), moveVector, rotationAngle,
1500 scalingFactor, centreOfTransform, mirrorInvert );
1501
1502 int newTxtWidth = KiROUND( kiTxt->GetTextWidth() * scalingFactor );
1503 int newTxtHeight = KiROUND( kiTxt->GetTextHeight() * scalingFactor );
1504 int newTxtThickness = KiROUND( kiTxt->GetTextThickness() * scalingFactor );
1505
1506 kiTxt->SetPosition( newPosition );
1507 kiTxt->SetTextWidth( newTxtWidth );
1508 kiTxt->SetTextHeight( newTxtHeight );
1509 kiTxt->SetTextThickness( newTxtThickness );
1510
1511 loadItemOntoKiCadSheet( docSym.LayerID, kiTxt );
1512 }
1513 }
1514}
1515
1516
1518{
1519 auto findAndReplaceTextField =
1520 [&]( TEXT_FIELD_NAME aField, wxString aValue )
1521 {
1522 if( m_context.TextFieldToValuesMap.find( aField ) != m_context.TextFieldToValuesMap.end() )
1523 {
1524 if( m_context.TextFieldToValuesMap.at( aField ) != aValue )
1525 {
1526 m_context.TextFieldToValuesMap.at( aField ) = aValue;
1527 m_context.InconsistentTextFields.insert( aField );
1528 return false;
1529 }
1530 }
1531 else
1532 {
1533 m_context.TextFieldToValuesMap.insert( { aField, aValue } );
1534 }
1535
1536 return true;
1537 };
1538
1539 PROJECT* pj = &m_schematic->Prj();
1540
1541 if( pj )
1542 {
1543 std::map<wxString, wxString>& txtVars = pj->GetTextVars();
1544
1545 // Most of the design text fields can be derived from other elements
1546 if( Schematic.VariantHierarchy.Variants.size() > 0 )
1547 {
1548 VARIANT loadedVar = Schematic.VariantHierarchy.Variants.begin()->second;
1549
1550 findAndReplaceTextField( TEXT_FIELD_NAME::VARIANT_NAME, loadedVar.Name );
1551 findAndReplaceTextField( TEXT_FIELD_NAME::VARIANT_DESCRIPTION, loadedVar.Description );
1552 }
1553
1554 findAndReplaceTextField( TEXT_FIELD_NAME::DESIGN_TITLE, Header.JobTitle );
1555
1556 for( std::pair<TEXT_FIELD_NAME, wxString> txtvalue : m_context.TextFieldToValuesMap )
1557 {
1558 wxString varName = CADSTAR_TO_KICAD_FIELDS.at( txtvalue.first );
1559 wxString varValue = txtvalue.second;
1560
1561 txtVars.insert( { varName, varValue } );
1562 }
1563
1564 for( std::pair<wxString, wxString> txtvalue : m_context.FilenamesToTextMap )
1565 {
1566 wxString varName = txtvalue.first;
1567 wxString varValue = txtvalue.second;
1568
1569 txtVars.insert( { varName, varValue } );
1570 }
1571 }
1572 else
1573 {
1574 m_reporter->Report( _( "Text Variables could not be set as there is no project attached." ),
1576 }
1577}
1578
1579
1580LIB_FIELD*
1582 std::unique_ptr<LIB_SYMBOL>& aKiCadSymbol )
1583{
1584 // First Check if field already exists
1585 LIB_FIELD* existingField = aKiCadSymbol->FindField( aFieldName );
1586
1587 if( existingField != nullptr )
1588 return existingField;
1589
1590 int newfieldID = aKiCadSymbol->GetFieldCount();
1591 LIB_FIELD* newfield = new LIB_FIELD( aKiCadSymbol.get(), newfieldID );
1592 newfield->SetName( aFieldName );
1593 newfield->SetVisible( false );
1594 aKiCadSymbol->AddField( newfield );
1595 /*
1596 @todo we should load that a field is a URL by checking if it starts with "Link"
1597 e.g.:
1598 if( aFieldName.Lower().StartsWith( "link" ) )
1599 newfield->SetAsURL*/
1600
1601 return newfield;
1602}
1603
1604
1606{
1607 wxCHECK( Library.SymbolDefinitions.find( aSymdefID ) != Library.SymbolDefinitions.end(), nullptr );
1608
1609 if( m_symDefMap.count( aSymdefID ) )
1610 return m_symDefMap.at( aSymdefID ).get(); // return a non-owning ptr
1611
1612 SYMDEF_SCM csSym = Library.SymbolDefinitions.at( aSymdefID );
1613 std::unique_ptr<LIB_SYMBOL> kiSym = std::make_unique<LIB_SYMBOL>( csSym.BuildLibName() );
1614 const int gateNumber = 1; // Always load to gate "A" - we will change the unit later
1615
1616 // Load Graphical Figures
1617 for( std::pair<FIGURE_ID, FIGURE> figPair : csSym.Figures )
1618 {
1619 FIGURE fig = figPair.second;
1620 int lineThickness = getLineThickness( fig.LineCodeID );
1621 PLOT_DASH_TYPE linestyle = getLineStyle( fig.LineCodeID );
1622
1623 if( fig.Shape.Type == SHAPE_TYPE::OPENSHAPE )
1624 {
1625 loadLibrarySymbolShapeVertices( fig.Shape.Vertices, csSym.Origin, kiSym.get(),
1626 gateNumber,
1627 lineThickness );
1628 }
1629 else
1630 {
1631 LIB_SHAPE* shape = new LIB_SHAPE( kiSym.get(), SHAPE_T::POLY );
1633 [&]( const VECTOR2I& aPt )
1634 {
1635 return getKiCadLibraryPoint( aPt, csSym.Origin );
1636 },
1637 ARC_ACCURACY ) );
1638
1639 shape->SetUnit( gateNumber );
1640
1641 shape->SetStroke( STROKE_PARAMS( lineThickness, linestyle ) );
1642
1643 if( fig.Shape.Type == SHAPE_TYPE::SOLID )
1644 shape->SetFillMode( FILL_T::FILLED_SHAPE );
1645 else if( fig.Shape.Type == SHAPE_TYPE::OUTLINE )
1646 shape->SetFillMode( FILL_T::NO_FILL );
1647 else if( fig.Shape.Type == SHAPE_TYPE::HATCHED ) // We don't have an equivalent
1648 shape->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
1649
1650 kiSym->AddDrawItem( shape );
1651 }
1652 }
1653
1654 PINNUM_TO_TERMINAL_MAP pinNumToTerminals;
1655
1656 // Load Pins
1657 for( std::pair<TERMINAL_ID, TERMINAL> termPair : csSym.Terminals )
1658 {
1659 TERMINAL term = termPair.second;
1660 wxString pinNum = wxString::Format( "%ld", term.ID );
1661 wxString pinName = wxEmptyString;
1662 std::unique_ptr<LIB_PIN> pin = std::make_unique<LIB_PIN>( kiSym.get() );
1663
1664 // Assume passive pin for now (we will set it later once we load the parts)
1665 pin->SetType( ELECTRICAL_PINTYPE::PT_PASSIVE );
1666
1667 pin->SetPosition( getKiCadLibraryPoint( term.Position, csSym.Origin ) );
1668 pin->SetLength( 0 ); //CADSTAR Pins are just a point (have no length)
1669 pin->SetShape( GRAPHIC_PINSHAPE::LINE );
1670 pin->SetUnit( gateNumber );
1671 pin->SetNumber( pinNum );
1672 pin->SetName( pinName );
1673
1674 // TC0 is the default CADSTAR text size for name/number if none specified
1675 int pinNumberHeight = getTextHeightFromTextCode( wxT( "TC0" ) );
1676 int pinNameHeight = getTextHeightFromTextCode( wxT( "TC0" ) );
1677
1678 if( csSym.PinNumberLocations.count( term.ID ) )
1679 {
1680 PIN_NUM_LABEL_LOC pinNumLocation = csSym.PinNumberLocations.at( term.ID );
1681 pinNumberHeight = getTextHeightFromTextCode( pinNumLocation.TextCodeID );
1682 }
1683
1684 if( csSym.PinLabelLocations.count( term.ID ) )
1685 {
1686 PIN_NUM_LABEL_LOC pinNameLocation = csSym.PinLabelLocations.at( term.ID );
1687 pinNameHeight = getTextHeightFromTextCode( pinNameLocation.TextCodeID );
1688 }
1689
1690 pin->SetNumberTextSize( pinNumberHeight );
1691 pin->SetNameTextSize( pinNameHeight );
1692
1693 pinNumToTerminals.insert( { pin->GetNumber(), term.ID } );
1694 kiSym->AddDrawItem( pin.release() );
1695 }
1696
1697 m_symDefTerminalsMap.insert( { aSymdefID, pinNumToTerminals } );
1698 fixUpLibraryPins( kiSym.get(), gateNumber );
1699
1700
1701 // Load Text items
1702 for( std::pair<TEXT_ID, TEXT> textPair : csSym.Texts )
1703 {
1704 TEXT csText = textPair.second;
1705
1706 std::unique_ptr<LIB_TEXT> libtext = std::make_unique<LIB_TEXT>( kiSym.get() );
1707 libtext->SetText( csText.Text );
1708 libtext->SetUnit( gateNumber );
1709 libtext->SetPosition( getKiCadLibraryPoint( csText.Position, csSym.Origin ) );
1710 libtext->SetMultilineAllowed( true ); // temporarily so that we calculate bbox correctly
1711
1712 applyTextSettings( libtext.get(), csText.TextCodeID, csText.Alignment, csText.Justification,
1713 csText.OrientAngle, csText.Mirror );
1714
1715 // Split out multi line text items into individual text elements
1716 if( csText.Text.Contains( "\n" ) )
1717 {
1718 wxArrayString strings;
1719 wxStringSplit( csText.Text, strings, '\n' );
1720 wxPoint firstLinePos;
1721
1722 for( size_t ii = 0; ii < strings.size(); ++ii )
1723 {
1724 BOX2I bbox = libtext->GetTextBox( ii, true );
1725 VECTOR2I linePos = { bbox.GetLeft(), -bbox.GetBottom() };
1726
1727 RotatePoint( linePos, libtext->GetTextPos(), -libtext->GetTextAngle() );
1728
1729 LIB_TEXT* textLine = static_cast<LIB_TEXT*>( libtext->Clone() );
1730 textLine->SetText( strings[ii] );
1733 textLine->SetTextPos( linePos );
1734
1735 // Multiline text not allowed in LIB_TEXT
1736 textLine->SetMultilineAllowed( false );
1737 kiSym->AddDrawItem( textLine );
1738 }
1739 }
1740 else
1741 {
1742 // Multiline text not allowed in LIB_TEXT
1743 libtext->SetMultilineAllowed( false );
1744 kiSym->AddDrawItem( libtext.release() );
1745 }
1746 }
1747
1748 // CADSTAR uses TC1 when fields don't have explicit text/attribute location
1749 static const TEXTCODE_ID defaultTextCode = "TC1";
1750
1751 // Load field locations (Attributes in CADSTAR)
1752
1753 // Symbol name (e.g. R1)
1754 if( csSym.TextLocations.count( SYMBOL_NAME_ATTRID ) )
1755 {
1756 TEXT_LOCATION& textLoc = csSym.TextLocations.at( SYMBOL_NAME_ATTRID );
1757 applyToLibraryFieldAttribute( textLoc, csSym.Origin, &kiSym->GetReferenceField() );
1758 }
1759 else
1760 {
1761 applyTextCodeIfExists( &kiSym->GetReferenceField(), defaultTextCode );
1762 }
1763
1764 // Always add the part name field (even if it doesn't have a specific location defined)
1765 LIB_FIELD* partField = addNewFieldToSymbol( PartNameFieldName, kiSym );
1766 wxCHECK( partField, nullptr );
1767 wxASSERT( partField->GetName() == PartNameFieldName );
1768
1769 if( csSym.TextLocations.count( PART_NAME_ATTRID ) )
1770 {
1771 TEXT_LOCATION& textLoc = csSym.TextLocations.at( PART_NAME_ATTRID );
1772 applyToLibraryFieldAttribute( textLoc, csSym.Origin, partField );
1773 }
1774 else
1775 {
1776 applyTextCodeIfExists( partField, defaultTextCode );
1777 }
1778
1780
1781
1782 for( auto& [attributeId, textLocation] : csSym.TextLocations )
1783 {
1784 if( attributeId == PART_NAME_ATTRID || attributeId == SYMBOL_NAME_ATTRID
1785 || attributeId == SIGNALNAME_ORIGIN_ATTRID || attributeId == LINK_ORIGIN_ATTRID )
1786 {
1787 continue;
1788 }
1789
1790 wxString attributeName = getAttributeName( attributeId );
1791 LIB_FIELD* field = addNewFieldToSymbol( attributeName, kiSym );
1792 applyToLibraryFieldAttribute( textLocation, csSym.Origin, field );
1793 }
1794
1795
1796 for( auto& [attributeId, attrValue] : csSym.AttributeValues )
1797 {
1798 if( attributeId == PART_NAME_ATTRID || attributeId == SYMBOL_NAME_ATTRID
1799 || attributeId == SIGNALNAME_ORIGIN_ATTRID || attributeId == LINK_ORIGIN_ATTRID )
1800 {
1801 continue;
1802 }
1803
1804 wxString attributeName = getAttributeName( attributeId );
1805 LIB_FIELD* field = addNewFieldToSymbol( attributeName, kiSym );
1806
1807 if( attrValue.HasLocation )
1808 applyToLibraryFieldAttribute( attrValue.AttributeLocation, csSym.Origin, field );
1809 else
1810 applyTextCodeIfExists( field, defaultTextCode );
1811 }
1812
1813
1814 m_symDefMap.insert( { aSymdefID, std::move( kiSym ) } );
1815
1816 return m_symDefMap.at( aSymdefID ).get(); // return a non-owning ptr
1817}
1818
1819
1821 const PART& aCadstarPart,
1822 const GATE_ID& aGateID,
1823 LIB_SYMBOL* aSymbol )
1824{
1825 wxCHECK( Library.SymbolDefinitions.find( aSymdefID ) != Library.SymbolDefinitions.end(), /*void*/ );
1826
1827 std::unique_ptr<LIB_SYMBOL> kiSymDef( loadSymdef( aSymdefID )->Duplicate() );
1828 wxCHECK( kiSymDef, /*void*/ );
1829
1830 //todo: need to use unique_ptr more. For now just create it here and release at end of function
1831 std::unique_ptr<LIB_SYMBOL> tempSymbol( aSymbol );
1832
1833 // Update the pin numbers to match those defined in the Cadstar part
1834 TERMINAL_TO_PINNUM_MAP pinNumMap;
1835
1836 for( auto&& [storedPinNum, termID] : m_symDefTerminalsMap[aSymdefID] )
1837 {
1838 PART::DEFINITION::PIN csPin = getPartDefinitionPin( aCadstarPart, aGateID, termID );
1839 LIB_PIN* pin = kiSymDef->GetPin( storedPinNum );
1840
1841 wxString pinName = HandleTextOverbar( csPin.Label );
1842 wxString pinNum = HandleTextOverbar( csPin.Name );
1843
1844 if( pinNum.IsEmpty() )
1845 {
1846 if( !csPin.Identifier.IsEmpty() )
1847 pinNum = csPin.Identifier;
1848 else if( csPin.ID == UNDEFINED_VALUE )
1849 pinNum = wxString::Format( "%ld", termID );
1850 else
1851 pinNum = wxString::Format( "%ld", csPin.ID );
1852 }
1853
1854 pin->SetType( getKiCadPinType( csPin.Type ) );
1855 pin->SetNumber( pinNum );
1856 pin->SetName( pinName );
1857
1858 pinNumMap.insert( { termID, pinNum } );
1859 }
1860
1861 m_pinNumsMap.insert( { aCadstarPart.ID + aGateID, pinNumMap } );
1862
1863 // COPY ITEMS
1864 int gateNumber = getKiCadUnitNumberFromGate( aGateID );
1865 copySymbolItems( kiSymDef, tempSymbol, gateNumber );
1866
1867 // Hide the value field for now (it might get unhidden if an attribute exists in the cadstar
1868 // design with the text "Value"
1869 tempSymbol->GetValueField().SetVisible( false );
1870
1871
1872 LIB_FIELD* partNameField = tempSymbol->FindField( PartNameFieldName );
1873
1874 if( partNameField )
1875 partNameField->SetText( EscapeFieldText( aCadstarPart.Name ) );
1876
1877 const POINT& symDefOrigin = Library.SymbolDefinitions.at( aSymdefID ).Origin;
1878 wxString footprintRefName = wxEmptyString;
1879 wxString footprintAlternateName = wxEmptyString;
1880
1881 auto loadLibraryField = [&]( const ATTRIBUTE_VALUE& aAttributeVal )
1882 {
1883 wxString attrName = getAttributeName( aAttributeVal.AttributeID );
1884
1885 // Remove invalid field characters
1886 wxString attributeValue = aAttributeVal.Value;
1887 attributeValue.Replace( wxT( "\n" ), wxT( "\\n" ) );
1888 attributeValue.Replace( wxT( "\r" ), wxT( "\\r" ) );
1889 attributeValue.Replace( wxT( "\t" ), wxT( "\\t" ) );
1890
1891 //TODO: Handle "links": In cadstar a field can be a "link" if its name starts
1892 // with the characters "Link ". Need to figure out how to convert them to
1893 // equivalent in KiCad.
1894
1895 if( attrName == wxT( "(PartDefinitionNameStem)" ) )
1896 {
1897 //Space not allowed in Reference field
1898 attributeValue.Replace( wxT( " " ), "_" );
1899 tempSymbol->GetReferenceField().SetText( attributeValue );
1900 return;
1901 }
1902 else if( attrName == wxT( "(PartDescription)" ) )
1903 {
1904 tempSymbol->SetDescription( attributeValue );
1905 return;
1906 }
1907 else if( attrName == wxT( "(PartDefinitionReferenceName)" ) )
1908 {
1909 footprintRefName = attributeValue;
1910 return;
1911 }
1912 else if( attrName == wxT( "(PartDefinitionAlternateName)" ) )
1913 {
1914 footprintAlternateName = attributeValue;
1915 return;
1916 }
1917
1918 bool attrIsNew = tempSymbol->FindField( attrName ) == nullptr;
1919 LIB_FIELD* attrField = addNewFieldToSymbol( attrName, tempSymbol );
1920
1921 wxASSERT( attrField->GetName() == attrName );
1922 attrField->SetText( aAttributeVal.Value );
1923 attrField->SetUnit( gateNumber );
1924
1925 const ATTRIBUTE_ID& attrid = aAttributeVal.AttributeID;
1926 attrField->SetVisible( isAttributeVisible( attrid ) );
1927
1928 if( aAttributeVal.HasLocation )
1929 {
1930 // Check if the part itself defined a location for the field
1931 applyToLibraryFieldAttribute( aAttributeVal.AttributeLocation, symDefOrigin,
1932 attrField );
1933 }
1934 else if( attrIsNew )
1935 {
1936 attrField->SetVisible( false );
1937 applyTextSettings( attrField, wxT( "TC1" ), ALIGNMENT::NO_ALIGNMENT,
1939 }
1940 };
1941
1942 // Load all attributes in the Part Definition
1943 for( auto& [attrId, attrVal] : aCadstarPart.Definition.AttributeValues )
1944 loadLibraryField( attrVal );
1945
1946 // Load all attributes in the Part itself.
1947 for( auto& [attrId, attrVal] : aCadstarPart.AttributeValues )
1948 loadLibraryField( attrVal );
1949
1950 setFootprintOnSymbol( tempSymbol, footprintRefName, footprintAlternateName );
1951
1952 if( aCadstarPart.Definition.HidePinNames )
1953 {
1954 tempSymbol->SetShowPinNames( false );
1955 tempSymbol->SetShowPinNumbers( false );
1956 }
1957
1958 aSymbol = tempSymbol.release();
1959}
1960
1961
1962void CADSTAR_SCH_ARCHIVE_LOADER::setFootprintOnSymbol( std::unique_ptr<LIB_SYMBOL>& aKiCadSymbol,
1963 const wxString& aFootprintName,
1964 const wxString& aFootprintAlternate )
1965{
1966 wxString fpNameInLibrary = generateLibName( aFootprintName, aFootprintAlternate );
1967
1968 if( !fpNameInLibrary.IsEmpty() )
1969 {
1970 wxArrayString fpFilters;
1971 fpFilters.Add( aFootprintName ); // In cadstar one footprint has several "alternates"
1972
1973 if( !aFootprintAlternate.IsEmpty() )
1974 fpFilters.Add( fpNameInLibrary );
1975
1976 aKiCadSymbol->SetFPFilters( fpFilters );
1977
1978 LIB_ID libID( m_footprintLibName, fpNameInLibrary );
1979 aKiCadSymbol->GetFootprintField().SetText( libID.Format() );
1980 }
1981}
1982
1983
1984void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
1985 VECTOR2I aSymbolOrigin,
1986 LIB_SYMBOL* aSymbol,
1987 int aGateNumber,
1988 int aLineThickness )
1989{
1990 const VERTEX* prev = &aCadstarVertices.at( 0 );
1991 const VERTEX* cur;
1992
1993 wxASSERT_MSG( prev->Type == VERTEX_TYPE::POINT, "First vertex should always be a point." );
1994
1995 for( size_t i = 1; i < aCadstarVertices.size(); i++ )
1996 {
1997 cur = &aCadstarVertices.at( i );
1998
1999 LIB_SHAPE* shape = nullptr;
2000 bool cw = false;
2001 VECTOR2I startPoint = getKiCadLibraryPoint( prev->End, aSymbolOrigin );
2002 VECTOR2I endPoint = getKiCadLibraryPoint( cur->End, aSymbolOrigin );
2003 VECTOR2I centerPoint;
2004
2007 {
2008 centerPoint = ( startPoint + endPoint ) / 2;
2009 }
2010 else
2011 {
2012 centerPoint = getKiCadLibraryPoint( cur->Center, aSymbolOrigin );
2013 }
2014
2015
2016 switch( cur->Type )
2017 {
2018 case VERTEX_TYPE::POINT:
2019 shape = new LIB_SHAPE( aSymbol, SHAPE_T::POLY );
2020 shape->AddPoint( startPoint );
2021 shape->AddPoint( endPoint );
2022 break;
2023
2026 cw = true;
2028
2031 shape = new LIB_SHAPE( aSymbol, SHAPE_T::ARC );
2032
2033 shape->SetPosition( centerPoint );
2034
2035 if( cw )
2036 {
2037 shape->SetStart( endPoint );
2038 shape->SetEnd( startPoint );
2039 }
2040 else
2041 {
2042 shape->SetStart( startPoint );
2043 shape->SetEnd( endPoint );
2044 }
2045
2046 break;
2047 }
2048
2049 shape->SetUnit( aGateNumber );
2050 shape->SetStroke( STROKE_PARAMS( aLineThickness, PLOT_DASH_TYPE::SOLID ) );
2051 aSymbol->AddDrawItem( shape );
2052
2053 prev = cur;
2054 }
2055}
2056
2057
2059 const ATTRIBUTE_LOCATION& aCadstarAttrLoc, VECTOR2I aSymbolOrigin, LIB_FIELD* aKiCadField )
2060{
2061 aKiCadField->SetTextPos( getKiCadLibraryPoint( aCadstarAttrLoc.Position, aSymbolOrigin ) );
2062
2063 applyTextSettings( aKiCadField,
2064 aCadstarAttrLoc.TextCodeID,
2065 aCadstarAttrLoc.Alignment,
2066 aCadstarAttrLoc.Justification,
2067 aCadstarAttrLoc.OrientAngle,
2068 aCadstarAttrLoc.Mirror );
2069}
2070
2071
2073 const LIB_SYMBOL& aKiCadPart,
2074 EDA_ANGLE& aComponentOrientation )
2075{
2076 LIB_ID libId;
2077 libId.SetLibItemName( aKiCadPart.GetName() );
2078
2079 int unit = getKiCadUnitNumberFromGate( aCadstarSymbol.GateID );
2080
2081 SCH_SHEET_PATH sheetpath;
2082 SCH_SHEET* kiSheet = m_sheetMap.at( aCadstarSymbol.LayerID );
2083 m_rootSheet->LocatePathOfScreen( kiSheet->GetScreen(), &sheetpath );
2084
2085 SCH_SYMBOL* symbol = new SCH_SYMBOL( aKiCadPart, libId, &sheetpath, unit );
2086
2087 if( aCadstarSymbol.IsComponent )
2088 {
2089 symbol->SetRef( &sheetpath, aCadstarSymbol.ComponentRef.Designator );
2090 }
2091
2092 symbol->SetPosition( getKiCadPoint( aCadstarSymbol.Origin ) );
2093
2094 EDA_ANGLE compAngle = getAngle( aCadstarSymbol.OrientAngle );
2095 int compOrientation = 0;
2096
2097 if( aCadstarSymbol.Mirror )
2098 {
2099 compAngle = -compAngle;
2100 compOrientation += SYMBOL_ORIENTATION_T::SYM_MIRROR_Y;
2101 }
2102
2103 compOrientation += getComponentOrientation( compAngle, aComponentOrientation );
2104 EDA_ANGLE test1( compAngle );
2105 EDA_ANGLE test2( aComponentOrientation );
2106
2107 if( test1.Normalize180() != test2.Normalize180() )
2108 {
2109 m_reporter->Report( wxString::Format( _( "Symbol '%s' is rotated by an angle of %.1f "
2110 "degrees in the original CADSTAR design but "
2111 "KiCad only supports rotation angles multiples "
2112 "of 90 degrees. The connecting wires will need "
2113 "manual fixing." ),
2114 aCadstarSymbol.ComponentRef.Designator,
2115 compAngle.AsDegrees() ),
2117 }
2118
2119 symbol->SetOrientation( compOrientation );
2120
2121 if( m_sheetMap.find( aCadstarSymbol.LayerID ) == m_sheetMap.end() )
2122 {
2123 m_reporter->Report( wxString::Format( _( "Symbol '%s' references sheet ID '%s' which does "
2124 "not exist in the design. The symbol was not "
2125 "loaded." ),
2126 aCadstarSymbol.ComponentRef.Designator,
2127 aCadstarSymbol.LayerID ),
2129
2130 delete symbol;
2131 return nullptr;
2132 }
2133
2134 wxString gate = ( aCadstarSymbol.GateID.IsEmpty() ) ? wxString( wxT( "A" ) ) : aCadstarSymbol.GateID;
2135 wxString partGateIndex = aCadstarSymbol.PartRef.RefID + gate;
2136
2137 //Handle pin swaps
2138 if( m_pinNumsMap.find( partGateIndex ) != m_pinNumsMap.end() )
2139 {
2140 TERMINAL_TO_PINNUM_MAP termNumMap = m_pinNumsMap.at( partGateIndex );
2141
2142 std::map<wxString, LIB_PIN*> pinNumToLibPinMap;
2143
2144 for( auto& term : termNumMap )
2145 {
2146 wxString pinNum = term.second;
2147 pinNumToLibPinMap.insert( { pinNum,
2148 symbol->GetLibSymbolRef()->GetPin( term.second ) } );
2149 }
2150
2151 auto replacePinNumber =
2152 [&]( wxString aOldPinNum, wxString aNewPinNum )
2153 {
2154 if( aOldPinNum == aNewPinNum )
2155 return;
2156
2157 LIB_PIN* libpin = pinNumToLibPinMap.at( aOldPinNum );
2158 libpin->SetNumber( HandleTextOverbar( aNewPinNum ) );
2159 };
2160
2161 //Older versions of Cadstar used pin numbers
2162 for( auto& pinPair : aCadstarSymbol.PinNumbers )
2163 {
2164 SYMBOL::PIN_NUM pin = pinPair.second;
2165
2166 replacePinNumber( termNumMap.at( pin.TerminalID ),
2167 wxString::Format( "%ld", pin.PinNum ) );
2168 }
2169
2170 //Newer versions of Cadstar use pin names
2171 for( auto& pinPair : aCadstarSymbol.PinNames )
2172 {
2173 SYMPINNAME_LABEL pin = pinPair.second;
2174 replacePinNumber( termNumMap.at( pin.TerminalID ), pin.NameOrLabel );
2175 }
2176
2177 symbol->UpdatePins();
2178 }
2179
2180 kiSheet->GetScreen()->Append( symbol );
2181
2182 return symbol;
2183}
2184
2185
2187 const EDA_ANGLE& aComponentOrientation,
2188 bool aIsMirrored,
2189 SCH_FIELD* aKiCadField )
2190{
2191 aKiCadField->SetPosition( getKiCadPoint( aCadstarAttrLoc.Position ) );
2192 aKiCadField->SetVisible( true );
2193
2194 ALIGNMENT alignment = aCadstarAttrLoc.Alignment;
2195 EDA_ANGLE textAngle = getAngle( aCadstarAttrLoc.OrientAngle );
2196
2197 if( aIsMirrored )
2198 {
2199 // We need to change the aligment when the symbol is mirrored based on the text orientation
2200 // To ensure the anchor point is the same in KiCad.
2201
2202 int textIsVertical = KiROUND( textAngle.AsDegrees() / 90.0 ) % 2;
2203
2204 if( textIsVertical )
2205 alignment = rotate180( alignment );
2206
2207 alignment = mirrorX( alignment );
2208 }
2209
2210 applyTextSettings( aKiCadField,
2211 aCadstarAttrLoc.TextCodeID,
2212 alignment,
2213 aCadstarAttrLoc.Justification,
2214 getCadstarAngle( textAngle - aComponentOrientation ),
2215 aCadstarAttrLoc.Mirror );
2216}
2217
2218
2220 EDA_ANGLE& aReturnedOrientation )
2221{
2222 int compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_0;
2223
2224 EDA_ANGLE oDeg = aOrientAngle;
2225 oDeg.Normalize180();
2226
2227 if( oDeg >= -ANGLE_45 && oDeg <= ANGLE_45 )
2228 {
2229 compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_0;
2230 aReturnedOrientation = ANGLE_0;
2231 }
2232 else if( oDeg >= ANGLE_45 && oDeg <= ANGLE_135 )
2233 {
2234 compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_90;
2235 aReturnedOrientation = ANGLE_90;
2236 }
2237 else if( oDeg >= ANGLE_135 || oDeg <= -ANGLE_135 )
2238 {
2239 compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_180;
2240 aReturnedOrientation = ANGLE_180;
2241 }
2242 else
2243 {
2244 compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_270;
2245 aReturnedOrientation = ANGLE_270;
2246 }
2247
2248 return compOrientation;
2249}
2250
2251
2254 const NETELEMENT_ID& aNetElementID )
2255{
2256 // clang-format off
2257 auto logUnknownNetElementError =
2258 [&]()
2259 {
2260 m_reporter->Report( wxString::Format( _( "Net %s references unknown net element %s. "
2261 "The net was not properly loaded and may "
2262 "require manual fixing." ),
2263 getNetName( aNet ),
2264 aNetElementID ),
2266
2267 return POINT();
2268 };
2269 // clang-format on
2270
2271 if( aNetElementID.Contains( "J" ) ) // Junction
2272 {
2273 if( aNet.Junctions.find( aNetElementID ) == aNet.Junctions.end() )
2274 return logUnknownNetElementError();
2275
2276 return aNet.Junctions.at( aNetElementID ).Location;
2277 }
2278 else if( aNetElementID.Contains( "P" ) ) // Terminal/Pin of a symbol
2279 {
2280 if( aNet.Terminals.find( aNetElementID ) == aNet.Terminals.end() )
2281 return logUnknownNetElementError();
2282
2283 SYMBOL_ID symid = aNet.Terminals.at( aNetElementID ).SymbolID;
2284 TERMINAL_ID termid = aNet.Terminals.at( aNetElementID ).TerminalID;
2285
2286 if( Schematic.Symbols.find( symid ) == Schematic.Symbols.end() )
2287 return logUnknownNetElementError();
2288
2289 SYMBOL sym = Schematic.Symbols.at( symid );
2290 SYMDEF_ID symdefid = sym.SymdefID;
2291 VECTOR2I symbolOrigin = sym.Origin;
2292
2293 if( Library.SymbolDefinitions.find( symdefid ) == Library.SymbolDefinitions.end() )
2294 return logUnknownNetElementError();
2295
2296 VECTOR2I libpinPosition =
2297 Library.SymbolDefinitions.at( symdefid ).Terminals.at( termid ).Position;
2298 VECTOR2I libOrigin = Library.SymbolDefinitions.at( symdefid ).Origin;
2299
2300 VECTOR2I pinOffset = libpinPosition - libOrigin;
2301 pinOffset.x = ( pinOffset.x * sym.ScaleRatioNumerator ) / sym.ScaleRatioDenominator;
2302 pinOffset.y = ( pinOffset.y * sym.ScaleRatioNumerator ) / sym.ScaleRatioDenominator;
2303
2304 VECTOR2I pinPosition = symbolOrigin + pinOffset;
2305 EDA_ANGLE compAngle = getAngle( sym.OrientAngle );
2306
2307 if( sym.Mirror )
2308 pinPosition.x = ( 2 * symbolOrigin.x ) - pinPosition.x;
2309
2310 EDA_ANGLE adjustedOrientation;
2311 getComponentOrientation( compAngle, adjustedOrientation );
2312
2313 RotatePoint( pinPosition, symbolOrigin, -adjustedOrientation );
2314
2315 POINT retval;
2316 retval.x = pinPosition.x;
2317 retval.y = pinPosition.y;
2318
2319 return retval;
2320 }
2321 else if( aNetElementID.Contains( "BT" ) ) // Bus Terminal
2322 {
2323 if( aNet.BusTerminals.find( aNetElementID ) == aNet.BusTerminals.end() )
2324 return logUnknownNetElementError();
2325
2326 return aNet.BusTerminals.at( aNetElementID ).SecondPoint;
2327 }
2328 else if( aNetElementID.Contains( "BLKT" ) ) // Block Terminal (sheet hierarchy connection)
2329 {
2330 if( aNet.BlockTerminals.find( aNetElementID ) == aNet.BlockTerminals.end() )
2331 return logUnknownNetElementError();
2332
2333 BLOCK_ID blockid = aNet.BlockTerminals.at( aNetElementID ).BlockID;
2334 TERMINAL_ID termid = aNet.BlockTerminals.at( aNetElementID ).TerminalID;
2335
2336 if( Schematic.Blocks.find( blockid ) == Schematic.Blocks.end() )
2337 return logUnknownNetElementError();
2338
2339 return Schematic.Blocks.at( blockid ).Terminals.at( termid ).Position;
2340 }
2341 else if( aNetElementID.Contains( "D" ) ) // Dangler
2342 {
2343 if( aNet.Danglers.find( aNetElementID ) == aNet.Danglers.end() )
2344 return logUnknownNetElementError();
2345
2346 return aNet.Danglers.at( aNetElementID ).Position;
2347 }
2348 else
2349 {
2350 return logUnknownNetElementError();
2351 }
2352}
2353
2354
2356{
2357 wxString netname = aNet.Name;
2358
2359 if( netname.IsEmpty() )
2360 netname = wxString::Format( "$%ld", aNet.SignalNum );
2361
2362 return netname;
2363}
2364
2365
2366void CADSTAR_SCH_ARCHIVE_LOADER::loadShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
2367 LINECODE_ID aCadstarLineCodeID,
2368 LAYER_ID aCadstarSheetID,
2369 SCH_LAYER_ID aKiCadSchLayerID,
2370 const VECTOR2I& aMoveVector,
2371 const EDA_ANGLE& aRotation,
2372 const double& aScalingFactor,
2373 const VECTOR2I& aTransformCentre,
2374 const bool& aMirrorInvert )
2375{
2376 int lineWidth = KiROUND( getLineThickness( aCadstarLineCodeID ) * aScalingFactor );
2377 PLOT_DASH_TYPE lineStyle = getLineStyle( aCadstarLineCodeID );
2378
2379 const VERTEX* prev = &aCadstarVertices.at( 0 );
2380 const VERTEX* cur;
2381
2382 wxASSERT_MSG( prev->Type == VERTEX_TYPE::POINT,
2383 "First vertex should always be a point vertex" );
2384
2385 auto pointTransform =
2386 [&]( const VECTOR2I& aV )
2387 {
2388 return applyTransform( getKiCadPoint( aV ), aMoveVector, aRotation,
2389 aScalingFactor, aTransformCentre, aMirrorInvert );
2390 };
2391
2392 for( size_t ii = 1; ii < aCadstarVertices.size(); ii++ )
2393 {
2394 cur = &aCadstarVertices.at( ii );
2395
2396 VECTOR2I transformedStartPoint = pointTransform( prev->End );
2397 VECTOR2I transformedEndPoint = pointTransform( cur->End );
2398
2399 switch( cur->Type )
2400 {
2405 {
2406 SHAPE_ARC tempArc = cur->BuildArc( transformedStartPoint, pointTransform );
2407
2408 SCH_SHAPE* arcShape = new SCH_SHAPE( SHAPE_T::ARC, lineWidth );
2409 arcShape->SetArcGeometry( tempArc.GetP0(), tempArc.GetArcMid(), tempArc.GetP1() );
2410
2411 loadItemOntoKiCadSheet( aCadstarSheetID, arcShape );
2412 }
2413 break;
2414
2415 case VERTEX_TYPE::POINT:
2416 {
2417 SCH_LINE* segment = new SCH_LINE();
2418
2419 segment->SetLayer( aKiCadSchLayerID );
2420 segment->SetLineWidth( lineWidth );
2421 segment->SetLineStyle( lineStyle );
2422
2423 segment->SetStartPoint( transformedStartPoint );
2424 segment->SetEndPoint( transformedEndPoint );
2425
2426 loadItemOntoKiCadSheet( aCadstarSheetID, segment );
2427 }
2428 break;
2429
2430 default:
2431 wxFAIL_MSG( "Unknown CADSTAR Vertex type" );
2432 }
2433
2434
2435 prev = cur;
2436 }
2437}
2438
2439
2441 const LAYER_ID& aCadstarSheetIDOverride,
2442 SCH_LAYER_ID aKiCadSchLayerID,
2443 const VECTOR2I& aMoveVector,
2444 const EDA_ANGLE& aRotation,
2445 const double& aScalingFactor,
2446 const VECTOR2I& aTransformCentre,
2447 const bool& aMirrorInvert )
2448{
2449 loadShapeVertices( aCadstarFigure.Shape.Vertices, aCadstarFigure.LineCodeID,
2450 aCadstarSheetIDOverride, aKiCadSchLayerID, aMoveVector, aRotation,
2451 aScalingFactor, aTransformCentre, aMirrorInvert );
2452
2453 for( CUTOUT cutout : aCadstarFigure.Shape.Cutouts )
2454 {
2455 loadShapeVertices( cutout.Vertices, aCadstarFigure.LineCodeID, aCadstarSheetIDOverride,
2456 aKiCadSchLayerID, aMoveVector, aRotation, aScalingFactor,
2457 aTransformCentre, aMirrorInvert );
2458 }
2459}
2460
2461
2463 const VECTOR2I& aPosition,
2464 VECTOR2I aSheetSize,
2465 const SCH_SHEET_PATH& aParentSheet )
2466{
2467 wxCHECK_MSG( m_sheetMap.find( aCadstarSheetID ) == m_sheetMap.end(), ,
2468 "Sheet already loaded!" );
2469
2470 SCH_SHEET* sheet = new SCH_SHEET(
2471 /* aParent */ aParentSheet.Last(),
2472 /* aPosition */ aPosition,
2473 /* aSize */ VECTOR2I( aSheetSize ) );
2474 SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
2475 SCH_SHEET_PATH instance( aParentSheet );
2476
2477 sheet->SetScreen( screen );
2478
2479 wxString name = Sheets.SheetNames.at( aCadstarSheetID );
2480
2481 SCH_FIELD& sheetNameField = sheet->GetFields()[SHEETNAME];
2482 SCH_FIELD& filenameField = sheet->GetFields()[SHEETFILENAME];
2483
2484 sheetNameField.SetText( name );
2485
2486 int sheetNum = getSheetNumber( aCadstarSheetID );
2487 wxString loadedFilename = wxFileName( Filename ).GetName();
2488 std::string filename = wxString::Format( "%s_%02d", loadedFilename, sheetNum ).ToStdString();
2489
2490 ReplaceIllegalFileNameChars( &filename );
2491 filename += wxT( "." ) + KiCadSchematicFileExtension;
2492
2493 filenameField.SetText( filename );
2494
2495 wxFileName fn( m_schematic->Prj().GetProjectPath() + filename );
2496 sheet->GetScreen()->SetFileName( fn.GetFullPath() );
2497 aParentSheet.Last()->GetScreen()->Append( sheet );
2498 instance.push_back( sheet );
2499
2500 wxString pageNumStr = wxString::Format( "%d", getSheetNumber( aCadstarSheetID ) );
2501 instance.SetPageNumber( pageNumStr );
2502
2503 sheet->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
2504
2505 m_sheetMap.insert( { aCadstarSheetID, sheet } );
2506
2507 loadChildSheets( aCadstarSheetID, instance );
2508}
2509
2510
2512 const SCH_SHEET_PATH& aSheet )
2513{
2514 wxCHECK_MSG( m_sheetMap.find( aCadstarSheetID ) != m_sheetMap.end(), ,
2515 "FIXME! Parent sheet should be loaded before attempting to load subsheets" );
2516
2517 for( std::pair<BLOCK_ID, BLOCK> blockPair : Schematic.Blocks )
2518 {
2519 BLOCK& block = blockPair.second;
2520
2521 if( block.LayerID == aCadstarSheetID && block.Type == BLOCK::TYPE::CHILD )
2522 {
2523 if( block.AssocLayerID == wxT( "NO_LINK" ) )
2524 {
2525 if( block.Figures.size() > 0 )
2526 {
2527 m_reporter->Report( wxString::Format( _( "The block ID %s (Block name: '%s') "
2528 "is drawn on sheet '%s' but is not "
2529 "linked to another sheet in the "
2530 "design. KiCad requires all sheet "
2531 "symbols to be associated to a sheet, "
2532 "so the block was not loaded." ),
2533 block.ID, block.Name,
2534 Sheets.SheetNames.at( aCadstarSheetID ) ),
2536 }
2537
2538 continue;
2539 }
2540
2541 // In KiCad you can only draw rectangular shapes whereas in Cadstar arbitrary shapes
2542 // are allowed. We will calculate the extents of the Cadstar shape and draw a rectangle
2543
2544 std::pair<VECTOR2I, VECTOR2I> blockExtents;
2545
2546 if( block.Figures.size() > 0 )
2547 {
2548 blockExtents = getFigureExtentsKiCad( block.Figures.begin()->second );
2549 }
2550 else
2551 {
2552 THROW_IO_ERROR( wxString::Format( _( "The CADSTAR schematic might be corrupt: "
2553 "Block %s references a child sheet but has no "
2554 "Figure defined." ),
2555 block.ID ) );
2556 }
2557
2558 loadSheetAndChildSheets( block.AssocLayerID, blockExtents.first, blockExtents.second,
2559 aSheet );
2560
2561 // Hide all KiCad sheet properties (sheet name/filename is not applicable in CADSTAR)
2562 SCH_SHEET* loadedSheet = m_sheetMap.at( block.AssocLayerID );
2563 SCH_FIELDS fields = loadedSheet->GetFields();
2564
2565 for( SCH_FIELD& field : fields )
2566 {
2567 field.SetVisible( false );
2568 }
2569
2570 if( block.HasBlockLabel )
2571 {
2572 //@todo use below code when KiCad supports multi-line fields
2573 /*
2574 // Add the block label as a separate field
2575 SCH_FIELD blockNameField( getKiCadPoint( block.BlockLabel.Position ), 2,
2576 loadedSheet, wxString( "Block name" ) );
2577 blockNameField.SetText( block.Name );
2578 blockNameField.SetVisible( true );
2579
2580 applyTextSettings( &blockNameField,
2581 block.BlockLabel.TextCodeID,
2582 block.BlockLabel.Alignment,
2583 block.BlockLabel.Justification,
2584 block.BlockLabel.OrientAngle,
2585 block.BlockLabel.Mirror );
2586
2587 fields.push_back( blockNameField );*/
2588
2589 // For now as as a text item (supports multi-line properly)
2590 SCH_TEXT* kiTxt = new SCH_TEXT();
2591
2592 kiTxt->SetParent( m_schematic );
2593 kiTxt->SetPosition( getKiCadPoint( block.BlockLabel.Position ) );
2594 kiTxt->SetText( block.Name );
2595
2596 applyTextSettings( kiTxt,
2597 block.BlockLabel.TextCodeID,
2598 block.BlockLabel.Alignment,
2600 block.BlockLabel.OrientAngle,
2601 block.BlockLabel.Mirror );
2602
2603 loadItemOntoKiCadSheet( aCadstarSheetID, kiTxt );
2604 }
2605
2606 loadedSheet->SetFields( fields );
2607 }
2608 }
2609}
2610
2611
2612std::vector<CADSTAR_SCH_ARCHIVE_LOADER::LAYER_ID> CADSTAR_SCH_ARCHIVE_LOADER::findOrphanSheets()
2613{
2614 std::vector<LAYER_ID> childSheets, orphanSheets;
2615
2616 //Find all sheets that are child of another
2617 for( std::pair<BLOCK_ID, BLOCK> blockPair : Schematic.Blocks )
2618 {
2619 BLOCK& block = blockPair.second;
2620 LAYER_ID& assocSheetID = block.AssocLayerID;
2621
2622 if( block.Type == BLOCK::TYPE::CHILD )
2623 childSheets.push_back( assocSheetID );
2624 }
2625
2626 //Add sheets that do not have a parent
2627 for( LAYER_ID sheetID : Sheets.SheetOrder )
2628 {
2629 if( std::find( childSheets.begin(), childSheets.end(), sheetID ) == childSheets.end() )
2630 orphanSheets.push_back( sheetID );
2631 }
2632
2633 return orphanSheets;
2634}
2635
2636
2638{
2639 int i = 1;
2640
2641 for( LAYER_ID sheetID : Sheets.SheetOrder )
2642 {
2643 if( sheetID == aCadstarSheetID )
2644 return i;
2645
2646 ++i;
2647 }
2648
2649 return -1;
2650}
2651
2652
2654{
2655 wxCHECK_MSG( aItem, /*void*/, "aItem is null" );
2656
2657 if( aCadstarSheetID == "ALL_SHEETS" )
2658 {
2659 SCH_ITEM* duplicateItem = nullptr;
2660
2661 for( std::pair<LAYER_ID, SHEET_NAME> sheetPair : Sheets.SheetNames )
2662 {
2663 LAYER_ID sheetID = sheetPair.first;
2664 duplicateItem = aItem->Duplicate();
2665 m_sheetMap.at( sheetID )->GetScreen()->Append( aItem->Duplicate() );
2666 }
2667
2668 //Get rid of the extra copy:
2669 delete aItem;
2670 aItem = duplicateItem;
2671 }
2672 else if( aCadstarSheetID == "NO_SHEET" )
2673 {
2674 wxASSERT_MSG( false,
2675 "Trying to add an item to NO_SHEET? This might be a documentation symbol." );
2676 }
2677 else
2678 {
2679 if( m_sheetMap.find( aCadstarSheetID ) != m_sheetMap.end() )
2680 {
2681 m_sheetMap.at( aCadstarSheetID )->GetScreen()->Append( aItem );
2682 }
2683 else
2684 {
2685 delete aItem;
2686 wxASSERT_MSG( false, "Unknown Sheet ID." );
2687 }
2688 }
2689}
2690
2691
2694 const wxString& aSymDefAlternate )
2695{
2696 if( m_SymDefNamesCache.size() != Library.SymbolDefinitions.size() )
2697 {
2698 // Re-initialise
2699 m_SymDefNamesCache.clear();
2701
2702 // Create a lower case cache to avoid searching each time
2703 for( auto& [id, symdef] : Library.SymbolDefinitions )
2704 {
2705 wxString refKey = symdef.ReferenceName.Lower();
2706 wxString altKey = symdef.Alternate.Lower();
2707
2708 m_SymDefNamesCache[{ refKey, altKey }] = id;
2709
2710 // Secondary cache to find symbols just by the Name (e.g. if the alternate
2711 // does not exist, we still want to return a symbo - the same behaviour
2712 // as CADSTAR
2713
2714 if( !m_DefaultSymDefNamesCache.count( refKey ) )
2715 {
2716 m_DefaultSymDefNamesCache.insert( { refKey, id } );
2717 }
2718 else if( altKey.IsEmpty() )
2719 {
2720 // Always use the empty alternate if it exists
2721 m_DefaultSymDefNamesCache[refKey] = id;
2722 }
2723 }
2724 }
2725
2726 wxString refKeyToFind = aSymdefName.Lower();
2727 wxString altKeyToFind = aSymDefAlternate.Lower();
2728
2729 if( m_SymDefNamesCache.count( { refKeyToFind, altKeyToFind } ) )
2730 {
2731 return m_SymDefNamesCache[{ refKeyToFind, altKeyToFind }];
2732 }
2733 else if( m_DefaultSymDefNamesCache.count( refKeyToFind ) )
2734 {
2735 return m_DefaultSymDefNamesCache[refKeyToFind];
2736 }
2737
2738
2739 return SYMDEF_ID();
2740}
2741
2742
2744{
2745 // Use CADSTAR visibility settings to determine if an attribute is visible
2746 if( AttrColors.AttributeColors.find( aCadstarAttributeID ) != AttrColors.AttributeColors.end() )
2747 {
2748 return AttrColors.AttributeColors.at( aCadstarAttributeID ).IsVisible;
2749 }
2750
2751 return false; // If there is no visibility setting, assume not displayed
2752}
2753
2754
2756{
2757 wxCHECK( Assignments.Codedefs.LineCodes.find( aCadstarLineCodeID )
2760
2761 return getKiCadLength( Assignments.Codedefs.LineCodes.at( aCadstarLineCodeID ).Width );
2762}
2763
2764
2766{
2767 wxCHECK( Assignments.Codedefs.LineCodes.find( aCadstarLineCodeID )
2769 PLOT_DASH_TYPE::SOLID );
2770
2771 // clang-format off
2772 switch( Assignments.Codedefs.LineCodes.at( aCadstarLineCodeID ).Style )
2773 {
2774 case LINESTYLE::DASH: return PLOT_DASH_TYPE::DASH;
2775 case LINESTYLE::DASHDOT: return PLOT_DASH_TYPE::DASHDOT;
2776 case LINESTYLE::DASHDOTDOT: return PLOT_DASH_TYPE::DASHDOT; //TODO: update in future
2777 case LINESTYLE::DOT: return PLOT_DASH_TYPE::DOT;
2778 case LINESTYLE::SOLID: return PLOT_DASH_TYPE::SOLID;
2779 default: return PLOT_DASH_TYPE::DEFAULT;
2780 }
2781 // clang-format on
2782}
2783
2784
2787{
2788 wxCHECK( Assignments.Codedefs.TextCodes.find( aCadstarTextCodeID )
2790 TEXTCODE() );
2791
2792 return Assignments.Codedefs.TextCodes.at( aCadstarTextCodeID );
2793}
2794
2795
2797{
2798 TEXTCODE txtCode = getTextCode( aCadstarTextCodeID );
2799
2800 return KiROUND( (double) getKiCadLength( txtCode.Height ) * TXT_HEIGHT_RATIO );
2801}
2802
2803
2805{
2806 wxCHECK( Assignments.Codedefs.AttributeNames.find( aCadstarAttributeID )
2808 aCadstarAttributeID );
2809
2810 return Assignments.Codedefs.AttributeNames.at( aCadstarAttributeID ).Name;
2811}
2812
2813
2816{
2817 wxCHECK( Parts.PartDefinitions.find( aCadstarPartID ) != Parts.PartDefinitions.end(), PART() );
2818
2819 return Parts.PartDefinitions.at( aCadstarPartID );
2820}
2821
2822
2825{
2826 wxCHECK( Assignments.Codedefs.RouteCodes.find( aCadstarRouteCodeID )
2828 ROUTECODE() );
2829
2830 return Assignments.Codedefs.RouteCodes.at( aCadstarRouteCodeID );
2831}
2832
2833
2834CADSTAR_SCH_ARCHIVE_LOADER::PART::DEFINITION::PIN
2836 const TERMINAL_ID& aTerminalID )
2837{
2838 for( std::pair<PART_DEFINITION_PIN_ID, PART::DEFINITION::PIN> pinPair :
2839 aCadstarPart.Definition.Pins )
2840 {
2841 PART::DEFINITION::PIN partPin = pinPair.second;
2842
2843 if( partPin.TerminalGate == aGateID && partPin.TerminalPin == aTerminalID )
2844 return partPin;
2845 }
2846
2847 return PART::DEFINITION::PIN();
2848}
2849
2850
2852{
2853 switch( aPinType )
2854 {
2855 case CADSTAR_PIN_TYPE::UNCOMMITTED: return ELECTRICAL_PINTYPE::PT_PASSIVE;
2856 case CADSTAR_PIN_TYPE::INPUT: return ELECTRICAL_PINTYPE::PT_INPUT;
2857 case CADSTAR_PIN_TYPE::OUTPUT_OR: return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
2858 case CADSTAR_PIN_TYPE::OUTPUT_NOT_OR: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2859 case CADSTAR_PIN_TYPE::OUTPUT_NOT_NORM_OR: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2860 case CADSTAR_PIN_TYPE::POWER: return ELECTRICAL_PINTYPE::PT_POWER_IN;
2861 case CADSTAR_PIN_TYPE::GROUND: return ELECTRICAL_PINTYPE::PT_POWER_IN;
2862 case CADSTAR_PIN_TYPE::TRISTATE_BIDIR: return ELECTRICAL_PINTYPE::PT_BIDI;
2863 case CADSTAR_PIN_TYPE::TRISTATE_INPUT: return ELECTRICAL_PINTYPE::PT_INPUT;
2864 case CADSTAR_PIN_TYPE::TRISTATE_DRIVER: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2865 }
2866
2867 return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
2868}
2869
2871{
2872 if( aCadstarGateID.IsEmpty() )
2873 return 1;
2874
2875 return (int) aCadstarGateID.Upper().GetChar( 0 ) - (int) wxUniChar( 'A' ) + 1;
2876}
2877
2878
2879TEXT_SPIN_STYLE CADSTAR_SCH_ARCHIVE_LOADER::getSpinStyle( const long long& aCadstarOrientation,
2880 bool aMirror )
2881{
2882 EDA_ANGLE orientation = getAngle( aCadstarOrientation );
2883 TEXT_SPIN_STYLE spinStyle = getSpinStyle( orientation );
2884
2885 if( aMirror )
2886 {
2887 spinStyle = spinStyle.RotateCCW();
2888 spinStyle = spinStyle.RotateCCW();
2889 }
2890
2891 return spinStyle;
2892}
2893
2894
2896{
2898
2899 EDA_ANGLE oDeg = aOrientation;
2900 oDeg.Normalize180();
2901
2902 if( oDeg >= -ANGLE_45 && oDeg <= ANGLE_45 )
2903 spinStyle = TEXT_SPIN_STYLE::RIGHT; // 0deg
2904 else if( oDeg >= ANGLE_45 && oDeg <= ANGLE_135 )
2905 spinStyle = TEXT_SPIN_STYLE::UP; // 90deg
2906 else if( oDeg >= ANGLE_135 || oDeg <= -ANGLE_135 )
2907 spinStyle = TEXT_SPIN_STYLE::LEFT; // 180deg
2908 else
2909 spinStyle = TEXT_SPIN_STYLE::BOTTOM; // 270deg
2910
2911 return spinStyle;
2912}
2913
2914
2917{
2918 switch( aCadstarAlignment )
2919 {
2920 // Change left to right:
2925
2926 //Change right to left:
2930
2931 // Center alignment does not mirror:
2934 case ALIGNMENT::TOPCENTER: return aCadstarAlignment;
2935
2936 // Shouldn't be here
2937 default: wxFAIL_MSG( "Unknown Cadstar Alignment" ); return aCadstarAlignment;
2938 }
2939}
2940
2941
2944{
2945 switch( aCadstarAlignment )
2946 {
2957
2958 // Shouldn't be here
2959 default: wxFAIL_MSG( "Unknown Cadstar Alignment" ); return aCadstarAlignment;
2960 }
2961}
2962
2963
2965 const TEXTCODE_ID& aCadstarTextCodeID )
2966{
2967 // Ensure we have no Cadstar overbar characters
2968 wxString escapedText = HandleTextOverbar( aKiCadTextItem->GetText() );
2969 aKiCadTextItem->SetText( escapedText );
2970
2971 if( !Assignments.Codedefs.TextCodes.count( aCadstarTextCodeID ) )
2972 return;
2973
2974 TEXTCODE textCode = getTextCode( aCadstarTextCodeID );
2975 int textHeight = KiROUND( (double) getKiCadLength( textCode.Height ) * TXT_HEIGHT_RATIO );
2976 int textWidth = getKiCadLength( textCode.Width );
2977
2978 // The width is zero for all non-cadstar fonts. Using a width equal to 2/3 the height seems
2979 // to work well for most fonts.
2980 if( textWidth == 0 )
2981 textWidth = getKiCadLength( 2LL * textCode.Height / 3LL );
2982
2983 aKiCadTextItem->SetTextWidth( textWidth );
2984 aKiCadTextItem->SetTextHeight( textHeight );
2985 aKiCadTextItem->SetTextThickness( getKiCadLength( textCode.LineWidth ) );
2986
2987 aKiCadTextItem->SetBold( textCode.Font.Modifier1 == FONT_BOLD );
2988 aKiCadTextItem->SetItalic( textCode.Font.Italic );
2989}
2990
2991
2993 const TEXTCODE_ID& aCadstarTextCodeID,
2994 const ALIGNMENT& aCadstarAlignment,
2995 const JUSTIFICATION& aCadstarJustification,
2996 const long long aCadstarOrientAngle,
2997 bool aMirrored )
2998{
2999 applyTextCodeIfExists( aKiCadTextItem, aCadstarTextCodeID );
3000 aKiCadTextItem->SetTextAngle( getAngle( aCadstarOrientAngle ) );
3001
3002 // Justification ignored for now as not supported in Eeschema, but leaving this code in
3003 // place for future upgrades.
3004 // TODO update this when Eeschema supports justification independent of anchor position.
3005 ALIGNMENT textAlignment = aCadstarAlignment;
3006
3007 // KiCad mirrors the justification and alignment when the symbol is mirrored but CADSTAR
3008 // specifies it post-mirroring. In contrast, if the text item itself is mirrored (not
3009 // supported in KiCad), CADSTAR specifies the alignment and justification pre-mirroring
3010 if( aMirrored )
3011 textAlignment = mirrorX( aCadstarAlignment );
3012
3013 auto setAlignment =
3014 [&]( EDA_TEXT* aText, ALIGNMENT aAlignment )
3015 {
3016 switch( aAlignment )
3017 {
3018 case ALIGNMENT::NO_ALIGNMENT: // Bottom left of the first line
3019 //No exact KiCad equivalent, so lets move the position of the text
3025 break;
3026
3030 break;
3031
3035 break;
3036
3040 break;
3041
3045 break;
3046
3050 break;
3051
3052 case ALIGNMENT::TOPLEFT:
3055 break;
3056
3060 break;
3061
3065 break;
3066 }
3067 };
3068
3069 TEXT_SPIN_STYLE spin = getSpinStyle( aCadstarOrientAngle, aMirrored );
3070 EDA_ITEM* textEdaItem = dynamic_cast<EDA_ITEM*>( aKiCadTextItem );
3071 wxCHECK( textEdaItem, /* void */ ); // ensure this is a EDA_ITEM
3072
3073 switch( textEdaItem->Type() )
3074 {
3075 // Some KiCad schematic text items only permit a limited amount of angles
3076 // and text justifications
3077 case LIB_TEXT_T:
3078 case SCH_FIELD_T:
3079 case LIB_FIELD_T:
3080 {
3081 // Spin style not used. All text justifications are permitted. However, only orientations
3082 // of 0 deg or 90 deg are supported
3083 EDA_ANGLE angle = aKiCadTextItem->GetTextAngle();
3084 angle.Normalize();
3085
3086 int quadrant = KiROUND( angle.AsDegrees() / 90.0 );
3087 quadrant %= 4;
3088
3089 switch( quadrant )
3090 {
3091 case 0:
3092 angle = ANGLE_HORIZONTAL;
3093 break;
3094 case 1:
3095 angle = ANGLE_VERTICAL;
3096 break;
3097 case 2:
3098 angle = ANGLE_HORIZONTAL;
3099 textAlignment = rotate180( textAlignment );
3100 break;
3101 case 3:
3102 angle = ANGLE_VERTICAL;
3103 textAlignment = rotate180( textAlignment );
3104 break;
3105 default: wxFAIL_MSG( "Unknown Quadrant" );
3106 }
3107
3108 aKiCadTextItem->SetTextAngle( angle );
3109 setAlignment( aKiCadTextItem, textAlignment );
3110 return;
3111 }
3112
3113 case SCH_TEXT_T:
3114 {
3115 // Note spin style in a SCH_TEXT results in a vertical alignment GR_TEXT_V_ALIGN_BOTTOM
3116 // so need to adjust the location of the text element based on Cadstar's original text
3117 // alignment (anchor position).
3118 setAlignment( aKiCadTextItem, textAlignment );
3119 BOX2I bb = textEdaItem->GetBoundingBox();
3120 int off = static_cast<SCH_TEXT*>( aKiCadTextItem )->GetTextOffset();
3121 VECTOR2I pos;
3122
3123 // Change the anchor point of the text item to make it match the same bounding box
3124 // And correct the error introduced by the text offsetting in KiCad
3125 switch( spin )
3126 {
3127 case TEXT_SPIN_STYLE::BOTTOM: pos = { bb.GetRight() - off, bb.GetTop() }; break;
3128 case TEXT_SPIN_STYLE::UP: pos = { bb.GetRight() - off, bb.GetBottom() }; break;
3129 case TEXT_SPIN_STYLE::LEFT: pos = { bb.GetRight() , bb.GetBottom() + off }; break;
3130 case TEXT_SPIN_STYLE::RIGHT: pos = { bb.GetLeft() , bb.GetBottom() + off }; break;
3131 }
3132
3133 aKiCadTextItem->SetTextPos( pos );
3134 }
3136
3137 // We don't want to change position of net labels as that would break connectivity
3138 case SCH_LABEL_T:
3139 case SCH_GLOBAL_LABEL_T:
3140 case SCH_HIER_LABEL_T:
3141 case SCH_SHEET_PIN_T:
3142 static_cast<SCH_TEXT*>( aKiCadTextItem )->SetTextSpinStyle( spin );
3143 return;
3144
3145 default:
3146 wxFAIL_MSG( "Unexpected item type" );
3147 return;
3148 }
3149}
3150
3151
3153{
3154 SCH_TEXT* kiTxt = new SCH_TEXT();
3155
3156 kiTxt->SetParent( m_schematic ); // set to the schematic for now to avoid asserts
3157 kiTxt->SetPosition( getKiCadPoint( aCadstarTextElement.Position ) );
3158 kiTxt->SetText( aCadstarTextElement.Text );
3159
3160 applyTextSettings( kiTxt,
3161 aCadstarTextElement.TextCodeID,
3162 aCadstarTextElement.Alignment,
3163 aCadstarTextElement.Justification,
3164 aCadstarTextElement.OrientAngle,
3165 aCadstarTextElement.Mirror );
3166
3167 return kiTxt;
3168}
3169
3170
3172 long long aScalingFactorNumerator,
3173 long long aScalingFactorDenominator )
3174{
3175 LIB_SYMBOL* retval = new LIB_SYMBOL( *aSymbol );
3176
3177 if( aScalingFactorNumerator == aScalingFactorDenominator )
3178 return retval; // 1:1 scale, nothing to do
3179
3180 auto scaleLen =
3181 [&]( int aLength ) -> int
3182 {
3183 return( aLength * aScalingFactorNumerator ) / aScalingFactorDenominator;
3184 };
3185
3186 auto scalePt =
3187 [&]( VECTOR2I aCoord ) -> VECTOR2I
3188 {
3189 return VECTOR2I( scaleLen( aCoord.x ), scaleLen( aCoord.y ) );
3190 };
3191
3192 auto scaleSize =
3193 [&]( VECTOR2I aSize ) -> VECTOR2I
3194 {
3195 return VECTOR2I( scaleLen( aSize.x ), scaleLen( aSize.y ) );
3196 };
3197
3198 LIB_ITEMS_CONTAINER& items = retval->GetDrawItems();
3199
3200 for( LIB_ITEM& item : items )
3201 {
3202 switch( item.Type() )
3203 {
3204 case KICAD_T::LIB_SHAPE_T:
3205 {
3206 LIB_SHAPE& shape = static_cast<LIB_SHAPE&>( item );
3207
3208 if( shape.GetShape() == SHAPE_T::ARC )
3209 {
3210 shape.SetPosition( scalePt( shape.GetPosition() ) );
3211 shape.SetStart( scalePt( shape.GetStart() ) );
3212 shape.SetEnd( scalePt( shape.GetEnd() ) );
3213 }
3214 else if( shape.GetShape() == SHAPE_T::POLY )
3215 {
3216 SHAPE_LINE_CHAIN& poly = shape.GetPolyShape().Outline( 0 );
3217
3218 for( size_t ii = 0; ii < poly.GetPointCount(); ++ii )
3219 poly.SetPoint( ii, scalePt( poly.CPoint( ii ) ) );
3220 }
3221 break;
3222 }
3223
3224 case KICAD_T::LIB_PIN_T:
3225 {
3226 LIB_PIN& pin = static_cast<LIB_PIN&>( item );
3227
3228 pin.SetPosition( scalePt( pin.GetPosition() ) );
3229 pin.SetLength( scaleLen( pin.GetLength() ) );
3230 break;
3231 }
3232
3233 case KICAD_T::LIB_TEXT_T:
3234 {
3235 LIB_TEXT& txt = static_cast<LIB_TEXT&>( item );
3236
3237 txt.SetPosition( scalePt( txt.GetPosition() ) );
3238 txt.SetTextSize( scaleSize( txt.GetTextSize() ) );
3239 break;
3240 }
3241
3242 default:
3243 break;
3244 }
3245
3246 }
3247
3248 return retval;
3249}
3250
3251
3252void CADSTAR_SCH_ARCHIVE_LOADER::fixUpLibraryPins( LIB_SYMBOL* aSymbolToFix, int aGateNumber )
3253{
3254 auto compLambda = []( const VECTOR2I& aA, const VECTOR2I& aB )
3255 {
3256 return LexicographicalCompare( aA, aB ) < 0;
3257 };
3258
3259 // Store a list of vertical or horizontal segments in the symbol
3260 // Note: Need the custom comparison function to ensure the map is sorted correctly
3261 std::map<VECTOR2I, SHAPE_LINE_CHAIN, decltype( compLambda )> uniqueSegments( compLambda );
3262
3263 LIB_ITEMS_CONTAINER::ITERATOR shapeIt = aSymbolToFix->GetDrawItems().begin( LIB_SHAPE_T );
3264
3265 for( ; shapeIt != aSymbolToFix->GetDrawItems().end( LIB_SHAPE_T ); ++shapeIt )
3266 {
3267 LIB_SHAPE& shape = static_cast<LIB_SHAPE&>( *shapeIt );
3268
3269 if( aGateNumber > 0 && shape.GetUnit() != aGateNumber )
3270 continue;
3271
3272 if( shape.GetShape() != SHAPE_T::POLY )
3273 continue;
3274
3275 SHAPE_LINE_CHAIN poly = shape.GetPolyShape().Outline( 0 );
3276
3277 if( poly.GetPointCount() == 2 )
3278 {
3279 VECTOR2I pt0 = poly.CPoint( 0 );
3280 VECTOR2I pt1 = poly.CPoint( 1 );
3281
3282 if( pt0 != pt1 && uniqueSegments.count( pt0 ) == 0 && uniqueSegments.count( pt1 ) == 0 )
3283 {
3284 // we are only interested in vertical or horizontal segments
3285 if( pt0.x == pt1.x || pt0.y == pt1.y )
3286 {
3287 uniqueSegments.insert( { pt0, poly } );
3288 uniqueSegments.insert( { pt1, poly } );
3289 }
3290 }
3291 }
3292 }
3293
3294 LIB_PINS pins;
3295 aSymbolToFix->GetPins( pins, aGateNumber );
3296
3297 for( auto& pin : pins )
3298 {
3299 auto setPinOrientation =
3300 [&]( const EDA_ANGLE& aAngle )
3301 {
3302 EDA_ANGLE angle( aAngle );
3303 angle.Normalize180();
3304
3305 if( angle >= -ANGLE_45 && angle <= ANGLE_45 )
3306 pin->SetOrientation( 'R' ); // 0 degrees
3307 else if( angle >= ANGLE_45 && angle <= ANGLE_135 )
3308 pin->SetOrientation( 'U' ); // 90 degrees
3309 else if( angle >= ANGLE_135 || angle <= -ANGLE_135 )
3310 pin->SetOrientation( 'L' ); // 180 degrees
3311 else
3312 pin->SetOrientation( 'D' ); // -90 degrees
3313 };
3314
3315 if( uniqueSegments.count( pin->GetPosition() ) )
3316 {
3317 SHAPE_LINE_CHAIN& poly = uniqueSegments.at( pin->GetPosition() );
3318
3319 VECTOR2I otherPt = poly.CPoint( 0 );
3320
3321 if( otherPt == pin->GetPosition() )
3322 otherPt = poly.CPoint( 1 );
3323
3324 VECTOR2I vec( otherPt - pin->GetPosition() );
3325
3326 pin->SetLength( vec.EuclideanNorm() );
3327 setPinOrientation( EDA_ANGLE( vec ) );
3328 }
3329 }
3330}
3331
3332
3333std::pair<VECTOR2I, VECTOR2I>
3335{
3336 VECTOR2I upperLeft( Assignments.Settings.DesignLimit.x, 0 );
3337 VECTOR2I lowerRight( 0, Assignments.Settings.DesignLimit.y );
3338
3339 for( const VERTEX& v : aCadstarFigure.Shape.Vertices )
3340 {
3341 if( upperLeft.x > v.End.x )
3342 upperLeft.x = v.End.x;
3343
3344 if( upperLeft.y < v.End.y )
3345 upperLeft.y = v.End.y;
3346
3347 if( lowerRight.x < v.End.x )
3348 lowerRight.x = v.End.x;
3349
3350 if( lowerRight.y > v.End.y )
3351 lowerRight.y = v.End.y;
3352 }
3353
3354 for( CUTOUT cutout : aCadstarFigure.Shape.Cutouts )
3355 {
3356 for( const VERTEX& v : aCadstarFigure.Shape.Vertices )
3357 {
3358 if( upperLeft.x > v.End.x )
3359 upperLeft.x = v.End.x;
3360
3361 if( upperLeft.y < v.End.y )
3362 upperLeft.y = v.End.y;
3363
3364 if( lowerRight.x < v.End.x )
3365 lowerRight.x = v.End.x;
3366
3367 if( lowerRight.y > v.End.y )
3368 lowerRight.y = v.End.y;
3369 }
3370 }
3371
3372 VECTOR2I upperLeftKiCad = getKiCadPoint( upperLeft );
3373 VECTOR2I lowerRightKiCad = getKiCadPoint( lowerRight );
3374
3375 VECTOR2I size = lowerRightKiCad - upperLeftKiCad;
3376
3377 return { upperLeftKiCad, VECTOR2I( abs( size.x ), abs( size.y ) ) };
3378}
3379
3380
3382{
3383 VECTOR2I retval;
3384
3385 retval.x = getKiCadLength( aCadstarPoint.x - m_designCenter.x );
3386 retval.y = -getKiCadLength( aCadstarPoint.y - m_designCenter.y );
3387
3388 return retval;
3389}
3390
3391
3393 const VECTOR2I& aCadstarCentre )
3394{
3395 VECTOR2I retval;
3396
3397 retval.x = getKiCadLength( aCadstarPoint.x - aCadstarCentre.x );
3398 retval.y = getKiCadLength( aCadstarPoint.y - aCadstarCentre.y );
3399
3400 return retval;
3401}
3402
3403
3405 const VECTOR2I& aMoveVector,
3406 const EDA_ANGLE& aRotation,
3407 const double& aScalingFactor,
3408 const VECTOR2I& aTransformCentre,
3409 const bool& aMirrorInvert )
3410{
3411 VECTOR2I retVal = aPoint;
3412
3413 if( aScalingFactor != 1.0 )
3414 {
3415 //scale point
3416 retVal -= aTransformCentre;
3417 retVal.x = KiROUND( retVal.x * aScalingFactor );
3418 retVal.y = KiROUND( retVal.y * aScalingFactor );
3419 retVal += aTransformCentre;
3420 }
3421
3422 if( aMirrorInvert )
3423 MIRROR( retVal.x, aTransformCentre.x );
3424
3425 if( !aRotation.IsZero() )
3426 RotatePoint( retVal, aTransformCentre, aRotation );
3427
3428 if( aMoveVector != VECTOR2I{ 0, 0 } )
3429 retVal += aMoveVector;
3430
3431 return retVal;
3432}
3433
3434
3436{
3437 return sqrt( ( (double) aPoint.x * (double) aPoint.x )
3438 + ( (double) aPoint.y * (double) aPoint.y ) );
3439}
const char * name
Definition: DXF_plotter.cpp:56
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
constexpr double SCH_IU_PER_MM
Definition: base_units.h:73
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.
coord_type GetTop() const
Definition: box2.h:194
Vec Centre() const
Definition: box2.h:70
coord_type GetRight() const
Definition: box2.h:189
coord_type GetLeft() const
Definition: box2.h:193
const Vec & GetSize() const
Definition: box2.h:179
coord_type GetBottom() const
Definition: box2.h:190
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:588
static wxString 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 wxString generateLibName(const wxString &aRefName, const wxString &aAlternateName)
wxString LAYER_ID
ID of a Sheet (if schematic) or board Layer (if PCB)
static void FixTextPositionNoAlignment(EDA_TEXT *aKiCadTextItem)
Corrects the position of a text element that had NO_ALIGNMENT in CADSTAR.
@ OUTLINE
Unfilled closed shape.
@ OPENSHAPE
Unfilled open shape. Cannot have cutouts.
@ SOLID
Filled closed shape (solid fill).
@ HATCHED
Filled closed shape (hatch fill).
static const double TXT_HEIGHT_RATIO
CADSTAR fonts are drawn on a 24x24 integer matrix, where the each axis goes from 0 to 24.
void checkPoint()
Updates m_progressReporter or throws if user cancelled.
static wxString HandleTextOverbar(wxString aCadstarString)
Convert a string with CADSTAR overbar characters to equivalent in KiCad.
JUSTIFICATION
From CADSTAR Help: "Multi Line Text can also be justified as Left, Centre or Right.
PROGRESS_REPORTER * m_progressReporter
bool CheckFileHeader(const std::filesystem::path &aPath) const
CADSTAR_PARTS_LIB_MODEL ReadFile(const std::filesystem::path &aPath) const
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)
void applyTextSettings(EDA_TEXT *aKiCadTextItem, const TEXTCODE_ID &aCadstarTextCodeID, const ALIGNMENT &aCadstarAlignment, const JUSTIFICATION &aCadstarJustification, const long long aCadstarOrientAngle=0, bool aMirrored=false)
wxString getAttributeName(const ATTRIBUTE_ID &aCadstarAttributeID)
std::vector< LIB_SYMBOL * > m_loadedSymbols
Loaded symbols so far.
PART getPart(const PART_ID &aCadstarPartID)
static LIB_FIELD * addNewFieldToSymbol(const wxString &aFieldName, std::unique_ptr< LIB_SYMBOL > &aKiCadSymbol)
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
void loadLibrarySymbolShapeVertices(const std::vector< VERTEX > &aCadstarVertices, VECTOR2I aSymbolOrigin, LIB_SYMBOL *aSymbol, int aGateNumber, int aLineThickness)
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)
TEXT_SPIN_STYLE getSpinStyle(const long long &aCadstarOrientation, bool aMirror)
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)
std::map< wxString, LIB_SYMBOL * > m_powerSymLibMap
NetName->KiCad Power Lib Symbol.
PLOT_DASH_TYPE getLineStyle(const LINECODE_ID &aCadstarLineCodeID)
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.
void applyToLibraryFieldAttribute(const ATTRIBUTE_LOCATION &aCadstarAttrLoc, VECTOR2I aSymbolOrigin, LIB_FIELD *aKiCadField)
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.
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 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:249
double AsDegrees() const
Definition: eda_angle.h:149
bool IsZero() const
Definition: eda_angle.h:169
EDA_ANGLE Normalize180()
Definition: eda_angle.h:288
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:73
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
EDA_ITEM * GetParent() const
Definition: eda_item.h:99
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:247
SHAPE_T GetShape() const
Definition: eda_shape.h:113
void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition: eda_shape.h:255
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:145
void SetStart(const VECTOR2I &aStart)
Definition: eda_shape.h:124
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:120
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:149
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
Definition: eda_shape.cpp:555
void SetFillMode(FILL_T aFill)
Definition: eda_shape.h:100
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:72
int GetTextHeight() const
Definition: eda_text.h:205
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:123
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:87
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:383
int GetTextWidth() const
Definition: eda_text.h:202
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition: eda_text.cpp:260
void SetTextWidth(int aWidth)
Definition: eda_text.cpp:367
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:229
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:375
void SetBold(bool aBold)
Definition: eda_text.cpp:221
void SetTextSize(const VECTOR2I &aNewSize)
Definition: eda_text.cpp:359
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:175
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:205
int GetTextThickness() const
Definition: eda_text.h:115
void SetItalic(bool aItalic)
Definition: eda_text.cpp:213
void SetMultilineAllowed(bool aAllow)
Definition: eda_text.cpp:244
VECTOR2I GetTextSize() const
Definition: eda_text.h:199
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:252
iterator end()
Returns a read/write iterator that points to one past the last element in the EE_RTREE.
Definition: sch_rtree.h:285
iterator begin()
Returns a read/write iterator that points to the first element in the EE_RTREE N.B.
Definition: sch_rtree.h:276
Field object used in symbol libraries.
Definition: lib_field.h:61
void SetName(const wxString &aName)
Set a user definable field name to aName.
Definition: lib_field.cpp:512
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: lib_field.cpp:488
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:109
UTF8 Format() const
Definition: lib_id.cpp:117
The base class for drawable items used by schematic library symbols.
Definition: lib_item.h:61
int GetUnit() const
Definition: lib_item.h:293
void SetPosition(const VECTOR2I &aPosition) override
Definition: lib_item.h:254
void SetUnit(int aUnit)
Definition: lib_item.h:292
void SetNumber(const wxString &aNumber)
Definition: lib_pin.h:130
void SetStroke(const STROKE_PARAMS &aStroke)
Definition: lib_shape.h:58
void AddPoint(const VECTOR2I &aPosition)
Definition: lib_shape.cpp:518
void SetPosition(const VECTOR2I &aPosition) override
Definition: lib_shape.h:91
VECTOR2I GetPosition() const override
Definition: lib_shape.h:90
Define a library symbol object.
Definition: lib_symbol.h:99
void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
Definition: lib_symbol.h:631
LIB_FIELD & GetReferenceField()
Return reference to the reference designator field.
void SetUnitCount(int aCount, bool aDuplicateDrawItems=true)
Set the units per symbol count.
void SetPower()
Definition: lib_symbol.cpp:693
void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition: lib_symbol.h:639
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:515
wxString GetName() const override
Definition: lib_symbol.h:143
void AddDrawItem(LIB_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
Definition: lib_symbol.cpp:960
LIB_FIELD & GetValueField()
Return reference to the value field.
std::vector< LIB_PIN * > GetAllLibPins() const
Return a list of pin pointers for all units / converts.
Definition: lib_symbol.cpp:998
void GetPins(LIB_PINS &aList, int aUnit=0, int aConvert=0) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:971
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:572
Define a symbol library graphical text item.
Definition: lib_text.h:40
VECTOR2I GetPosition() const override
Definition: lib_text.h:98
ITERATOR_BASE< LIB_ITEM, MULTIVECTOR< LIB_ITEM, FIRST_TYPE_VAL, LAST_TYPE_VAL >, typename ITEM_PTR_VECTOR::iterator > ITERATOR
The const iterator.
Definition: multivector.h: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:54
void SetWidthMils(int aWidthInMils)
Definition: page_info.cpp:245
void SetHeightMils(int aHeightInMils)
Definition: page_info.cpp:259
const VECTOR2I GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition: page_info.h:162
virtual void SetNumPhases(int aNumPhases)=0
Set the number of phases.
virtual void BeginPhase(int aPhase)=0
Initialize the aPhase virtual zone of the dialog progress bar.
virtual void SetMaxProgress(int aMaxProgress)=0
Fix the value that gives the 100 percent progress bar length (inside the current virtual zone).
Container for project specific data.
Definition: project.h:64
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:126
virtual std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:82
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
Holds all the data relating to one schematic.
Definition: schematic.h:72
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:87
void SetSize(const VECTOR2I &aSize)
Definition: sch_bus_entry.h:72
Class for a wire to bus entry.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:830
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_field.cpp:1074
void SetTextSpinStyle(TEXT_SPIN_STYLE aSpinStyle) override
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_label.cpp:1519
void SetTextSpinStyle(TEXT_SPIN_STYLE aSpinStyle) override
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_label.cpp:1679
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
void SetLayer(SCH_LAYER_ID aLayer)
Set the layer this item is on.
Definition: sch_item.h:256
SCH_ITEM * Duplicate(bool doClone=false) const
Routine to create a new copy of given item.
Definition: sch_item.cpp:94
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_junction.h:103
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_label.cpp:294
void SetShape(LABEL_FLAG_SHAPE aShape) override
Definition: sch_label.h:74
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_label.cpp:466
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
void SetStartPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:139
void SetLineWidth(const int aSize)
Definition: sch_line.cpp:316
VECTOR2I GetEndPoint() const
Definition: sch_line.h:143
VECTOR2I GetStartPoint() const
Definition: sch_line.h:138
void SetLineStyle(const PLOT_DASH_TYPE aStyle)
Definition: sch_line.cpp:287
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:144
const PAGE_INFO & GetPageSettings() const
Definition: sch_screen.h:131
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:144
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:109
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
Definition: sch_screen.cpp:307
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:368
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:758
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:346
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:161
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_sheet.cpp:605
static bool ClassOf(const EDA_ITEM *aItem)
Definition: sch_sheet.h:72
Schematic symbol object.
Definition: sch_symbol.h:81
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_symbol.h:727
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:500
SCH_FIELD * FindField(const wxString &aFieldName, bool aIncludeDefaultFields=true)
Search for a SCH_FIELD with aFieldName.
Definition: sch_symbol.cpp:976
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:891
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
Definition: sch_symbol.cpp:339
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:740
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:954
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:939
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:195
VECTOR2I GetPosition() const override
Definition: sch_text.h:212
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_text.h:213
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_text.cpp:329
virtual void SetTextSpinStyle(TEXT_SPIN_STYLE aSpinStyle)
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_text.cpp:193
const VECTOR2I & GetArcMid() const
Definition: shape_arc.h:114
const VECTOR2I & GetP1() const
Definition: shape_arc.h:113
const VECTOR2I & GetP0() const
Definition: shape_arc.h:112
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.
Simple container to manage line stroke parameters.
Definition: stroke_params.h:88
TEXT_SPIN_STYLE MirrorY()
Mirror the label spin style across the Y axis or simply swaps left and right.
Definition: sch_text.cpp:99
TEXT_SPIN_STYLE RotateCCW()
Definition: sch_text.cpp:67
TEXT_SPIN_STYLE MirrorX()
Mirror the label spin style across the X axis or simply swaps up and bottom.
Definition: sch_text.cpp:83
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h: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_180
Definition: eda_angle.h:433
static constexpr EDA_ANGLE & ANGLE_HORIZONTAL
Definition: eda_angle.h:425
static constexpr EDA_ANGLE & ANGLE_VERTICAL
Definition: eda_angle.h:426
static constexpr EDA_ANGLE & ANGLE_45
Definition: eda_angle.h:430
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:431
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:429
static constexpr EDA_ANGLE & ANGLE_270
Definition: eda_angle.h:434
static constexpr EDA_ANGLE & ANGLE_135
Definition: eda_angle.h:432
const std::string KiCadSchematicFileExtension
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
SCH_LAYER_ID
Eeschema drawing layers.
Definition: layer_ids.h:345
@ LAYER_WIRE
Definition: layer_ids.h:348
@ LAYER_NOTES
Definition: layer_ids.h:362
@ LAYER_BUS
Definition: layer_ids.h:349
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:54
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition: mirror.h:40
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:99
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_TYPE_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:55
PLOT_DASH_TYPE
Dashed line types.
Definition: stroke_params.h:48
std::map< ATTRIBUTE_ID, ATTRCOL > AttributeColors
JUSTIFICATION Justification
Note: Justification has no effect on single lines of text.
ALIGNMENT Alignment
In CADSTAR The default alignment for a TEXT object (when "(No Alignment()" is selected) Bottom Left o...
bool HasLocation
Flag to know if this ATTRIBUTE_VALUE has a location i.e.
std::map< LINECODE_ID, LINECODE > LineCodes
std::map< ATTRIBUTE_ID, ATTRNAME > AttributeNames
std::map< ROUTECODE_ID, ROUTECODE > RouteCodes
std::map< TEXTCODE_ID, TEXTCODE > TextCodes
Represents a cutout in a closed shape (e.g.
long ScaleRatioNumerator
Documentation symbols can be arbitrarily scaled when added to a design.
long ScaleRatioDenominator
Documentation symbols can be arbitrarily scaled when added to a design.
POINT Origin
Origin of the component (this is used as the reference point when placing the component in the design...
LAYER_ID LayerID
Move all objects in the Symdef to this layer.
SYMDEF_ID SymdefID
Normally documentation symbols only have TEXT, FIGURE and TEXT_LOCATION objects which are all drawn o...
long Modifier1
It seems this is related to weight. 400=Normal, 700=Bold.
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::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:100
const double IU_PER_MILS
Definition: base_units.h:78
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
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)
Definition: trigo.cpp:183
@ LIB_TEXT_T
Definition: typeinfo.h:190
@ SCH_SYMBOL_T
Definition: typeinfo.h:146
@ SCH_FIELD_T
Definition: typeinfo.h:145
@ SCH_LABEL_T
Definition: typeinfo.h:141
@ LIB_SHAPE_T
Definition: typeinfo.h:189
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:143
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:147
@ SCH_TEXT_T
Definition: typeinfo.h:140
@ LIB_FIELD_T
Definition: typeinfo.h:198
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:142
int sign(T val)
Definition: util.h:124
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
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.