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