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