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