KiCad PCB EDA Suite
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 <roberto.fer.bau@gmail.com>
5  * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
27 
28 #include <bus_alias.h>
29 #include <core/mirror.h>
30 #include <eda_text.h>
31 #include <lib_arc.h>
32 #include <lib_polyline.h>
33 #include <lib_text.h>
34 #include <macros.h>
35 #include <kicad_string.h>
36 #include <sch_bus_entry.h>
37 #include <sch_edit_frame.h> //SYMBOL_ORIENTATION_T
38 #include <sch_io_mgr.h>
39 #include <sch_junction.h>
40 #include <sch_line.h>
41 #include <sch_screen.h>
42 #include <sch_sheet.h>
43 #include <sch_sheet_path.h>
44 #include <sch_sheet_pin.h>
45 #include <sch_text.h>
46 #include <schematic.h>
47 #include <trigo.h>
49 
50 
51 const wxString PartNameFieldName = "Part Name";
52 
53 
54 void CADSTAR_SCH_ARCHIVE_LOADER::Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet,
55  SCH_PLUGIN::SCH_PLUGIN_RELEASER* aSchPlugin, const wxFileName& aLibraryFileName )
56 {
57  Parse();
58 
60 
61  //Note: can't use getKiCadPoint() due wxPoint being int - need long long to make the check
62  long long designSizeXkicad = (long long) designLimit.x / KiCadUnitDivider;
63  long long designSizeYkicad = (long long) designLimit.y / KiCadUnitDivider;
64 
65  // Max size limited by the positive dimension of wxPoint (which is an int)
66  constexpr long long maxDesignSizekicad = std::numeric_limits<int>::max();
67 
68  if( designSizeXkicad > maxDesignSizekicad || designSizeYkicad > maxDesignSizekicad )
69  {
71  _( "The design is too large and cannot be imported into KiCad. \n"
72  "Please reduce the maximum design size in CADSTAR by navigating to: \n"
73  "Design Tab -> Properties -> Design Options -> Maximum Design Size. \n"
74  "Current Design size: %.2f, %.2f millimeters. \n"
75  "Maximum permitted design size: %.2f, %.2f millimeters.\n" ),
76  (double) designSizeXkicad / SCH_IU_PER_MM,
77  (double) designSizeYkicad / SCH_IU_PER_MM,
78  (double) maxDesignSizekicad / SCH_IU_PER_MM,
79  (double) maxDesignSizekicad / SCH_IU_PER_MM ) );
80  }
81 
82  // Assume the centre at 0,0 since we are going to be translating the design afterwards anyway
83  m_designCenter = { 0, 0 };
84 
85  m_schematic = aSchematic;
86  m_rootSheet = aRootSheet;
87  m_plugin = aSchPlugin;
88  m_libraryFileName = aLibraryFileName;
89 
90  loadTextVariables(); // Load text variables right at the start to ensure bounding box
91  // calculations work correctly for text items
92  loadSheets();
96  loadBusses();
97  loadNets();
98  loadFigures();
99  loadTexts();
101 
102  if( Schematic.VariantHierarchy.Variants.size() > 0 )
103  {
104  m_reporter->Report( wxString::Format( _( "The CADSTAR design contains variants which has "
105  "no KiCad equivalent. Only the master variant "
106  "('%s') was loaded." ),
107  Schematic.VariantHierarchy.Variants.at( "V0" ).Name ),
109  }
110 
111  if( Schematic.Groups.size() > 0 )
112  {
113  m_reporter->Report( _( "The CADSTAR design contains grouped items which has no KiCad "
114  "equivalent. Any grouped items have been ungrouped." ),
116  }
117 
118  if( Schematic.ReuseBlocks.size() > 0 )
119  {
120  m_reporter->Report( _( "The CADSTAR design contains re-use blocks which has no KiCad "
121  "equivalent. The re-use block information has been discarded during "
122  "the import." ),
124  }
125 
126 
127  // For all sheets, centre all elements and re calculate the page size:
128  for( std::pair<LAYER_ID, SCH_SHEET*> sheetPair : m_sheetMap )
129  {
130  SCH_SHEET* sheet = sheetPair.second;
131 
132  // Calculate the new sheet size.
133  EDA_RECT sheetBoundingBox;
134 
135  for( auto item : sheet->GetScreen()->Items() )
136  {
137  EDA_RECT bbox;
138 
139  // Only use the visible fields of the symbols to calculate their bounding box
140  // (hidden fields could be very long and artificially enlarge the sheet bounding box)
141  if( item->Type() == SCH_SYMBOL_T )
142  {
143  SCH_SYMBOL* comp = static_cast<SCH_SYMBOL*>( item );
144  bbox = comp->GetBodyBoundingBox();
145 
146  for( const SCH_FIELD& field : comp->GetFields() )
147  {
148  if( field.IsVisible() )
149  bbox.Merge( field.GetBoundingBox() );
150  }
151  }
152  else
153  {
154  bbox = item->GetBoundingBox();
155  }
156 
157  sheetBoundingBox.Merge( bbox );
158  }
159 
160  // Find the working grid of the original CADSTAR design
162 
167 
168  grid = getKiCadLength( grid );
169 
170  auto roundToNearestGrid =
171  [&]( int aNumber ) -> int
172  {
173  int error = aNumber % grid;
174  int absError = sign( error ) * error;
175 
176  if( absError > ( grid / 2 ) )
177  return aNumber + ( sign( error ) * grid ) - error;
178  else
179  return aNumber - error;
180  };
181 
182  // When exporting to pdf, CADSTAR applies a margin of 3% of the longest dimension (height
183  // or width) to all 4 sides (top, bottom, left right). For the import, we are also rounding
184  // the margin to the nearest grid, ensuring all items remain on the grid.
185  wxSize targetSheetSize = sheetBoundingBox.GetSize();
186  int longestSide = std::max( targetSheetSize.x, targetSheetSize.y );
187  int margin = ( (double) longestSide * 0.03);
188  margin = roundToNearestGrid( margin );
189  targetSheetSize.IncBy( margin * 2, margin * 2 );
190 
191  // Update page size always
192  PAGE_INFO pageInfo = sheet->GetScreen()->GetPageSettings();
193  pageInfo.SetWidthMils( Iu2Mils( targetSheetSize.x ) );
194  pageInfo.SetHeightMils( Iu2Mils( targetSheetSize.y ) );
195 
196  // Set the new sheet size.
197  sheet->GetScreen()->SetPageSettings( pageInfo );
198 
199 
200  wxSize pageSizeIU = sheet->GetScreen()->GetPageSettings().GetSizeIU();
201  wxPoint sheetcentre( pageSizeIU.x / 2, pageSizeIU.y / 2 );
202  wxPoint itemsCentre = sheetBoundingBox.Centre();
203 
204  // round the translation to nearest point on the grid
205  wxPoint translation = sheetcentre - itemsCentre;
206  translation.x = roundToNearestGrid( translation.x );
207  translation.y = roundToNearestGrid( translation.y );
208 
209  // Translate the items.
210  std::vector<SCH_ITEM*> allItems;
211 
212  std::copy( sheet->GetScreen()->Items().begin(), sheet->GetScreen()->Items().end(),
213  std::back_inserter( allItems ) );
214 
215  for( SCH_ITEM* item : allItems )
216  {
217  item->SetPosition( item->GetPosition() + translation );
218  item->ClearFlags();
219  sheet->GetScreen()->Update( item );
220  }
221  }
222 
223  m_reporter->Report( _( "The CADSTAR design has been imported successfully.\n"
224  "Please review the import errors and warnings (if any)." ) );
225 }
226 
227 
229 {
230  const std::vector<LAYER_ID>& orphanSheets = findOrphanSheets();
231  SCH_SHEET_PATH rootPath;
232  rootPath.push_back( m_rootSheet );
233  m_rootSheet->AddInstance( rootPath.Path() );
234  m_rootSheet->SetPageNumber( rootPath, wxT( "1" ) );
235 
236  if( orphanSheets.size() > 1 )
237  {
238  int x = 1;
239  int y = 1;
240 
241  for( LAYER_ID sheetID : orphanSheets )
242  {
243  wxPoint pos( x * Mils2iu( 1000 ), y * Mils2iu( 1000 ) );
244  wxSize siz( Mils2iu( 1000 ), Mils2iu( 1000 ) );
245 
246  loadSheetAndChildSheets( sheetID, pos, siz, rootPath );
247 
248  x += 2;
249 
250  if( x > 10 ) // start next row
251  {
252  x = 1;
253  y += 2;
254  }
255  }
256  }
257  else if( orphanSheets.size() > 0 )
258  {
259  LAYER_ID rootSheetID = orphanSheets.at( 0 );
260 
261  wxFileName loadedFilePath = wxFileName( Filename );
262 
263  std::string filename = wxString::Format(
264  "%s_%02d", loadedFilePath.GetName(), getSheetNumber( rootSheetID ) )
265  .ToStdString();
266  ReplaceIllegalFileNameChars( &filename );
267  filename += wxT( "." ) + KiCadSchematicFileExtension;
268 
269  wxFileName fn( m_schematic->Prj().GetProjectPath() + filename );
270  m_rootSheet->GetScreen()->SetFileName( fn.GetFullPath() );
271 
272  m_sheetMap.insert( { rootSheetID, m_rootSheet } );
273  loadChildSheets( rootSheetID, rootPath );
274  }
275  else
276  {
277  THROW_IO_ERROR( _( "The CADSTAR schematic might be corrupt: there is no root sheet." ) );
278  }
279 }
280 
281 
283 {
284  for( std::pair<BLOCK_ID, BLOCK> blockPair : Schematic.Blocks )
285  {
286  BLOCK& block = blockPair.second;
287  LAYER_ID sheetID = "";
288 
289  if( block.Type == BLOCK::TYPE::PARENT )
290  sheetID = block.LayerID;
291  else if( block.Type == BLOCK::TYPE::CHILD )
292  sheetID = block.AssocLayerID;
293  else
294  continue;
295 
296  if( m_sheetMap.find( sheetID ) != m_sheetMap.end() )
297  {
298  SCH_SHEET* sheet = m_sheetMap.at( sheetID );
299 
300  for( std::pair<TERMINAL_ID, TERMINAL> termPair : block.Terminals )
301  {
302  TERMINAL term = termPair.second;
303  wxString name = "YOU SHOULDN'T SEE THIS TEXT. THIS IS A BUG.";
304 
305  SCH_HIERLABEL* sheetPin = nullptr;
306 
307  if( block.Type == BLOCK::TYPE::PARENT )
308  sheetPin = new SCH_HIERLABEL();
309  else if( block.Type == BLOCK::TYPE::CHILD )
310  sheetPin = new SCH_SHEET_PIN( sheet );
311 
312  sheetPin->SetText( name );
314  sheetPin->SetLabelSpinStyle( getSpinStyle( term.OrientAngle, false ) );
315  sheetPin->SetPosition( getKiCadPoint( term.Position ) );
316 
317  if( sheetPin->Type() == SCH_SHEET_PIN_T )
318  sheet->AddPin( (SCH_SHEET_PIN*) sheetPin );
319  else
320  sheet->GetScreen()->Append( sheetPin );
321 
322  BLOCK_PIN_ID blockPinID = std::make_pair( block.ID, term.ID );
323  m_sheetPinMap.insert( { blockPinID, sheetPin } );
324  }
325  }
326  }
327 }
328 
329 
331 {
332  for( std::pair<PART_ID, PART> partPair : Parts.PartDefinitions )
333  {
334  PART_ID partID = partPair.first;
335  PART part = partPair.second;
336 
337  if( part.Definition.GateSymbols.size() == 0 )
338  continue;
339 
340  LIB_SYMBOL* kiPart = new LIB_SYMBOL( part.Name );
341 
342  kiPart->SetUnitCount( part.Definition.GateSymbols.size() );
343  bool ok = true;
344 
345  for( std::pair<GATE_ID, PART::DEFINITION::GATE> gatePair : part.Definition.GateSymbols )
346  {
347  GATE_ID gateID = gatePair.first;
348  PART::DEFINITION::GATE gate = gatePair.second;
349  SYMDEF_ID symbolID = getSymDefFromName( gate.Name, gate.Alternate );
350  m_partSymbolsMap.insert( { { partID, gateID }, symbolID } );
351 
352  if( symbolID.IsEmpty() )
353  {
354  m_reporter->Report( wxString::Format( _( "Part definition '%s' references symbol "
355  "'%s' (alternate '%s') which could not be "
356  "found in the symbol library. The part has "
357  "not been loaded into the KiCad library." ),
358  part.Name,
359  gate.Name,
360  gate.Alternate ),
362 
363  ok = false;
364  break;
365  }
366 
367  loadSymDefIntoLibrary( symbolID, &part, gateID, kiPart );
368  }
369 
370  if( ok )
371  {
372  ( *m_plugin )->SaveSymbol( m_libraryFileName.GetFullPath(), kiPart );
373 
374  LIB_SYMBOL* loadedPart =
375  ( *m_plugin )->LoadSymbol( m_libraryFileName.GetFullPath(), kiPart->GetName() );
376 
377  m_partMap.insert( { partID, loadedPart } );
378  }
379  else
380  {
381  // Don't save in the library, but still keep it cached as some of the units might have
382  // been loaded correctly (saving us time later on)
383  m_partMap.insert( { partID, kiPart } );
384  }
385  }
386 }
387 
388 
390 {
391  for( std::pair<SYMBOL_ID, SYMBOL> symPair : Schematic.Symbols )
392  {
393  SYMBOL sym = symPair.second;
394 
395  if( !sym.VariantID.empty() && sym.VariantParentSymbolID != sym.ID )
396  continue; // Only load master Variant
397 
398  if( sym.IsComponent )
399  {
400  if( m_partMap.find( sym.PartRef.RefID ) == m_partMap.end() )
401  {
402  m_reporter->Report( wxString::Format( _( "Symbol '%s' references part '%s' which "
403  "could not be found in the library. The "
404  "symbol was not loaded" ),
406  sym.PartRef.RefID ),
408 
409  continue;
410  }
411 
412  if( sym.GateID.IsEmpty() )
413  sym.GateID = wxT( "A" ); // Assume Gate "A" if unspecified
414 
415  PART_GATE_ID partSymbolID = { sym.PartRef.RefID, sym.GateID };
416  LIB_SYMBOL* kiPart = m_partMap.at( sym.PartRef.RefID );
417  bool copy = false;
418 
419  // The symbol definition in the part either does not exist for this gate number
420  // or is different to the symbol instance. We need to load a new symbol
421  if( m_partSymbolsMap.find( partSymbolID ) == m_partSymbolsMap.end()
422  || m_partSymbolsMap.at( partSymbolID ) != sym.SymdefID )
423  {
424  kiPart = new LIB_SYMBOL( *kiPart ); // Make a copy
425  copy = true;
426  const PART& part = Parts.PartDefinitions.at( sym.PartRef.RefID );
427  loadSymDefIntoLibrary( sym.SymdefID, &part, sym.GateID, kiPart );
428  }
429 
430  LIB_SYMBOL* scaledPart = getScaledLibPart( kiPart, sym.ScaleRatioNumerator,
431  sym.ScaleRatioDenominator );
432 
433  double symOrientDeciDeg = 0.0;
434  SCH_SYMBOL* symbol = loadSchematicSymbol( sym, *scaledPart, symOrientDeciDeg );
435 
436  delete scaledPart;
437 
438  if( copy )
439  delete kiPart;
440 
441  SCH_FIELD* refField = symbol->GetField( REFERENCE_FIELD );
442 
443  sym.ComponentRef.Designator.Replace( wxT( "\n" ), wxT( "\\n" ) );
444  sym.ComponentRef.Designator.Replace( wxT( "\r" ), wxT( "\\r" ) );
445  sym.ComponentRef.Designator.Replace( wxT( "\t" ), wxT( "\\t" ) );
446  sym.ComponentRef.Designator.Replace( wxT( " " ), wxT( "_" ) );
447 
448  refField->SetText( sym.ComponentRef.Designator );
449  loadSymbolFieldAttribute( sym.ComponentRef.AttrLoc, symOrientDeciDeg,
450  sym.Mirror, refField );
451 
452  if( sym.HasPartRef )
453  {
454  SCH_FIELD* partField = symbol->FindField( PartNameFieldName );
455 
456  if( !partField )
457  {
458  int fieldID = symbol->GetFieldCount();
459  partField = symbol->AddField( SCH_FIELD( wxPoint(), fieldID, symbol,
460  PartNameFieldName ) );
461  }
462 
463  wxASSERT( partField->GetName() == PartNameFieldName );
464 
465  wxString partname = getPart( sym.PartRef.RefID ).Name;
466  partname.Replace( wxT( "\n" ), wxT( "\\n" ) );
467  partname.Replace( wxT( "\r" ), wxT( "\\r" ) );
468  partname.Replace( wxT( "\t" ), wxT( "\\t" ) );
469  partField->SetText( partname );
470 
471  loadSymbolFieldAttribute( sym.PartRef.AttrLoc, symOrientDeciDeg,
472  sym.Mirror, partField );
473 
475  }
476 
477  for( auto attr : sym.AttributeValues )
478  {
479  ATTRIBUTE_VALUE attrVal = attr.second;
480 
481  if( attrVal.HasLocation )
482  {
483  wxString attrName = getAttributeName( attrVal.AttributeID );
484  SCH_FIELD* attrField = symbol->FindField( attrName );
485 
486  if( !attrField )
487  {
488  int fieldID = symbol->GetFieldCount();
489  attrField = symbol->AddField( SCH_FIELD( wxPoint(), fieldID,
490  symbol, attrName ) );
491  }
492 
493  wxASSERT( attrField->GetName() == attrName );
494 
495  attrVal.Value.Replace( wxT( "\n" ), wxT( "\\n" ) );
496  attrVal.Value.Replace( wxT( "\r" ), wxT( "\\r" ) );
497  attrVal.Value.Replace( wxT( "\t" ), wxT( "\\t" ) );
498  attrField->SetText( attrVal.Value );
499 
500  loadSymbolFieldAttribute( attrVal.AttributeLocation, symOrientDeciDeg,
501  sym.Mirror, attrField );
502  attrField->SetVisible( isAttributeVisible( attrVal.AttributeID ) );
503  }
504  }
505  }
506  else if( sym.IsSymbolVariant )
507  {
508  if( Library.SymbolDefinitions.find( sym.SymdefID ) == Library.SymbolDefinitions.end() )
509  {
511  _( "Symbol ID '%s' references library symbol '%s' which could not be "
512  "found in the library. Did you export all items of the design?" ),
513  sym.ID, sym.PartRef.RefID ) );
514  }
515 
516  SYMDEF_SCM libSymDef = Library.SymbolDefinitions.at( sym.SymdefID );
517 
518  if( libSymDef.Terminals.size() != 1 )
519  {
521  _( "Symbol ID '%s' is a signal reference or global signal but it has too "
522  "many pins. The expected number of pins is 1 but %d were found." ),
523  sym.ID, libSymDef.Terminals.size() ) );
524  }
525 
526  if( sym.SymbolVariant.Type == SYMBOLVARIANT::TYPE::GLOBALSIGNAL )
527  {
528  SYMDEF_ID symID = sym.SymdefID;
529  LIB_SYMBOL* kiPart = nullptr;
530 
531  // In CADSTAR "GlobalSignal" is a special type of symbol which defines
532  // a Power Symbol. The "Alternate" name defines the default net name of
533  // the power symbol but this can be overridden in the design itself.
534  wxString libraryNetName = Library.SymbolDefinitions.at( symID ).Alternate;
535 
536  // Name of the net that the symbol instance in CADSTAR refers to:
537  wxString symbolInstanceNetName = sym.SymbolVariant.Reference;
538  symbolInstanceNetName = LIB_ID::FixIllegalChars( symbolInstanceNetName );
539 
540  // Name of the symbol we will use for saving the part in KiCad
541  // Note: In CADSTAR all power symbols will start have the reference name be
542  // "GLOBALSIGNAL" followed by the default net name, so it makes sense to save
543  // the symbol in KiCad as the default net name as well.
544  wxString libPartName = libraryNetName;
545 
546  // In CADSTAR power symbol instances can refer to a different net to that defined
547  // in the library. This causes problems in KiCad v6 as it breaks connectivity when
548  // the user decides to update all symbols from library. We handle this by creating
549  // individual versions of the power symbol for each net name.
550  if( libPartName != symbolInstanceNetName )
551  {
552  libPartName += wxT( " (" ) + symbolInstanceNetName + wxT( ")" );
553  }
554 
555  if( m_powerSymLibMap.find( libPartName ) == m_powerSymLibMap.end() )
556  {
557  SYMDEF_SCM symbolDef = Library.SymbolDefinitions.at( symID );
558 
559  kiPart = new LIB_SYMBOL( libPartName );
560  kiPart->SetPower();
561  loadSymDefIntoLibrary( symID, nullptr, "A", kiPart );
562 
563  kiPart->GetValueField().SetText( symbolInstanceNetName );
564 
565  if( symbolDef.TextLocations.find( SIGNALNAME_ORIGIN_ATTRID )
566  != symbolDef.TextLocations.end() )
567  {
568  TEXT_LOCATION txtLoc =
569  symbolDef.TextLocations.at( SIGNALNAME_ORIGIN_ATTRID );
570 
571  wxPoint valPos = getKiCadLibraryPoint( txtLoc.Position, symbolDef.Origin );
572 
573  kiPart->GetValueField().SetPosition( valPos );
574  kiPart->GetValueField().SetVisible( true );
575  }
576  else
577  {
578  kiPart->GetValueField().SetVisible( false );
579  }
580 
581  kiPart->GetReferenceField().SetText( "#PWR" );
582  kiPart->GetReferenceField().SetVisible( false );
583  ( *m_plugin )->SaveSymbol( m_libraryFileName.GetFullPath(), kiPart );
584  m_powerSymLibMap.insert( { libPartName, kiPart } );
585  }
586  else
587  {
588  kiPart = m_powerSymLibMap.at( libPartName );
589  wxASSERT( kiPart->GetValueField().GetText() == symbolInstanceNetName );
590  }
591 
592  LIB_SYMBOL* scaledPart = getScaledLibPart( kiPart, sym.ScaleRatioNumerator,
593  sym.ScaleRatioDenominator );
594 
595  double returnedOrient = 0.0;
596  SCH_SYMBOL* symbol = loadSchematicSymbol( sym, *scaledPart, returnedOrient );
597  m_powerSymMap.insert( { sym.ID, symbol } );
598 
599  delete scaledPart;
600  }
601  else if( sym.SymbolVariant.Type == SYMBOLVARIANT::TYPE::SIGNALREF )
602  {
603  // There should only be one pin and we'll use that to set the position
604  TERMINAL& symbolTerminal = libSymDef.Terminals.begin()->second;
605  wxPoint terminalPosOffset = symbolTerminal.Position - libSymDef.Origin;
606  double rotateDeciDegree = getAngleTenthDegree( sym.OrientAngle );
607 
608  if( sym.Mirror )
609  rotateDeciDegree += 1800.0;
610 
611  RotatePoint( &terminalPosOffset, -rotateDeciDegree );
612 
613  SCH_GLOBALLABEL* netLabel = new SCH_GLOBALLABEL;
614  netLabel->SetPosition( getKiCadPoint( sym.Origin + terminalPosOffset ) );
615  netLabel->SetText( "YOU SHOULDN'T SEE THIS TEXT - PLEASE REPORT THIS BUG" );
616  netLabel->SetTextSize( wxSize( Mils2iu( 50 ), Mils2iu( 50 ) ) );
617  netLabel->SetLabelSpinStyle( getSpinStyle( sym.OrientAngle, sym.Mirror ) );
618 
619  if( libSymDef.Alternate.Lower().Contains( "in" ) )
621  else if( libSymDef.Alternate.Lower().Contains( "bi" ) )
623  else if( libSymDef.Alternate.Lower().Contains( "out" ) )
625  else
627 
628  m_sheetMap.at( sym.LayerID )->GetScreen()->Append( netLabel );
629  m_globalLabelsMap.insert( { sym.ID, netLabel } );
630  }
631  else
632  {
633  wxASSERT_MSG( false, "Unknown Symbol Variant." );
634  }
635  }
636  else
637  {
638  m_reporter->Report( wxString::Format( _( "Symbol ID '%s' is of an unknown type. It is "
639  "neither a symbol or a net power / symbol. "
640  "The symbol was not loaded." ),
641  sym.ID ),
643  }
644 
645  if( sym.ScaleRatioDenominator != 1 || sym.ScaleRatioNumerator != 1 )
646  {
647  wxString symbolName = sym.ComponentRef.Designator;
648 
649  if( symbolName.empty() )
650  symbolName = wxString::Format( "ID: %s", sym.ID);
651 
652  m_reporter->Report( wxString::Format( _( "Symbol '%s' is scaled in the original "
653  "CADSTAR schematic but this is not supported "
654  "in KiCad. When the symbol is reloaded from "
655  "the library, it will revert to the original "
656  "1:1 scale." ),
657  symbolName,
658  sym.PartRef.RefID ),
660  }
661  }
662 }
663 
664 
666 {
667  for( std::pair<BUS_ID, BUS> busPair : Schematic.Buses )
668  {
669  BUS bus = busPair.second;
670  bool firstPt = true;
671  VERTEX last;
672 
673  if( bus.LayerID != wxT( "NO_SHEET" ) )
674  {
675  SCH_SCREEN* screen = m_sheetMap.at( bus.LayerID )->GetScreen();
676  std::shared_ptr<BUS_ALIAS> kiBusAlias = std::make_shared<BUS_ALIAS>();
677 
678  kiBusAlias->SetName( bus.Name );
679  kiBusAlias->SetParent( screen );
680  screen->AddBusAlias( kiBusAlias );
681  m_busesMap.insert( { bus.ID, kiBusAlias } );
682 
683  SCH_LABEL* label = new SCH_LABEL();
684  label->SetText( wxT( "{" ) + bus.Name + wxT( "}" ) );
685  label->SetVisible( true );
686  screen->Append( label );
687 
688  SHAPE_LINE_CHAIN busLineChain; // to compute nearest segment to bus label
689 
690  for( const VERTEX& cur : bus.Shape.Vertices )
691  {
692  busLineChain.Append( getKiCadPoint( cur.End ) );
693 
694  if( firstPt )
695  {
696  last = cur;
697  firstPt = false;
698 
699  if( !bus.HasBusLabel )
700  {
701  // Add a bus label on the starting point if the original CADSTAR design
702  // does not have an explicit label
703  label->SetPosition( getKiCadPoint( last.End ) );
704  }
705 
706  continue;
707  }
708 
709 
710  SCH_LINE* kiBus = new SCH_LINE();
711 
712  kiBus->SetStartPoint( getKiCadPoint( last.End ) );
713  kiBus->SetEndPoint( getKiCadPoint( cur.End ) );
714  kiBus->SetLayer( LAYER_BUS );
715  kiBus->SetLineWidth( getLineThickness( bus.LineCodeID ) );
716  screen->Append( kiBus );
717 
718  last = cur;
719  }
720 
721  if( bus.HasBusLabel )
722  {
723  //lets find the closest point in the busline to the label
724  VECTOR2I busLabelLoc = getKiCadPoint( bus.BusLabel.Position );
725  wxPoint nearestPt = (wxPoint) busLineChain.NearestPoint( busLabelLoc );
726 
727  label->SetPosition( nearestPt );
728 
729  applyTextSettings( label,
730  bus.BusLabel.TextCodeID,
731  bus.BusLabel.Alignment,
732  bus.BusLabel.Justification );
733 
734  // Note orientation of the bus label will be determined in loadNets
735  // (the position of the wire will determine how best to place the bus label)
736  }
737  }
738 
739  }
740 }
741 
742 
744 {
745  for( std::pair<NET_ID, NET_SCH> netPair : Schematic.Nets )
746  {
747  NET_SCH net = netPair.second;
748  wxString netName = net.Name;
749  std::map<NETELEMENT_ID, SCH_LABEL*> netlabels;
750 
751  if( netName.IsEmpty() )
752  netName = wxString::Format( "$%ld", net.SignalNum );
753 
754 
755  for( std::pair<NETELEMENT_ID, NET_SCH::SYM_TERM> terminalPair : net.Terminals )
756  {
757  NET_SCH::SYM_TERM netTerm = terminalPair.second;
758 
759  if( m_powerSymMap.find( netTerm.SymbolID ) != m_powerSymMap.end() )
760  {
761  SCH_FIELD* val = m_powerSymMap.at( netTerm.SymbolID )->GetField( VALUE_FIELD );
762  val->SetText( netName );
763  val->SetBold( false );
764  val->SetVisible( false );
765 
766  if( netTerm.HasNetLabel )
767  {
768  val->SetVisible( true );
769  val->SetPosition( getKiCadPoint( netTerm.NetLabel.Position ) );
770 
771  applyTextSettings( val,
772  netTerm.NetLabel.TextCodeID,
773  netTerm.NetLabel.Alignment,
774  netTerm.NetLabel.Justification,
775  netTerm.NetLabel.OrientAngle,
776  netTerm.NetLabel.Mirror );
777  }
778  }
779  else if( m_globalLabelsMap.find( netTerm.SymbolID ) != m_globalLabelsMap.end() )
780  {
781  m_globalLabelsMap.at( netTerm.SymbolID )->SetText( netName );
782  }
783  }
784 
785  auto getHierarchicalLabel =
786  [&]( NETELEMENT_ID aNode ) -> SCH_HIERLABEL*
787  {
788  if( aNode.Contains( "BLKT" ) )
789  {
790  NET_SCH::BLOCK_TERM blockTerm = net.BlockTerminals.at( aNode );
791  BLOCK_PIN_ID blockPinID = std::make_pair( blockTerm.BlockID,
792  blockTerm.TerminalID );
793 
794  if( m_sheetPinMap.find( blockPinID )
795  != m_sheetPinMap.end() )
796  {
797  return m_sheetPinMap.at( blockPinID );
798  }
799  }
800 
801  return nullptr;
802  };
803 
804  //Add net name to all hierarchical pins (block terminals in CADSTAR)
805  for( std::pair<NETELEMENT_ID, NET_SCH::BLOCK_TERM> blockPair : net.BlockTerminals )
806  {
807  SCH_HIERLABEL* label = getHierarchicalLabel( blockPair.first );
808 
809  if(label)
810  label->SetText( netName );
811  }
812 
813  // Load all bus entries and add net label if required
814  for( std::pair<NETELEMENT_ID, NET_SCH::BUS_TERM> busPair : net.BusTerminals )
815  {
816  NET_SCH::BUS_TERM busTerm = busPair.second;
817  BUS bus = Schematic.Buses.at( busTerm.BusID );
818 
819  if( !m_busesMap.at( bus.ID )->Contains( netName ) )
820  m_busesMap.at( bus.ID )->AddMember( netName );
821 
822  SCH_BUS_WIRE_ENTRY* busEntry =
823  new SCH_BUS_WIRE_ENTRY( getKiCadPoint( busTerm.FirstPoint ), false );
824 
825  wxPoint size =
826  getKiCadPoint( busTerm.SecondPoint ) - getKiCadPoint( busTerm.FirstPoint );
827  busEntry->SetSize( wxSize( size.x, size.y ) );
828 
829  m_sheetMap.at( bus.LayerID )->GetScreen()->Append( busEntry );
830 
831  // Always add a label at bus terminals to ensure connectivity.
832  // If the original design does not have a label, just make it very small
833  // to keep connectivity but make the design look visually similar to
834  // the original.
835  SCH_LABEL* label = new SCH_LABEL();
836  label->SetText( netName );
837  label->SetPosition( getKiCadPoint( busTerm.SecondPoint ) );
838  label->SetVisible( true );
839 
840  if( busTerm.HasNetLabel )
841  {
842  applyTextSettings( label,
843  busTerm.NetLabel.TextCodeID,
844  busTerm.NetLabel.Alignment,
845  busTerm.NetLabel.Justification );
846  }
847  else
848  {
849  const int smallText = KiROUND( (double) SCH_IU_PER_MM * 0.4 );
850  label->SetTextSize( wxSize( smallText, smallText ) );
851  }
852 
853  netlabels.insert( { busTerm.ID, label } );
854  m_sheetMap.at( bus.LayerID )->GetScreen()->Append( label );
855  }
856 
857 
858  for( std::pair<NETELEMENT_ID, NET_SCH::DANGLER> danglerPair : net.Danglers )
859  {
860  NET_SCH::DANGLER dangler = danglerPair.second;
861 
862  SCH_LABEL* label = new SCH_LABEL();
863  label->SetText( netName );
864  label->SetPosition( getKiCadPoint( dangler.Position ) );
865  label->SetVisible( true );
866  netlabels.insert( { dangler.ID, label } );
867 
868  m_sheetMap.at( dangler.LayerID )->GetScreen()->Append( label );
869  }
870 
871 
872  for( NET_SCH::CONNECTION_SCH conn : net.Connections )
873  {
874  if( conn.LayerID == wxT( "NO_SHEET" ) )
875  continue; // No point loading virtual connections. KiCad handles that internally
876 
877  POINT start = getLocationOfNetElement( net, conn.StartNode );
878  POINT end = getLocationOfNetElement( net, conn.EndNode );
879 
880  if( start.x == UNDEFINED_VALUE || end.x == UNDEFINED_VALUE )
881  continue;
882 
883  // Connections in CADSTAR are always implied between symbols even if the route
884  // doesn't start and end exactly at the connection points
885  if( conn.Path.size() < 1 || conn.Path.front() != start )
886  conn.Path.insert( conn.Path.begin(), start );
887 
888  if( conn.Path.size() < 2 || conn.Path.back() != end )
889  conn.Path.push_back( end );
890 
891  bool firstPt = true;
892  bool secondPt = false;
893  wxPoint last;
894  SCH_LINE* wire = nullptr;
895 
896  SHAPE_LINE_CHAIN wireChain; // Create a temp. line chain representing the connection
897 
898  for( POINT pt : conn.Path )
899  {
900  wireChain.Append( getKiCadPoint( pt ) );
901  }
902 
903  // AUTO-FIX SHEET PINS
904  //--------------------
905  // KiCad constrains the sheet pin on the edge of the sheet object whereas in
906  // CADSTAR it can be anywhere. Let's find the intersection of the wires with the sheet
907  // and place the hierarchical
908  std::vector<NETELEMENT_ID> nodes;
909  nodes.push_back( conn.StartNode );
910  nodes.push_back( conn.EndNode );
911 
912  for( NETELEMENT_ID node : nodes )
913  {
914  SCH_HIERLABEL* sheetPin = getHierarchicalLabel( node );
915 
916  if( sheetPin )
917  {
918  if( sheetPin->Type() == SCH_SHEET_PIN_T
919  && SCH_SHEET::ClassOf( sheetPin->GetParent() ) )
920  {
921  SCH_SHEET* parentSheet = static_cast<SCH_SHEET*>( sheetPin->GetParent() );
922  wxSize sheetSize = parentSheet->GetSize();
923  wxPoint sheetPosition = parentSheet->GetPosition();
924 
925  int leftSide = sheetPosition.x;
926  int rightSide = sheetPosition.x + sheetSize.x;
927  int topSide = sheetPosition.y;
928  int botSide = sheetPosition.y + sheetSize.y;
929 
930  SHAPE_LINE_CHAIN sheetEdge;
931 
932  sheetEdge.Append( leftSide, topSide );
933  sheetEdge.Append( rightSide, topSide );
934  sheetEdge.Append( rightSide, botSide );
935  sheetEdge.Append( leftSide, botSide );
936  sheetEdge.Append( leftSide, topSide );
937 
938  SHAPE_LINE_CHAIN::INTERSECTIONS wireToSheetIntersects;
939 
940  if( !wireChain.Intersect( sheetEdge, wireToSheetIntersects ) )
941  {
942  // The block terminal is outside the block shape in the original
943  // CADSTAR design. Since KiCad's Sheet Pin will already be constrained
944  // on the edge, we will simply join to it with a straight line.
945  if( node == conn.StartNode )
946  wireChain = wireChain.Reverse();
947 
948  wireChain.Append( sheetPin->GetPosition() );
949 
950  if( node == conn.StartNode )
951  wireChain = wireChain.Reverse();
952  }
953  else
954  {
955  // The block terminal is either inside or on the shape edge. Lets use the
956  // first interection point
957  VECTOR2I intsctPt = wireToSheetIntersects.at( 0 ).p;
958  int intsctIndx = wireChain.FindSegment( intsctPt );
959  wxASSERT_MSG( intsctIndx != -1, "Can't find intersecting segment" );
960 
961  if( node == conn.StartNode )
962  wireChain.Replace( 0, intsctIndx, intsctPt );
963  else
964  wireChain.Replace( intsctIndx + 1, /*end index*/ -1, intsctPt );
965 
966  sheetPin->SetPosition( (wxPoint) intsctPt );
967  }
968  }
969  }
970  }
971 
972  auto fixNetLabelsAndSheetPins =
973  [&]( double aWireAngleDeciDeg, NETELEMENT_ID& aNetEleID )
974  {
975  LABEL_SPIN_STYLE spin = getSpinStyleDeciDeg( aWireAngleDeciDeg );
976 
977  if( netlabels.find( aNetEleID ) != netlabels.end() )
978  netlabels.at( aNetEleID )->SetLabelSpinStyle( spin.MirrorY() );
979 
980  SCH_HIERLABEL* sheetPin = getHierarchicalLabel( aNetEleID );
981 
982  if( sheetPin )
983  sheetPin->SetLabelSpinStyle( spin.MirrorX() );
984  };
985 
986  // Now we can load the wires and fix the label orientations
987  for( const VECTOR2I& pt : wireChain.CPoints() )
988  {
989  if( firstPt )
990  {
991  last = (wxPoint) pt;
992  firstPt = false;
993  secondPt = true;
994  continue;
995  }
996 
997  if( secondPt )
998  {
999  secondPt = false;
1000 
1001 
1002  wxPoint kiLast = last;
1003  wxPoint kiCurrent = (wxPoint) pt;
1004  double wireangleDeciDeg = getPolarAngle( kiLast - kiCurrent );
1005  fixNetLabelsAndSheetPins( wireangleDeciDeg, conn.StartNode );
1006  }
1007 
1008  wire = new SCH_LINE();
1009 
1010  wire->SetStartPoint( last );
1011  wire->SetEndPoint( (wxPoint) pt );
1012  wire->SetLayer( LAYER_WIRE );
1013 
1014  if( !conn.ConnectionLineCode.IsEmpty() )
1015  wire->SetLineWidth( getLineThickness( conn.ConnectionLineCode ) );
1016 
1017  last = (wxPoint) pt;
1018 
1019  m_sheetMap.at( conn.LayerID )->GetScreen()->Append( wire );
1020  }
1021 
1022  //Fix labels on the end wire
1023  if( wire )
1024  {
1025  wxPoint kiLast = wire->GetEndPoint();
1026  wxPoint kiCurrent = wire->GetStartPoint();
1027  double wireangleDeciDeg = getPolarAngle( kiLast - kiCurrent );
1028  fixNetLabelsAndSheetPins( wireangleDeciDeg, conn.EndNode );
1029  }
1030  }
1031 
1032  for( std::pair<NETELEMENT_ID, NET_SCH::JUNCTION_SCH> juncPair : net.Junctions )
1033  {
1034  NET_SCH::JUNCTION_SCH junc = juncPair.second;
1035 
1036  SCH_JUNCTION* kiJunc = new SCH_JUNCTION();
1037 
1038  kiJunc->SetPosition( getKiCadPoint( junc.Location ) );
1039  m_sheetMap.at( junc.LayerID )->GetScreen()->Append( kiJunc );
1040 
1041  if( junc.HasNetLabel )
1042  {
1043  // In CADSTAR the label can be placed anywhere, but in KiCad it has to be placed
1044  // in the same location as the junction for it to be connected to it.
1045  SCH_LABEL* label = new SCH_LABEL();
1046  label->SetText( netName );
1047  label->SetPosition( getKiCadPoint( junc.Location ) );
1048  label->SetVisible( true );
1049 
1050  double labelAngleDeciDeg = getAngleTenthDegree( junc.NetLabel.OrientAngle );
1051  LABEL_SPIN_STYLE spin = getSpinStyleDeciDeg( labelAngleDeciDeg );
1052  label->SetLabelSpinStyle( spin );
1053 
1054  m_sheetMap.at( junc.LayerID )->GetScreen()->Append( label );
1055  }
1056  }
1057  }
1058 }
1059 
1060 
1062 {
1063  for( std::pair<FIGURE_ID, FIGURE> figPair : Schematic.Figures )
1064  {
1065  FIGURE fig = figPair.second;
1066 
1067  loadFigure( fig, fig.LayerID, LAYER_NOTES );
1068  }
1069 }
1070 
1071 
1073 {
1074  for( std::pair<TEXT_ID, TEXT> textPair : Schematic.Texts )
1075  {
1076  TEXT txt = textPair.second;
1077 
1078  SCH_TEXT* kiTxt = getKiCadSchText( txt );
1079  loadItemOntoKiCadSheet( txt.LayerID, kiTxt );
1080  }
1081 }
1082 
1083 
1085 {
1086  for( std::pair<DOCUMENTATION_SYMBOL_ID, DOCUMENTATION_SYMBOL> docSymPair :
1088  {
1089  DOCUMENTATION_SYMBOL docSym = docSymPair.second;
1090 
1091  if( Library.SymbolDefinitions.find( docSym.SymdefID ) == Library.SymbolDefinitions.end() )
1092  {
1093  m_reporter->Report( wxString::Format( _( "Documentation Symbol '%s' refers to symbol "
1094  "definition ID '%s' which does not exist in "
1095  "the library. The symbol was not loaded." ),
1096  docSym.ID,
1097  docSym.SymdefID ),
1099  continue;
1100  }
1101 
1102  SYMDEF_SCM docSymDef = Library.SymbolDefinitions.at( docSym.SymdefID );
1103  wxPoint moveVector = getKiCadPoint( docSym.Origin ) - getKiCadPoint( docSymDef.Origin );
1104  double rotationAngle = getAngleTenthDegree( docSym.OrientAngle );
1105  double scalingFactor =
1106  (double) docSym.ScaleRatioNumerator / (double) docSym.ScaleRatioDenominator;
1107  wxPoint centreOfTransform = getKiCadPoint( docSymDef.Origin );
1108  bool mirrorInvert = docSym.Mirror;
1109 
1110  for( std::pair<FIGURE_ID, FIGURE> figPair : docSymDef.Figures )
1111  {
1112  FIGURE fig = figPair.second;
1113 
1114  loadFigure( fig, docSym.LayerID, LAYER_NOTES, moveVector, rotationAngle, scalingFactor,
1115  centreOfTransform, mirrorInvert );
1116  }
1117 
1118  for( std::pair<TEXT_ID, TEXT> textPair : docSymDef.Texts )
1119  {
1120  TEXT txt = textPair.second;
1121 
1122  txt.Mirror = ( txt.Mirror ) ? !mirrorInvert : mirrorInvert;
1123  txt.OrientAngle = docSym.OrientAngle - txt.OrientAngle;
1124 
1125  SCH_TEXT* kiTxt = getKiCadSchText( txt );
1126 
1127  wxPoint newPosition = applyTransform( kiTxt->GetPosition(), moveVector, rotationAngle,
1128  scalingFactor, centreOfTransform, mirrorInvert );
1129 
1130  int newTxtWidth = KiROUND( kiTxt->GetTextWidth() * scalingFactor );
1131  int newTxtHeight = KiROUND( kiTxt->GetTextHeight() * scalingFactor );
1132  int newTxtThickness = KiROUND( kiTxt->GetTextThickness() * scalingFactor );
1133 
1134  kiTxt->SetPosition( newPosition );
1135  kiTxt->SetTextWidth( newTxtWidth );
1136  kiTxt->SetTextHeight( newTxtHeight );
1137  kiTxt->SetTextThickness( newTxtThickness );
1138 
1139  loadItemOntoKiCadSheet( docSym.LayerID, kiTxt );
1140  }
1141  }
1142 }
1143 
1144 
1146 {
1147  auto findAndReplaceTextField = [&]( TEXT_FIELD_NAME aField, wxString aValue ) {
1148  if( m_context.TextFieldToValuesMap.find( aField ) != m_context.TextFieldToValuesMap.end() )
1149  {
1150  if( m_context.TextFieldToValuesMap.at( aField ) != aValue )
1151  {
1152  m_context.TextFieldToValuesMap.at( aField ) = aValue;
1153  m_context.InconsistentTextFields.insert( aField );
1154  return false;
1155  }
1156  }
1157  else
1158  {
1159  m_context.TextFieldToValuesMap.insert( { aField, aValue } );
1160  }
1161 
1162  return true;
1163  };
1164 
1165  PROJECT* pj = &m_schematic->Prj();
1166 
1167  if( pj )
1168  {
1169  std::map<wxString, wxString>& txtVars = pj->GetTextVars();
1170 
1171  // Most of the design text fields can be derived from other elements
1172  if( Schematic.VariantHierarchy.Variants.size() > 0 )
1173  {
1174  VARIANT loadedVar = Schematic.VariantHierarchy.Variants.begin()->second;
1175 
1176  findAndReplaceTextField( TEXT_FIELD_NAME::VARIANT_NAME, loadedVar.Name );
1177  findAndReplaceTextField( TEXT_FIELD_NAME::VARIANT_DESCRIPTION, loadedVar.Description );
1178  }
1179 
1180  findAndReplaceTextField( TEXT_FIELD_NAME::DESIGN_TITLE, Header.JobTitle );
1181 
1182  for( std::pair<TEXT_FIELD_NAME, wxString> txtvalue : m_context.TextFieldToValuesMap )
1183  {
1184  wxString varName = CADSTAR_TO_KICAD_FIELDS.at( txtvalue.first );
1185  wxString varValue = txtvalue.second;
1186 
1187  txtVars.insert( { varName, varValue } );
1188  }
1189 
1190  for( std::pair<wxString, wxString> txtvalue : m_context.FilenamesToTextMap )
1191  {
1192  wxString varName = txtvalue.first;
1193  wxString varValue = txtvalue.second;
1194 
1195  txtVars.insert( { varName, varValue } );
1196  }
1197  }
1198  else
1199  {
1200  m_reporter->Report( _( "Text Variables could not be set as there is no project attached." ),
1202  }
1203 }
1204 
1205 
1207  const PART* aCadstarPart, const GATE_ID& aGateID, LIB_SYMBOL* aSymbol )
1208 {
1209  wxCHECK( Library.SymbolDefinitions.find( aSymdefID ) != Library.SymbolDefinitions.end(), );
1210 
1211  SYMDEF_SCM symbol = Library.SymbolDefinitions.at( aSymdefID );
1212  int gateNumber = getKiCadUnitNumberFromGate( aGateID );
1213 
1214  for( std::pair<FIGURE_ID, FIGURE> figPair : symbol.Figures )
1215  {
1216  FIGURE fig = figPair.second;
1217 
1218  loadLibrarySymbolShapeVertices( fig.Shape.Vertices, symbol.Origin, aSymbol, gateNumber );
1219 
1220  for( CUTOUT c : fig.Shape.Cutouts )
1221  {
1222  loadLibrarySymbolShapeVertices( c.Vertices, symbol.Origin, aSymbol, gateNumber );
1223  }
1224  }
1225 
1226  TERMINAL_TO_PINNUM_MAP pinNumMap;
1227 
1228  for( std::pair<TERMINAL_ID, TERMINAL> termPair : symbol.Terminals )
1229  {
1230  TERMINAL term = termPair.second;
1231  wxString pinNum = wxString::Format( "%ld", term.ID );
1232  wxString pinName = wxEmptyString;
1233  LIB_PIN* pin = new LIB_PIN( aSymbol );
1234 
1235  if( aCadstarPart )
1236  {
1237  PART::DEFINITION::PIN csPin = getPartDefinitionPin( *aCadstarPart, aGateID, term.ID );
1238 
1239  pinName = csPin.Label;
1240  pinNum = csPin.Name;
1241 
1242  if( pinNum.IsEmpty() )
1243  {
1244  if( !csPin.Identifier.IsEmpty() )
1245  pinNum = csPin.Identifier;
1246  else if( csPin.ID == UNDEFINED_VALUE )
1247  pinNum = wxString::Format( "%ld", term.ID );
1248  else
1249  pinNum = wxString::Format( "%ld", csPin.ID );
1250  }
1251 
1252  pin->SetType( getKiCadPinType( csPin.Type ) );
1253 
1254  pinNumMap.insert( { term.ID, pinNum } );
1255  }
1256  else
1257  {
1258  // If no part is defined, we don't know the pin type. Assume passive pin
1259  pin->SetType( ELECTRICAL_PINTYPE::PT_PASSIVE );
1260  }
1261 
1262  pin->SetPosition( getKiCadLibraryPoint( term.Position, symbol.Origin ) );
1263  pin->SetLength( 0 ); //CADSTAR Pins are just a point (have no length)
1264  pin->SetShape( GRAPHIC_PINSHAPE::LINE );
1265  pin->SetUnit( gateNumber );
1266  pin->SetNumber( pinNum );
1267  pin->SetName( pinName );
1268 
1269  if( aSymbol->IsPower() )
1270  {
1271  pin->SetVisible( false );
1273  pin->SetName( aSymbol->GetName() );
1274  }
1275 
1276  aSymbol->AddDrawItem( pin );
1277  }
1278 
1279  fixUpLibraryPins( aSymbol, gateNumber );
1280 
1281  if(aCadstarPart)
1282  m_pinNumsMap.insert( { aCadstarPart->ID + aGateID, pinNumMap } );
1283 
1284  for( std::pair<TEXT_ID, TEXT> textPair : symbol.Texts )
1285  {
1286  TEXT csText = textPair.second;
1287 
1288  LIB_TEXT* libtext = new LIB_TEXT( aSymbol );
1289  libtext->SetText( csText.Text );
1290  libtext->SetUnit( gateNumber );
1291  libtext->SetPosition( getKiCadLibraryPoint( csText.Position, symbol.Origin ) );
1292  libtext->SetMultilineAllowed( true ); // temporarily so that we calculate bbox correctly
1293 
1294  applyTextSettings( libtext,
1295  csText.TextCodeID,
1296  csText.Alignment,
1297  csText.Justification,
1298  csText.OrientAngle,
1299  csText.Mirror );
1300 
1301  // Split out multi line text items into individual text elements
1302  if( csText.Text.Contains( "\n" ) )
1303  {
1304  wxArrayString strings;
1305  wxStringSplit( csText.Text, strings, '\n' );
1306  wxPoint firstLinePos;
1307 
1308  for( size_t ii = 0; ii < strings.size(); ++ii )
1309  {
1310  EDA_RECT bbox = libtext->GetTextBox( ii, true );
1311  wxPoint linePos = { bbox.GetLeft(), -bbox.GetBottom() };
1312 
1313  RotatePoint( &linePos, libtext->GetTextPos(), -libtext->GetTextAngle() );
1314 
1315  LIB_TEXT* line = static_cast<LIB_TEXT*>( libtext->Clone() );
1316  line->SetText( strings[ii] );
1317  line->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
1318  line->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
1319  line->SetTextPos( linePos );
1320 
1321  // Multiline text not allowed in LIB_TEXT
1322  line->SetMultilineAllowed( false );
1323  aSymbol->AddDrawItem( line );
1324  }
1325 
1326  delete libtext;
1327  }
1328  else
1329  {
1330  // Multiline text not allowed in LIB_TEXT
1331  libtext->SetMultilineAllowed( false );
1332  aSymbol->AddDrawItem( libtext );
1333  }
1334  }
1335 
1336  if( symbol.TextLocations.find( SYMBOL_NAME_ATTRID ) != symbol.TextLocations.end() )
1337  {
1338  TEXT_LOCATION textLoc = symbol.TextLocations.at( SYMBOL_NAME_ATTRID );
1339  LIB_FIELD* field = &aSymbol->GetReferenceField();
1340  applyToLibraryFieldAttribute( textLoc, symbol.Origin, field );
1341  field->SetUnit( gateNumber );
1342  }
1343 
1344  // Hide the value field for now (it might get unhidden if an attribute exists in the cadstar
1345  // design with the text "Value"
1346  aSymbol->GetValueField().SetVisible( false );
1347 
1348  if( symbol.TextLocations.find( PART_NAME_ATTRID ) != symbol.TextLocations.end() )
1349  {
1350  TEXT_LOCATION textLoc = symbol.TextLocations.at( PART_NAME_ATTRID );
1351  LIB_FIELD* field = aSymbol->FindField( PartNameFieldName );
1352 
1353  if( !field )
1354  {
1355  int fieldID = aSymbol->GetFieldCount();
1356  field = new LIB_FIELD( aSymbol, fieldID );
1357  field->SetName( PartNameFieldName );
1358  aSymbol->AddField( field );
1359  }
1360 
1361  wxASSERT( field->GetName() == PartNameFieldName );
1362  applyToLibraryFieldAttribute( textLoc, symbol.Origin, field );
1363 
1364  if( aCadstarPart )
1365  {
1366  wxString partName = aCadstarPart->Name;
1367  partName.Replace( wxT( "\n" ), wxT( "\\n" ) );
1368  partName.Replace( wxT( "\r" ), wxT( "\\r" ) );
1369  partName.Replace( wxT( "\t" ), wxT( "\\t" ) );
1370  field->SetText( partName );
1371  }
1372 
1373  field->SetUnit( gateNumber );
1375  }
1376 
1377  if( aCadstarPart )
1378  {
1379  wxString footprintRefName = wxEmptyString;
1380  wxString footprintAlternateName = wxEmptyString;
1381 
1382  auto loadLibraryField =
1383  [&]( ATTRIBUTE_VALUE& aAttributeVal )
1384  {
1385  wxString attrName = getAttributeName( aAttributeVal.AttributeID );
1386 
1387  // Remove invalid field characters
1388  aAttributeVal.Value.Replace( wxT( "\n" ), wxT( "\\n" ) );
1389  aAttributeVal.Value.Replace( wxT( "\r" ), wxT( "\\r" ) );
1390  aAttributeVal.Value.Replace( wxT( "\t" ), wxT( "\\t" ) );
1391 
1392  //TODO: Handle "links": In cadstar a field can be a "link" if its name starts
1393  // with the characters "Link ". Need to figure out how to convert them to
1394  // equivalent in KiCad.
1395 
1396  if( attrName == wxT( "(PartDefinitionNameStem)" ) )
1397  {
1398  //Space not allowed in Reference field
1399  aAttributeVal.Value.Replace( wxT( " " ), "_" );
1400  aSymbol->GetReferenceField().SetText( aAttributeVal.Value );
1401  return;
1402  }
1403  else if( attrName == wxT( "(PartDescription)" ) )
1404  {
1405  aSymbol->SetDescription( aAttributeVal.Value );
1406  return;
1407  }
1408  else if( attrName == wxT( "(PartDefinitionReferenceName)" ) )
1409  {
1410  footprintRefName = aAttributeVal.Value;
1411  return;
1412  }
1413  else if( attrName == wxT( "(PartDefinitionAlternateName)" ) )
1414  {
1415  footprintAlternateName = aAttributeVal.Value;
1416  return;
1417  }
1418 
1419  LIB_FIELD* attrField = aSymbol->FindField( attrName );
1420 
1421  if( !attrField )
1422  {
1423  int fieldID = aSymbol->GetFieldCount();
1424  attrField = new LIB_FIELD( aSymbol, fieldID );
1425  attrField->SetName( attrName );
1426  aSymbol->AddField( attrField );
1427  }
1428 
1429  wxASSERT( attrField->GetName() == attrName );
1430  attrField->SetText( aAttributeVal.Value );
1431  attrField->SetUnit( gateNumber );
1432 
1433  ATTRIBUTE_ID& attrid = aAttributeVal.AttributeID;
1434  attrField->SetVisible( isAttributeVisible( attrid ) );
1435 
1436  if( aAttributeVal.HasLocation )
1437  {
1438  // #1 Check if the part itself defined a location for the field
1439  applyToLibraryFieldAttribute( aAttributeVal.AttributeLocation, symbol.Origin,
1440  attrField );
1441  }
1442  else if( symbol.TextLocations.find( aAttributeVal.AttributeID )
1443  != symbol.TextLocations.end() )
1444  {
1445  // #2 Look in the symbol definition: Text locations
1446  TEXT_LOCATION symTxtLoc = symbol.TextLocations.at( aAttributeVal.AttributeID );
1447  applyToLibraryFieldAttribute( symTxtLoc, symbol.Origin, attrField );
1448  }
1449  else if( symbol.AttributeValues.find( attrid ) != symbol.AttributeValues.end()
1450  && symbol.AttributeValues.at( attrid ).HasLocation )
1451  {
1452  // #3 Look in the symbol definition: Attribute values
1453  ATTRIBUTE_VALUE symAttrVal = symbol.AttributeValues.at( attrid );
1454  applyToLibraryFieldAttribute( symAttrVal.AttributeLocation, symbol.Origin,
1455  attrField );
1456  }
1457  else
1458  {
1459  attrField->SetVisible( false );
1460  applyTextSettings( attrField, wxT( "TC1" ), ALIGNMENT::NO_ALIGNMENT,
1462  }
1463  };
1464 
1465  // Load all attributes in the Part Definition
1466  for( std::pair<ATTRIBUTE_ID, ATTRIBUTE_VALUE> attr : aCadstarPart->Definition.AttributeValues )
1467  {
1468  ATTRIBUTE_VALUE attrVal = attr.second;
1469  loadLibraryField( attrVal );
1470  }
1471 
1472  // Load all attributes in the Part itself.
1473  for( std::pair<ATTRIBUTE_ID, ATTRIBUTE_VALUE> attr : aCadstarPart->AttributeValues )
1474  {
1475  ATTRIBUTE_VALUE attrVal = attr.second;
1476  loadLibraryField( attrVal );
1477  }
1478 
1479  wxString fpNameInLibrary = generateLibName( footprintRefName, footprintAlternateName );
1480  wxArrayString fpFilters;
1481  fpFilters.Add( fpNameInLibrary );
1482 
1483  aSymbol->SetFPFilters( fpFilters );
1484 
1485  // Assume that the PCB footprint library name will be the same as the schematic filename
1486  wxFileName schFilename( Filename );
1487  wxString libName = schFilename.GetName();
1488 
1489  aSymbol->GetFootprintField().SetText( libName + wxT( ":" ) + fpNameInLibrary );
1490  }
1491 
1492  if( aCadstarPart && aCadstarPart->Definition.HidePinNames )
1493  {
1494  aSymbol->SetShowPinNames( false );
1495  aSymbol->SetShowPinNumbers( false );
1496  }
1497 }
1498 
1499 
1501  const std::vector<VERTEX>& aCadstarVertices, wxPoint aSymbolOrigin, LIB_SYMBOL* aSymbol,
1502  int aGateNumber )
1503 {
1504  const VERTEX* prev = &aCadstarVertices.at( 0 );
1505  const VERTEX* cur;
1506 
1507  wxASSERT_MSG(
1508  prev->Type == VERTEX_TYPE::POINT, "First vertex should always be a point vertex" );
1509 
1510  for( size_t i = 1; i < aCadstarVertices.size(); i++ )
1511  {
1512  cur = &aCadstarVertices.at( i );
1513 
1514  LIB_ITEM* segment = nullptr;
1515  bool cw = false;
1516  wxPoint startPoint = getKiCadLibraryPoint( prev->End, aSymbolOrigin );
1517  wxPoint endPoint = getKiCadLibraryPoint( cur->End, aSymbolOrigin );
1518  wxPoint centerPoint;
1519 
1522  {
1523  centerPoint = ( startPoint + endPoint ) / 2;
1524  }
1525  else
1526  {
1527  centerPoint = getKiCadLibraryPoint( cur->Center, aSymbolOrigin );
1528  }
1529 
1530 
1531  switch( cur->Type )
1532  {
1533  case VERTEX_TYPE::POINT:
1534  segment = new LIB_POLYLINE( aSymbol );
1535  ( (LIB_POLYLINE*) segment )->AddPoint( startPoint );
1536  ( (LIB_POLYLINE*) segment )->AddPoint( endPoint );
1537  break;
1538 
1541  cw = true;
1543 
1546  segment = new LIB_ARC( aSymbol );
1547 
1548  ( (LIB_ARC*) segment )->SetPosition( centerPoint );
1549 
1550  if( cw )
1551  {
1552  ( (LIB_ARC*) segment )->SetStart( endPoint );
1553  ( (LIB_ARC*) segment )->SetEnd( startPoint );
1554  }
1555  else
1556  {
1557  ( (LIB_ARC*) segment )->SetStart( startPoint );
1558  ( (LIB_ARC*) segment )->SetEnd( endPoint );
1559  }
1560 
1561  ( (LIB_ARC*) segment )->CalcRadiusAngles();
1562  break;
1563  }
1564 
1565  segment->SetUnit( aGateNumber );
1566  aSymbol->AddDrawItem( segment );
1567 
1568  prev = cur;
1569  }
1570 }
1571 
1572 
1574  const ATTRIBUTE_LOCATION& aCadstarAttrLoc, wxPoint aSymbolOrigin, LIB_FIELD* aKiCadField )
1575 {
1576  aKiCadField->SetTextPos( getKiCadLibraryPoint( aCadstarAttrLoc.Position, aSymbolOrigin ) );
1577 
1578  applyTextSettings( aKiCadField,
1579  aCadstarAttrLoc.TextCodeID,
1580  aCadstarAttrLoc.Alignment,
1581  aCadstarAttrLoc.Justification,
1582  aCadstarAttrLoc.OrientAngle,
1583  aCadstarAttrLoc.Mirror );
1584 }
1585 
1586 
1588  const LIB_SYMBOL& aKiCadPart,
1589  double& aComponentOrientationDeciDeg )
1590 {
1591  LIB_ID libId( m_libraryFileName.GetName(), aKiCadPart.GetName() );
1592  int unit = getKiCadUnitNumberFromGate( aCadstarSymbol.GateID );
1593 
1594  SCH_SHEET_PATH sheetpath;
1595  SCH_SHEET* kiSheet = m_sheetMap.at( aCadstarSymbol.LayerID );
1596  m_rootSheet->LocatePathOfScreen( kiSheet->GetScreen(), &sheetpath );
1597 
1598  SCH_SYMBOL* symbol = new SCH_SYMBOL( aKiCadPart, libId, &sheetpath, unit );
1599 
1600  if( aCadstarSymbol.IsComponent )
1601  {
1602  symbol->SetRef( &sheetpath, aCadstarSymbol.ComponentRef.Designator );
1603  }
1604 
1605  symbol->SetPosition( getKiCadPoint( aCadstarSymbol.Origin ) );
1606 
1607  double compAngleDeciDeg = getAngleTenthDegree( aCadstarSymbol.OrientAngle );
1608  int compOrientation = 0;
1609 
1610  if( aCadstarSymbol.Mirror )
1611  {
1612  compAngleDeciDeg = -compAngleDeciDeg;
1613  compOrientation += SYMBOL_ORIENTATION_T::SYM_MIRROR_Y;
1614  }
1615 
1616  compOrientation += getComponentOrientation( compAngleDeciDeg, aComponentOrientationDeciDeg );
1617 
1618  if( NormalizeAngle180( compAngleDeciDeg ) != NormalizeAngle180( aComponentOrientationDeciDeg ) )
1619  {
1620  m_reporter->Report( wxString::Format( _( "Symbol '%s' is rotated by an angle of %.1f "
1621  "degrees in the original CADSTAR design but "
1622  "KiCad only supports rotation angles multiples "
1623  "of 90 degrees. The connecting wires will need "
1624  "manual fixing." ),
1625  aCadstarSymbol.ComponentRef.Designator,
1626  compAngleDeciDeg / 10.0 ),
1628  }
1629 
1630  symbol->SetOrientation( compOrientation );
1631 
1632  if( m_sheetMap.find( aCadstarSymbol.LayerID ) == m_sheetMap.end() )
1633  {
1634  m_reporter->Report( wxString::Format( _( "Symbol '%s' references sheet ID '%s' which does "
1635  "not exist in the design. The symbol was not "
1636  "loaded." ),
1637  aCadstarSymbol.ComponentRef.Designator,
1638  aCadstarSymbol.LayerID ),
1640 
1641  delete symbol;
1642  return nullptr;
1643  }
1644 
1645  wxString gate = ( aCadstarSymbol.GateID.IsEmpty() ) ? wxT( "A" ) : aCadstarSymbol.GateID;
1646  wxString partGateIndex = aCadstarSymbol.PartRef.RefID + gate;
1647 
1648  //Handle pin swaps
1649  if( m_pinNumsMap.find( partGateIndex ) != m_pinNumsMap.end() )
1650  {
1651  TERMINAL_TO_PINNUM_MAP termNumMap = m_pinNumsMap.at( partGateIndex );
1652 
1653  std::map<wxString, LIB_PIN*> pinNumToLibPinMap;
1654 
1655  for( auto& term : termNumMap )
1656  {
1657  wxString pinNum = term.second;
1658  pinNumToLibPinMap.insert( { pinNum,
1659  symbol->GetLibSymbolRef()->GetPin( term.second ) } );
1660  }
1661 
1662  auto replacePinNumber = [&]( wxString aOldPinNum, wxString aNewPinNum )
1663  {
1664  if( aOldPinNum == aNewPinNum )
1665  return;
1666 
1667  LIB_PIN* libpin = pinNumToLibPinMap.at( aOldPinNum );
1668  libpin->SetNumber( aNewPinNum );
1669  };
1670 
1671  //Older versions of Cadstar used pin numbers
1672  for( auto& pinPair : aCadstarSymbol.PinNumbers )
1673  {
1674  SYMBOL::PIN_NUM pin = pinPair.second;
1675 
1676  replacePinNumber( termNumMap.at( pin.TerminalID ),
1677  wxString::Format( "%ld", pin.PinNum ) );
1678  }
1679 
1680  //Newer versions of Cadstar use pin names
1681  for( auto& pinPair : aCadstarSymbol.PinNames )
1682  {
1683  SYMPINNAME_LABEL pin = pinPair.second;
1684  replacePinNumber( termNumMap.at( pin.TerminalID ), pin.NameOrLabel );
1685  }
1686 
1687  symbol->UpdatePins();
1688  }
1689 
1690  kiSheet->GetScreen()->Append( symbol );
1691 
1692  return symbol;
1693 }
1694 
1695 
1697  const ATTRIBUTE_LOCATION& aCadstarAttrLoc, const double& aComponentOrientationDeciDeg,
1698  bool aIsMirrored, SCH_FIELD* aKiCadField )
1699 {
1700  aKiCadField->SetPosition( getKiCadPoint( aCadstarAttrLoc.Position ) );
1701  aKiCadField->SetVisible( true );
1702 
1703  ALIGNMENT alignment = aCadstarAttrLoc.Alignment;
1704 
1705  double textAngle = getAngleTenthDegree( aCadstarAttrLoc.OrientAngle );
1706  long long cadstarAngle = getCadstarAngle( textAngle - aComponentOrientationDeciDeg );
1707 
1708  if( aIsMirrored )
1709  {
1710  // In KiCad, the angle of the symbol instance affects the position of the symbol
1711  // fields because there is a distinction on x-axis and y-axis mirroring
1712  double angleDeciDeg = NormalizeAnglePos( aComponentOrientationDeciDeg );
1713  int quadrant = KiROUND( angleDeciDeg / 900.0 );
1714  quadrant %= 4;
1715 
1716  switch( quadrant )
1717  {
1718  case 1:
1719  case 3: alignment = rotate180( alignment ); KI_FALLTHROUGH;
1720  case 0:
1721  case 2: alignment = mirrorX( alignment ); break;
1722  default: wxFAIL_MSG( "unknown quadrant" ); break;
1723  }
1724  }
1725 
1726  applyTextSettings( aKiCadField,
1727  aCadstarAttrLoc.TextCodeID,
1728  alignment,
1729  aCadstarAttrLoc.Justification,
1730  cadstarAngle,
1731  aCadstarAttrLoc.Mirror );
1732 }
1733 
1734 
1736  double aOrientAngleDeciDeg, double& aReturnedOrientationDeciDeg )
1737 {
1738  int compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_0;
1739 
1740  int oDeg = (int) NormalizeAngle180( aOrientAngleDeciDeg );
1741 
1742  if( oDeg >= -450 && oDeg <= 450 )
1743  {
1744  compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_0;
1745  aReturnedOrientationDeciDeg = 0.0;
1746  }
1747  else if( oDeg >= 450 && oDeg <= 1350 )
1748  {
1749  compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_90;
1750  aReturnedOrientationDeciDeg = 900.0;
1751  }
1752  else if( oDeg >= 1350 || oDeg <= -1350 )
1753  {
1754  compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_180;
1755  aReturnedOrientationDeciDeg = 1800.0;
1756  }
1757  else
1758  {
1759  compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_270;
1760  aReturnedOrientationDeciDeg = 2700.0;
1761  }
1762 
1763  return compOrientation;
1764 }
1765 
1766 
1768  const NET_SCH& aNet, const NETELEMENT_ID& aNetElementID )
1769 {
1770  // clang-format off
1771  auto logUnknownNetElementError =
1772  [&]()
1773  {
1774  m_reporter->Report( wxString::Format( _( "Net %s references unknown net element %s. "
1775  "The net was not properly loaded and may "
1776  "require manual fixing." ),
1777  getNetName( aNet ),
1778  aNetElementID ),
1780 
1781  return POINT();
1782  };
1783  // clang-format on
1784 
1785  if( aNetElementID.Contains( "J" ) ) // Junction
1786  {
1787  if( aNet.Junctions.find( aNetElementID ) == aNet.Junctions.end() )
1788  return logUnknownNetElementError();
1789 
1790  return aNet.Junctions.at( aNetElementID ).Location;
1791  }
1792  else if( aNetElementID.Contains( "P" ) ) // Terminal/Pin of a symbol
1793  {
1794  if( aNet.Terminals.find( aNetElementID ) == aNet.Terminals.end() )
1795  return logUnknownNetElementError();
1796 
1797  SYMBOL_ID symid = aNet.Terminals.at( aNetElementID ).SymbolID;
1798  TERMINAL_ID termid = aNet.Terminals.at( aNetElementID ).TerminalID;
1799 
1800  if( Schematic.Symbols.find( symid ) == Schematic.Symbols.end() )
1801  return logUnknownNetElementError();
1802 
1803  SYMBOL sym = Schematic.Symbols.at( symid );
1804  SYMDEF_ID symdefid = sym.SymdefID;
1805  wxPoint symbolOrigin = sym.Origin;
1806 
1807  if( Library.SymbolDefinitions.find( symdefid ) == Library.SymbolDefinitions.end() )
1808  return logUnknownNetElementError();
1809 
1810  wxPoint libpinPosition =
1811  Library.SymbolDefinitions.at( symdefid ).Terminals.at( termid ).Position;
1812  wxPoint libOrigin = Library.SymbolDefinitions.at( symdefid ).Origin;
1813 
1814  wxPoint pinOffset = libpinPosition - libOrigin;
1815  pinOffset.x = ( pinOffset.x * sym.ScaleRatioNumerator ) / sym.ScaleRatioDenominator;
1816  pinOffset.y = ( pinOffset.y * sym.ScaleRatioNumerator ) / sym.ScaleRatioDenominator;
1817 
1818  wxPoint pinPosition = symbolOrigin + pinOffset;
1819 
1820  double compAngleDeciDeg = getAngleTenthDegree( sym.OrientAngle );
1821 
1822  if( sym.Mirror )
1823  pinPosition.x = ( 2 * symbolOrigin.x ) - pinPosition.x;
1824 
1825  double adjustedOrientationDecideg;
1826  getComponentOrientation( compAngleDeciDeg, adjustedOrientationDecideg );
1827 
1828  RotatePoint( &pinPosition, symbolOrigin, -adjustedOrientationDecideg );
1829 
1830  POINT retval;
1831  retval.x = pinPosition.x;
1832  retval.y = pinPosition.y;
1833 
1834  return retval;
1835  }
1836  else if( aNetElementID.Contains( "BT" ) ) // Bus Terminal
1837  {
1838  if( aNet.BusTerminals.find( aNetElementID ) == aNet.BusTerminals.end() )
1839  return logUnknownNetElementError();
1840 
1841  return aNet.BusTerminals.at( aNetElementID ).SecondPoint;
1842  }
1843  else if( aNetElementID.Contains( "BLKT" ) ) // Block Terminal (sheet hierarchy connection)
1844  {
1845  if( aNet.BlockTerminals.find( aNetElementID ) == aNet.BlockTerminals.end() )
1846  return logUnknownNetElementError();
1847 
1848  BLOCK_ID blockid = aNet.BlockTerminals.at( aNetElementID ).BlockID;
1849  TERMINAL_ID termid = aNet.BlockTerminals.at( aNetElementID ).TerminalID;
1850 
1851  if( Schematic.Blocks.find( blockid ) == Schematic.Blocks.end() )
1852  return logUnknownNetElementError();
1853 
1854  return Schematic.Blocks.at( blockid ).Terminals.at( termid ).Position;
1855  }
1856  else if( aNetElementID.Contains( "D" ) ) // Dangler
1857  {
1858  if( aNet.Danglers.find( aNetElementID ) == aNet.Danglers.end() )
1859  return logUnknownNetElementError();
1860 
1861  return aNet.Danglers.at( aNetElementID ).Position;
1862  }
1863  else
1864  {
1865  return logUnknownNetElementError();
1866  }
1867 
1868  return POINT();
1869 }
1870 
1871 
1873 {
1874  wxString netname = aNet.Name;
1875 
1876  if( netname.IsEmpty() )
1877  netname = wxString::Format( "$%ld", aNet.SignalNum );
1878 
1879  return netname;
1880 }
1881 
1882 
1884  const wxPoint& aEndPoint, const LINECODE_ID& aCadstarLineCodeID,
1885  const LAYER_ID& aCadstarSheetID, const SCH_LAYER_ID& aKiCadSchLayerID,
1886  const wxPoint& aMoveVector, const double& aRotationAngleDeciDeg,
1887  const double& aScalingFactor, const wxPoint& aTransformCentre, const bool& aMirrorInvert )
1888 {
1889  SCH_LINE* segment = new SCH_LINE();
1890 
1891  segment->SetLayer( aKiCadSchLayerID );
1892  segment->SetLineWidth( KiROUND( getLineThickness( aCadstarLineCodeID ) * aScalingFactor ) );
1893  segment->SetLineStyle( getLineStyle( aCadstarLineCodeID ) );
1894 
1895  //Apply transforms
1896  wxPoint startPoint = applyTransform( aStartPoint, aMoveVector, aRotationAngleDeciDeg,
1897  aScalingFactor, aTransformCentre, aMirrorInvert );
1898  wxPoint endPoint = applyTransform( aEndPoint, aMoveVector, aRotationAngleDeciDeg,
1899  aScalingFactor, aTransformCentre, aMirrorInvert );
1900 
1901  segment->SetStartPoint( startPoint );
1902  segment->SetEndPoint( endPoint );
1903 
1904  loadItemOntoKiCadSheet( aCadstarSheetID, segment );
1905 }
1906 
1907 
1908 void CADSTAR_SCH_ARCHIVE_LOADER::loadShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
1909  LINECODE_ID aCadstarLineCodeID, LAYER_ID aCadstarSheetID, SCH_LAYER_ID aKiCadSchLayerID,
1910  const wxPoint& aMoveVector, const double& aRotationAngleDeciDeg,
1911  const double& aScalingFactor, const wxPoint& aTransformCentre, const bool& aMirrorInvert )
1912 {
1913  const VERTEX* prev = &aCadstarVertices.at( 0 );
1914  const VERTEX* cur;
1915 
1916  wxASSERT_MSG(
1917  prev->Type == VERTEX_TYPE::POINT, "First vertex should always be a point vertex" );
1918 
1919  for( size_t ii = 1; ii < aCadstarVertices.size(); ii++ )
1920  {
1921  cur = &aCadstarVertices.at( ii );
1922 
1923  wxPoint startPoint = getKiCadPoint( prev->End );
1924  wxPoint endPoint = getKiCadPoint( cur->End );
1925  wxPoint centerPoint = getKiCadPoint( cur->Center );
1926  bool cw = false;
1927 
1930  {
1931  centerPoint = ( startPoint + endPoint ) / 2;
1932  }
1933 
1934  switch( cur->Type )
1935  {
1938  cw = true;
1942  {
1943  double arcStartAngle = getPolarAngle( startPoint - centerPoint );
1944  double arcEndAngle = getPolarAngle( endPoint - centerPoint );
1945  double arcAngleDeciDeg = arcEndAngle - arcStartAngle;
1946 
1947  if( cw )
1948  arcAngleDeciDeg = NormalizeAnglePos( arcAngleDeciDeg );
1949  else
1950  arcAngleDeciDeg = NormalizeAngleNeg( arcAngleDeciDeg );
1951 
1952  SHAPE_ARC tempArc( VECTOR2I(centerPoint), VECTOR2I(startPoint), arcAngleDeciDeg / 10.0 );
1953  SHAPE_LINE_CHAIN arcSegments = tempArc.ConvertToPolyline( Millimeter2iu( 0.1 ) );
1954 
1955  // Load the arc as a series of piece-wise segments
1956 
1957  for( int jj = 0; jj < arcSegments.SegmentCount(); jj++ )
1958  {
1959  wxPoint segStart = (wxPoint) arcSegments.Segment( jj ).A;
1960  wxPoint segEnd = (wxPoint) arcSegments.Segment( jj ).B;
1961 
1962  loadGraphicStaightSegment( segStart, segEnd, aCadstarLineCodeID,
1963  aCadstarSheetID, aKiCadSchLayerID, aMoveVector, aRotationAngleDeciDeg,
1964  aScalingFactor, aTransformCentre, aMirrorInvert );
1965  }
1966  }
1967  break;
1968 
1969  case VERTEX_TYPE::POINT:
1970  loadGraphicStaightSegment( startPoint, endPoint, aCadstarLineCodeID, aCadstarSheetID,
1971  aKiCadSchLayerID, aMoveVector, aRotationAngleDeciDeg, aScalingFactor,
1972  aTransformCentre, aMirrorInvert );
1973  break;
1974 
1975  default:
1976  wxFAIL_MSG( "Unknown CADSTAR Vertex type" );
1977  }
1978 
1979 
1980  prev = cur;
1981  }
1982 }
1983 
1984 
1986  const LAYER_ID& aCadstarSheetIDOverride, SCH_LAYER_ID aKiCadSchLayerID,
1987  const wxPoint& aMoveVector, const double& aRotationAngleDeciDeg,
1988  const double& aScalingFactor, const wxPoint& aTransformCentre, const bool& aMirrorInvert )
1989 {
1990  loadShapeVertices( aCadstarFigure.Shape.Vertices, aCadstarFigure.LineCodeID,
1991  aCadstarSheetIDOverride, aKiCadSchLayerID, aMoveVector, aRotationAngleDeciDeg,
1992  aScalingFactor, aTransformCentre, aMirrorInvert );
1993 
1994  for( CUTOUT cutout : aCadstarFigure.Shape.Cutouts )
1995  {
1996  loadShapeVertices( cutout.Vertices, aCadstarFigure.LineCodeID, aCadstarSheetIDOverride,
1997  aKiCadSchLayerID, aMoveVector, aRotationAngleDeciDeg, aScalingFactor,
1998  aTransformCentre, aMirrorInvert );
1999  }
2000 }
2001 
2002 
2004  LAYER_ID aCadstarSheetID, wxPoint aPosition, wxSize aSheetSize,
2005  const SCH_SHEET_PATH& aParentSheet )
2006 {
2007  wxCHECK_MSG( m_sheetMap.find( aCadstarSheetID ) == m_sheetMap.end(), ,
2008  "Sheet already loaded!" );
2009 
2010  SCH_SHEET* sheet = new SCH_SHEET( aParentSheet.Last(), aPosition );
2011  SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
2012  SCH_SHEET_PATH instance( aParentSheet );
2013 
2014  sheet->SetSize( aSheetSize );
2015  sheet->SetScreen( screen );
2016 
2017  wxString name = Sheets.SheetNames.at( aCadstarSheetID );
2018 
2019  SCH_FIELD& sheetNameField = sheet->GetFields()[SHEETNAME];
2020  SCH_FIELD& filenameField = sheet->GetFields()[SHEETFILENAME];
2021 
2022  sheetNameField.SetText( name );
2023 
2024  int sheetNum = getSheetNumber( aCadstarSheetID );
2025  wxString loadedFilename = wxFileName( Filename ).GetName();
2026  std::string filename = wxString::Format( "%s_%02d", loadedFilename, sheetNum ).ToStdString();
2027 
2028  ReplaceIllegalFileNameChars( &filename );
2029  filename += wxT( "." ) + KiCadSchematicFileExtension;
2030 
2031  filenameField.SetText( filename );
2032 
2033  wxFileName fn( m_schematic->Prj().GetProjectPath() + filename );
2034  sheet->GetScreen()->SetFileName( fn.GetFullPath() );
2035  aParentSheet.Last()->GetScreen()->Append( sheet );
2036  instance.push_back( sheet );
2037  sheet->AddInstance( instance.Path() );
2038 
2039  wxString pageNumStr = wxString::Format( "%d", getSheetNumber( aCadstarSheetID ) );
2040  sheet->SetPageNumber( instance, pageNumStr );
2041 
2042  sheet->AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
2043 
2044  m_sheetMap.insert( { aCadstarSheetID, sheet } );
2045 
2046  loadChildSheets( aCadstarSheetID, instance );
2047 }
2048 
2049 
2051  LAYER_ID aCadstarSheetID, const SCH_SHEET_PATH& aSheet )
2052 {
2053  wxCHECK_MSG( m_sheetMap.find( aCadstarSheetID ) != m_sheetMap.end(), ,
2054  "FIXME! Parent sheet should be loaded before attempting to load subsheets" );
2055 
2056  for( std::pair<BLOCK_ID, BLOCK> blockPair : Schematic.Blocks )
2057  {
2058  BLOCK& block = blockPair.second;
2059 
2060  if( block.LayerID == aCadstarSheetID && block.Type == BLOCK::TYPE::CHILD )
2061  {
2062  if( block.AssocLayerID == wxT( "NO_LINK" ) )
2063  {
2064  if( block.Figures.size() > 0 )
2065  {
2066  m_reporter->Report( wxString::Format( _( "The block ID %s (Block name: '%s') "
2067  "is drawn on sheet '%s' but is not "
2068  "linked to another sheet in the "
2069  "design. KiCad requires all sheet "
2070  "symbols to be associated to a sheet, "
2071  "so the block was not loaded." ),
2072  block.ID, block.Name,
2073  Sheets.SheetNames.at( aCadstarSheetID ) ),
2075  }
2076 
2077  continue;
2078  }
2079 
2080  // In KiCad you can only draw rectangular shapes whereas in Cadstar arbitrary shapes
2081  // are allowed. We will calculate the extents of the Cadstar shape and draw a rectangle
2082 
2083  std::pair<wxPoint, wxSize> blockExtents;
2084 
2085  if( block.Figures.size() > 0 )
2086  {
2087  blockExtents = getFigureExtentsKiCad( block.Figures.begin()->second );
2088  }
2089  else
2090  {
2091  THROW_IO_ERROR( wxString::Format( _( "The CADSTAR schematic might be corrupt: "
2092  "Block %s references a child sheet but has no "
2093  "Figure defined." ),
2094  block.ID ) );
2095  }
2096 
2097  loadSheetAndChildSheets( block.AssocLayerID, blockExtents.first, blockExtents.second,
2098  aSheet );
2099 
2100  if( block.HasBlockLabel )
2101  {
2102  // Add the block label as a separate field
2103  SCH_SHEET* loadedSheet = m_sheetMap.at( block.AssocLayerID );
2104  SCH_FIELDS fields = loadedSheet->GetFields();
2105 
2106  for( SCH_FIELD& field : fields )
2107  {
2108  field.SetVisible( false );
2109  }
2110 
2111  SCH_FIELD blockNameField( getKiCadPoint( block.BlockLabel.Position ), 2,
2112  loadedSheet, wxString( "Block name" ) );
2113  blockNameField.SetText( block.Name );
2114  blockNameField.SetVisible( true );
2115 
2116  applyTextSettings( &blockNameField,
2117  block.BlockLabel.TextCodeID,
2118  block.BlockLabel.Alignment,
2119  block.BlockLabel.Justification,
2120  block.BlockLabel.OrientAngle,
2121  block.BlockLabel.Mirror );
2122 
2123  fields.push_back( blockNameField );
2124  loadedSheet->SetFields( fields );
2125  }
2126  }
2127  }
2128 }
2129 
2130 
2131 std::vector<CADSTAR_SCH_ARCHIVE_LOADER::LAYER_ID> CADSTAR_SCH_ARCHIVE_LOADER::findOrphanSheets()
2132 {
2133  std::vector<LAYER_ID> childSheets, orphanSheets;
2134 
2135  //Find all sheets that are child of another
2136  for( std::pair<BLOCK_ID, BLOCK> blockPair : Schematic.Blocks )
2137  {
2138  BLOCK& block = blockPair.second;
2139  LAYER_ID& assocSheetID = block.AssocLayerID;
2140 
2141  if( block.Type == BLOCK::TYPE::CHILD )
2142  childSheets.push_back( assocSheetID );
2143  }
2144 
2145  //Add sheets that do not have a parent
2146  for( LAYER_ID sheetID : Sheets.SheetOrder )
2147  {
2148  if( std::find( childSheets.begin(), childSheets.end(), sheetID ) == childSheets.end() )
2149  orphanSheets.push_back( sheetID );
2150  }
2151 
2152  return orphanSheets;
2153 }
2154 
2155 
2157 {
2158  int i = 1;
2159 
2160  for( LAYER_ID sheetID : Sheets.SheetOrder )
2161  {
2162  if( sheetID == aCadstarSheetID )
2163  return i;
2164 
2165  ++i;
2166  }
2167 
2168  return -1;
2169 }
2170 
2171 
2173 {
2174  wxCHECK_MSG( aItem, /*void*/, "aItem is null" );
2175 
2176  if( aCadstarSheetID == "ALL_SHEETS" )
2177  {
2178  SCH_ITEM* duplicateItem;
2179 
2180  for( std::pair<LAYER_ID, SHEET_NAME> sheetPair : Sheets.SheetNames )
2181  {
2182  LAYER_ID sheetID = sheetPair.first;
2183  duplicateItem = aItem->Duplicate();
2184  m_sheetMap.at( sheetID )->GetScreen()->Append( aItem->Duplicate() );
2185  }
2186 
2187  //Get rid of the extra copy:
2188  delete aItem;
2189  aItem = duplicateItem;
2190  }
2191  else if( aCadstarSheetID == "NO_SHEET" )
2192  {
2193  wxASSERT_MSG(
2194  false, "Trying to add an item to NO_SHEET? This might be a documentation symbol." );
2195  }
2196  else
2197  {
2198  if( m_sheetMap.find( aCadstarSheetID ) != m_sheetMap.end() )
2199  {
2200  m_sheetMap.at( aCadstarSheetID )->GetScreen()->Append( aItem );
2201  }
2202  else
2203  {
2204  delete aItem;
2205  wxASSERT_MSG( false, "Unknown Sheet ID." );
2206  }
2207  }
2208 }
2209 
2210 
2212  const wxString& aSymdefName, const wxString& aSymDefAlternate )
2213 {
2214  // Do a case-insensitive comparison
2215  for( std::pair<SYMDEF_ID, SYMDEF_SCM> symPair : Library.SymbolDefinitions )
2216  {
2217  SYMDEF_ID id = symPair.first;
2218  SYMDEF_SCM symdef = symPair.second;
2219 
2220  if( symdef.ReferenceName.Lower() == aSymdefName.Lower()
2221  && symdef.Alternate.Lower() == aSymDefAlternate.Lower() )
2222  {
2223  return id;
2224  }
2225  }
2226 
2227  return SYMDEF_ID();
2228 }
2229 
2231 {
2232  // Use CADSTAR visibility settings to determine if an attribute is visible
2233  if( AttrColors.AttributeColors.find( aCadstarAttributeID ) != AttrColors.AttributeColors.end() )
2234  {
2235  return AttrColors.AttributeColors.at( aCadstarAttributeID ).IsVisible;
2236  }
2237 
2238  return false; // If there is no visibility setting, assume not displayed
2239 }
2240 
2241 
2243 {
2244  wxCHECK( Assignments.Codedefs.LineCodes.find( aCadstarLineCodeID )
2245  != Assignments.Codedefs.LineCodes.end(),
2247 
2248  return getKiCadLength( Assignments.Codedefs.LineCodes.at( aCadstarLineCodeID ).Width );
2249 }
2250 
2251 
2253 {
2254  wxCHECK( Assignments.Codedefs.LineCodes.find( aCadstarLineCodeID )
2255  != Assignments.Codedefs.LineCodes.end(),
2257 
2258  // clang-format off
2259  switch( Assignments.Codedefs.LineCodes.at( aCadstarLineCodeID ).Style )
2260  {
2263  case LINESTYLE::DASHDOTDOT: return PLOT_DASH_TYPE::DASHDOT; //TODO: update in future
2264  case LINESTYLE::DOT: return PLOT_DASH_TYPE::DOT;
2266  default: return PLOT_DASH_TYPE::DEFAULT;
2267  }
2268  // clang-format on
2269 
2270  return PLOT_DASH_TYPE();
2271 }
2272 
2273 
2275  const TEXTCODE_ID& aCadstarTextCodeID )
2276 {
2277  wxCHECK( Assignments.Codedefs.TextCodes.find( aCadstarTextCodeID )
2278  != Assignments.Codedefs.TextCodes.end(),
2279  TEXTCODE() );
2280 
2281  return Assignments.Codedefs.TextCodes.at( aCadstarTextCodeID );
2282 }
2283 
2284 
2285 wxString CADSTAR_SCH_ARCHIVE_LOADER::getAttributeName( const ATTRIBUTE_ID& aCadstarAttributeID )
2286 {
2287  wxCHECK( Assignments.Codedefs.AttributeNames.find( aCadstarAttributeID )
2289  wxEmptyString );
2290 
2291  return Assignments.Codedefs.AttributeNames.at( aCadstarAttributeID ).Name;
2292 }
2293 
2294 
2296  const PART_ID& aCadstarPartID )
2297 {
2298  wxCHECK( Parts.PartDefinitions.find( aCadstarPartID ) != Parts.PartDefinitions.end(), PART() );
2299 
2300  return Parts.PartDefinitions.at( aCadstarPartID );
2301 }
2302 
2303 
2305  const ROUTECODE_ID& aCadstarRouteCodeID )
2306 {
2307  wxCHECK( Assignments.Codedefs.RouteCodes.find( aCadstarRouteCodeID )
2308  != Assignments.Codedefs.RouteCodes.end(),
2309  ROUTECODE() );
2310 
2311  return Assignments.Codedefs.RouteCodes.at( aCadstarRouteCodeID );
2312 }
2313 
2314 
2315 CADSTAR_SCH_ARCHIVE_LOADER::PART::DEFINITION::PIN CADSTAR_SCH_ARCHIVE_LOADER::getPartDefinitionPin(
2316  const PART& aCadstarPart, const GATE_ID& aGateID, const TERMINAL_ID& aTerminalID )
2317 {
2318  for( std::pair<PART_DEFINITION_PIN_ID, PART::DEFINITION::PIN> pinPair :
2319  aCadstarPart.Definition.Pins )
2320  {
2321  PART::DEFINITION::PIN partPin = pinPair.second;
2322 
2323  if( partPin.TerminalGate == aGateID && partPin.TerminalPin == aTerminalID )
2324  return partPin;
2325  }
2326 
2327  return PART::DEFINITION::PIN();
2328 }
2329 
2330 
2332 {
2333  switch( aPinType )
2334  {
2335  case PART::PIN_TYPE::UNCOMMITTED: return ELECTRICAL_PINTYPE::PT_PASSIVE;
2336  case PART::PIN_TYPE::INPUT: return ELECTRICAL_PINTYPE::PT_INPUT;
2337  case PART::PIN_TYPE::OUTPUT_OR: return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
2338  case PART::PIN_TYPE::OUTPUT_NOT_OR: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2339  case PART::PIN_TYPE::OUTPUT_NOT_NORM_OR: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2340  case PART::PIN_TYPE::POWER: return ELECTRICAL_PINTYPE::PT_POWER_IN;
2341  case PART::PIN_TYPE::GROUND: return ELECTRICAL_PINTYPE::PT_POWER_IN;
2342  case PART::PIN_TYPE::TRISTATE_BIDIR: return ELECTRICAL_PINTYPE::PT_BIDI;
2343  case PART::PIN_TYPE::TRISTATE_INPUT: return ELECTRICAL_PINTYPE::PT_INPUT;
2344  case PART::PIN_TYPE::TRISTATE_DRIVER: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2345  }
2346 
2348 }
2349 
2351 {
2352  if( aCadstarGateID.IsEmpty() )
2353  return 1;
2354 
2355  return (int) aCadstarGateID.Upper().GetChar( 0 ) - (int) wxUniChar( 'A' ) + 1;
2356 }
2357 
2358 
2360  const long long& aCadstarOrientation, bool aMirror )
2361 {
2362  double orientationDeciDegree = getAngleTenthDegree( aCadstarOrientation );
2363  LABEL_SPIN_STYLE spinStyle = getSpinStyleDeciDeg( orientationDeciDegree );
2364 
2365  if( aMirror )
2366  {
2367  spinStyle = spinStyle.RotateCCW();
2368  spinStyle = spinStyle.RotateCCW();
2369  }
2370 
2371  return spinStyle;
2372 }
2373 
2374 
2376  const double& aOrientationDeciDeg )
2377 {
2379 
2380  int oDeg = (int) NormalizeAngle180( aOrientationDeciDeg );
2381 
2382  if( oDeg >= -450 && oDeg <= 450 )
2383  spinStyle = LABEL_SPIN_STYLE::RIGHT; // 0deg
2384  else if( oDeg >= 450 && oDeg <= 1350 )
2385  spinStyle = LABEL_SPIN_STYLE::UP; // 90deg
2386  else if( oDeg >= 1350 || oDeg <= -1350 )
2387  spinStyle = LABEL_SPIN_STYLE::LEFT; // 180deg
2388  else
2389  spinStyle = LABEL_SPIN_STYLE::BOTTOM; // 270deg
2390 
2391  return spinStyle;
2392 }
2393 
2394 
2397 {
2398  switch( aCadstarAlignment )
2399  {
2400  // Change left to right:
2405  //Change right to left:
2409  // Center alignment does not mirror:
2412  case ALIGNMENT::TOPCENTER: return aCadstarAlignment;
2413  // Shouldn't be here
2414  default: wxFAIL_MSG( "Unknown Cadstar Alignment" ); return aCadstarAlignment;
2415  }
2416 }
2417 
2418 
2421 {
2422  switch( aCadstarAlignment )
2423  {
2434  // Shouldn't be here
2435  default: wxFAIL_MSG( "Unknown Cadstar Alignment" ); return aCadstarAlignment;
2436  }
2437 }
2438 
2439 
2441  const TEXTCODE_ID& aCadstarTextCodeID,
2442  const ALIGNMENT& aCadstarAlignment,
2443  const JUSTIFICATION& aCadstarJustification,
2444  const long long aCadstarOrientAngle,
2445  bool aMirrored )
2446 {
2447  // Justification ignored for now as not supported in eeschema, but leaving this code in
2448  // place for future upgrades.
2449  // TODO update this when eeschema supports justification independent of anchor position.
2450 
2451  TEXTCODE textCode = getTextCode( aCadstarTextCodeID );
2452  int textHeight = KiROUND( (double) getKiCadLength( textCode.Height ) * TXT_HEIGHT_RATIO );
2453  int textWidth = getKiCadLength( textCode.Width );
2454 
2455  // In Cadstar the overbar token is "'" whereas in KiCad it is "~"
2456  wxString escapedText = aKiCadTextItem->GetText();
2457  escapedText.Replace( wxT( "~" ), wxT( "~~" ) );
2458  escapedText.Replace( wxT( "'" ), wxT( "~" ) );
2459  aKiCadTextItem->SetText( escapedText );
2460 
2461  // The width is zero for all non-cadstar fonts. Using a width equal to 2/3 the height seems
2462  // to work well for most fonts.
2463  if( textWidth == 0 )
2464  textWidth = getKiCadLength( 2 * textCode.Height / 3 );
2465 
2466  aKiCadTextItem->SetTextWidth( textWidth );
2467  aKiCadTextItem->SetTextHeight( textHeight );
2468  aKiCadTextItem->SetTextThickness( getKiCadLength( textCode.LineWidth ) );
2469  aKiCadTextItem->SetTextAngle( getAngleTenthDegree( aCadstarOrientAngle ) );
2470  aKiCadTextItem->SetBold( textCode.Font.Modifier1 == FONT_BOLD );
2471  aKiCadTextItem->SetItalic( textCode.Font.Italic );
2472 
2473  ALIGNMENT textAlignment = aCadstarAlignment;
2474 
2475  // KiCad mirrors the justification and alignment when the symbol is mirrored but CADSTAR
2476  // specifies it post-mirroring. In contrast, if the text item itself is mirrored (not
2477  // supported in KiCad), CADSTAR specifies the alignment and justification pre-mirroring
2478  if( aMirrored )
2479  textAlignment = mirrorX( aCadstarAlignment );
2480 
2481  auto setAlignment = [&]( EDA_TEXT* aText, ALIGNMENT aAlignment )
2482  {
2483  switch( aAlignment )
2484  {
2485  case ALIGNMENT::NO_ALIGNMENT: // Bottom left of the first line
2486  //No exact KiCad equivalent, so lets move the position of the text
2487  FixTextPositionNoAlignment( aText );
2489  case ALIGNMENT::BOTTOMLEFT:
2492  break;
2493 
2497  break;
2498 
2502  break;
2503 
2504  case ALIGNMENT::CENTERLEFT:
2507  break;
2508 
2512  break;
2513 
2517  break;
2518 
2519  case ALIGNMENT::TOPLEFT:
2522  break;
2523 
2524  case ALIGNMENT::TOPCENTER:
2527  break;
2528 
2529  case ALIGNMENT::TOPRIGHT:
2532  break;
2533  }
2534  };
2535 
2536  LABEL_SPIN_STYLE spin = getSpinStyle( aCadstarOrientAngle, aMirrored );
2537  EDA_ITEM* textEdaItem = dynamic_cast<EDA_ITEM*>( aKiCadTextItem );
2538  wxCHECK( textEdaItem, /* void */ ); // ensure this is a EDA_ITEM
2539 
2540  switch( textEdaItem->Type() )
2541  {
2542  // Some KiCad schematic text items only permit a limited amount of angles
2543  // and text justifications
2544  case LIB_TEXT_T:
2545  case SCH_FIELD_T:
2546  case LIB_FIELD_T:
2547  {
2548  // Spin style not used. All text justifications are permitted. However, only orientations
2549  // of 0 deg or 90 deg are supported
2550  double angleDeciDeg = NormalizeAnglePos( aKiCadTextItem->GetTextAngle() );
2551  int quadrant = KiROUND( angleDeciDeg / 900.0 );
2552  quadrant %= 4;
2553 
2554  switch( quadrant )
2555  {
2556  case 0:
2557  angleDeciDeg = 0;
2558  break;
2559  case 1:
2560  angleDeciDeg = 900;
2561  break;
2562  case 2:
2563  angleDeciDeg = 0;
2564  textAlignment = rotate180( textAlignment );
2565  break;
2566  case 3:
2567  angleDeciDeg = 900;
2568  textAlignment = rotate180( textAlignment );
2569  break;
2570  default: wxFAIL_MSG( "Unknown Quadrant" );
2571  }
2572 
2573  aKiCadTextItem->SetTextAngle( angleDeciDeg );
2574  setAlignment( aKiCadTextItem, textAlignment );
2575  }
2576  return;
2577 
2578  case SCH_TEXT_T:
2579  {
2580  // Note spin style in a SCH_TEXT results in a vertical alignment GR_TEXT_VJUSTIFY_BOTTOM
2581  // so need to adjust the location of the text element based on Cadstar's original text
2582  // alignment (anchor position).
2583  setAlignment( aKiCadTextItem, textAlignment );
2584  EDA_RECT bb = textEdaItem->GetBoundingBox();
2585  int off = static_cast<SCH_TEXT*>( aKiCadTextItem )->GetTextOffset();
2586  wxPoint pos;
2587 
2588  // Change the anchor point of the text item to make it match the same bounding box
2589  // And correct the error introduced by the text offsetting in KiCad
2590  switch( spin )
2591  {
2592  case LABEL_SPIN_STYLE::BOTTOM: pos = { bb.GetRight() - off, bb.GetTop() }; break;
2593  case LABEL_SPIN_STYLE::UP: pos = { bb.GetRight() - off, bb.GetBottom() }; break;
2594  case LABEL_SPIN_STYLE::LEFT: pos = { bb.GetRight() , bb.GetBottom() + off }; break;
2595  case LABEL_SPIN_STYLE::RIGHT: pos = { bb.GetLeft() , bb.GetBottom() + off }; break;
2596  }
2597 
2598  aKiCadTextItem->SetTextPos( pos );
2599  }
2601 
2602  // We don't want to change position of net labels as that would break connectivity
2603  case SCH_LABEL_T:
2604  case SCH_GLOBAL_LABEL_T:
2605  case SCH_HIER_LABEL_T:
2606  case SCH_SHEET_PIN_T:
2607  static_cast<SCH_TEXT*>( aKiCadTextItem )->SetLabelSpinStyle( spin );
2608  return;
2609 
2610  default:
2611  wxFAIL_MSG( "Unexpected item type" );
2612  return;
2613  }
2614 }
2615 
2617 {
2618  SCH_TEXT* kiTxt = new SCH_TEXT();
2619 
2620  kiTxt->SetParent( m_schematic ); // set to the schematic for now to avoid asserts
2621  kiTxt->SetPosition( getKiCadPoint( aCadstarTextElement.Position ) );
2622  kiTxt->SetText( aCadstarTextElement.Text );
2623 
2624  applyTextSettings( kiTxt,
2625  aCadstarTextElement.TextCodeID,
2626  aCadstarTextElement.Alignment,
2627  aCadstarTextElement.Justification,
2628  aCadstarTextElement.OrientAngle,
2629  aCadstarTextElement.Mirror );
2630 
2631  return kiTxt;
2632 }
2633 
2634 
2636  long long aScalingFactorNumerator,
2637  long long aScalingFactorDenominator )
2638 {
2639  LIB_SYMBOL* retval = new LIB_SYMBOL( *aSymbol );
2640 
2641  if( aScalingFactorNumerator == aScalingFactorDenominator )
2642  return retval; // 1:1 scale, nothing to do
2643 
2644  auto scaleLen =
2645  [&]( int aLength ) -> int
2646  {
2647  return( aLength * aScalingFactorNumerator ) / aScalingFactorDenominator;
2648  };
2649 
2650  auto scalePt =
2651  [&]( wxPoint aCoord ) -> wxPoint
2652  {
2653  return wxPoint( scaleLen( aCoord.x ), scaleLen( aCoord.y ) );
2654  };
2655 
2656  auto scaleSize =
2657  [&]( wxSize aSize ) -> wxSize
2658  {
2659  return wxSize( scaleLen( aSize.x ), scaleLen( aSize.y ) );
2660  };
2661 
2662  LIB_ITEMS_CONTAINER& items = retval->GetDrawItems();
2663 
2664  for( auto& item : items )
2665  {
2666  switch( item.Type() )
2667  {
2668  case KICAD_T::LIB_ARC_T:
2669  {
2670  LIB_ARC& arc = static_cast<LIB_ARC&>( item );
2671  arc.SetPosition( scalePt( arc.GetPosition() ) );
2672  arc.SetStart( scalePt( arc.GetStart() ) );
2673  arc.SetEnd( scalePt( arc.GetEnd() ) );
2674  arc.CalcRadiusAngles(); // Maybe not needed?
2675  }
2676  break;
2677 
2679  {
2680  LIB_POLYLINE& poly = static_cast<LIB_POLYLINE&>( item );
2681 
2682  std::vector<wxPoint> originalPts = poly.GetPolyPoints();
2683  poly.ClearPoints();
2684 
2685  for( wxPoint& pt : originalPts )
2686  poly.AddPoint( scalePt( pt ) );
2687  }
2688  break;
2689 
2690  case KICAD_T::LIB_PIN_T:
2691  {
2692  LIB_PIN& pin = static_cast<LIB_PIN&>( item );
2693 
2694  pin.SetPosition( scalePt( pin.GetPosition() ) );
2695  pin.SetLength( scaleLen( pin.GetLength() ) );
2696  }
2697  break;
2698 
2699  case KICAD_T::LIB_TEXT_T:
2700  {
2701  LIB_TEXT& txt = static_cast<LIB_TEXT&>( item );
2702 
2703  txt.SetPosition( scalePt( txt.GetPosition() ) );
2704  txt.SetTextSize( scaleSize( txt.GetTextSize() ) );
2705  }
2706  break;
2707 
2708  default: break;
2709  }
2710 
2711  }
2712 
2713  return retval;
2714 }
2715 
2716 
2717 void CADSTAR_SCH_ARCHIVE_LOADER::fixUpLibraryPins( LIB_SYMBOL* aSymbolToFix, int aGateNumber )
2718 {
2719  // Store a list of segments that are not connected to other segments and are vertical or
2720  // horizontal.
2721  std::map<wxPoint, LIB_POLYLINE*> twoPointUniqueSegments;
2722 
2723  LIB_ITEMS_CONTAINER::ITERATOR polylineiter =
2724  aSymbolToFix->GetDrawItems().begin( LIB_POLYLINE_T );
2725 
2726  for( ; polylineiter != aSymbolToFix->GetDrawItems().end( LIB_POLYLINE_T ); ++polylineiter )
2727  {
2728  LIB_POLYLINE& polyline = static_cast<LIB_POLYLINE&>( *polylineiter );
2729 
2730  if( aGateNumber > 0 && polyline.GetUnit() != aGateNumber )
2731  continue;
2732 
2733  const std::vector<wxPoint>& pts = polyline.GetPolyPoints();
2734 
2735  bool isUnique = true;
2736 
2737  auto removeSegment =
2738  [&]( LIB_POLYLINE* aLineToRemove )
2739  {
2740  twoPointUniqueSegments.erase( aLineToRemove->GetPolyPoints().at( 0 ) );
2741  twoPointUniqueSegments.erase( aLineToRemove->GetPolyPoints().at( 1 ) );
2742  isUnique = false;
2743  };
2744 
2745  if( pts.size() == 2 )
2746  {
2747  const wxPoint& pt0 = pts.at( 0 );
2748  const wxPoint& pt1 = pts.at( 1 );
2749 
2750  if( twoPointUniqueSegments.count( pt0 ) )
2751  removeSegment( twoPointUniqueSegments.at( pt0 ) );
2752 
2753  if( twoPointUniqueSegments.count( pt1 ) )
2754  removeSegment( twoPointUniqueSegments.at( pt1 ) );
2755 
2756  if( isUnique && pt0 != pt1 )
2757  {
2758  if( pt0.x == pt1.x || pt0.y == pt1.y )
2759  {
2760  twoPointUniqueSegments.insert( { pts.at( 0 ), &polyline } );
2761  twoPointUniqueSegments.insert( { pts.at( 1 ), &polyline } );
2762  }
2763  }
2764  }
2765  }
2766 
2767  LIB_PINS pins;
2768  aSymbolToFix->GetPins( pins, aGateNumber );
2769 
2770  for( auto& pin : pins )
2771  {
2772  auto setPinOrientation =
2773  [&]( double aAngleRad )
2774  {
2775  int oDeg = (int) NormalizeAngle180( RAD2DEG( aAngleRad ) );
2776 
2777  if( oDeg >= -45 && oDeg <= 45 )
2778  pin->SetOrientation( 'R' ); // 0 degrees
2779  else if( oDeg >= 45 && oDeg <= 135 )
2780  pin->SetOrientation( 'U' ); // 90 degrees
2781  else if( oDeg >= 135 || oDeg <= -135 )
2782  pin->SetOrientation( 'L' ); // 180 degrees
2783  else
2784  pin->SetOrientation( 'D' ); // -90 degrees
2785  };
2786 
2787  if( twoPointUniqueSegments.count( pin->GetPosition() ) )
2788  {
2789  LIB_POLYLINE* poly = twoPointUniqueSegments.at( pin->GetPosition() );
2790 
2791  wxPoint otherPt = poly->GetPolyPoints().at( 0 );
2792 
2793  if( otherPt == pin->GetPosition() )
2794  otherPt = poly->GetPolyPoints().at( 1 );
2795 
2796  VECTOR2I vec( otherPt - pin->GetPosition() );
2797 
2798  pin->SetLength( vec.EuclideanNorm() );
2799  setPinOrientation( vec.Angle() );
2800  }
2801  }
2802 }
2803 
2804 
2805 std::pair<wxPoint, wxSize>
2807  const FIGURE& aCadstarFigure )
2808 {
2809  wxPoint upperLeft( Assignments.Settings.DesignLimit.x, 0 );
2810  wxPoint lowerRight( 0, Assignments.Settings.DesignLimit.y );
2811 
2812  for( const VERTEX& v : aCadstarFigure.Shape.Vertices )
2813  {
2814  if( upperLeft.x > v.End.x )
2815  upperLeft.x = v.End.x;
2816 
2817  if( upperLeft.y < v.End.y )
2818  upperLeft.y = v.End.y;
2819 
2820  if( lowerRight.x < v.End.x )
2821  lowerRight.x = v.End.x;
2822 
2823  if( lowerRight.y > v.End.y )
2824  lowerRight.y = v.End.y;
2825  }
2826 
2827  for( CUTOUT cutout : aCadstarFigure.Shape.Cutouts )
2828  {
2829  for( const VERTEX& v : aCadstarFigure.Shape.Vertices )
2830  {
2831  if( upperLeft.x > v.End.x )
2832  upperLeft.x = v.End.x;
2833 
2834  if( upperLeft.y < v.End.y )
2835  upperLeft.y = v.End.y;
2836 
2837  if( lowerRight.x < v.End.x )
2838  lowerRight.x = v.End.x;
2839 
2840  if( lowerRight.y > v.End.y )
2841  lowerRight.y = v.End.y;
2842  }
2843  }
2844 
2845  wxPoint upperLeftKiCad = getKiCadPoint( upperLeft );
2846  wxPoint lowerRightKiCad = getKiCadPoint( lowerRight );
2847 
2848  wxPoint size = lowerRightKiCad - upperLeftKiCad;
2849 
2850  return { upperLeftKiCad, wxSize( abs( size.x ), abs( size.y ) ) };
2851 }
2852 
2853 
2854 wxPoint CADSTAR_SCH_ARCHIVE_LOADER::getKiCadPoint( wxPoint aCadstarPoint )
2855 {
2856  wxPoint retval;
2857 
2858  retval.x = getKiCadLength( aCadstarPoint.x - m_designCenter.x );
2859  retval.y = -getKiCadLength( aCadstarPoint.y - m_designCenter.y );
2860 
2861  return retval;
2862 }
2863 
2864 
2866  wxPoint aCadstarPoint, wxPoint aCadstarCentre )
2867 {
2868  wxPoint retval;
2869 
2870  retval.x = getKiCadLength( aCadstarPoint.x - aCadstarCentre.x );
2871  retval.y = getKiCadLength( aCadstarPoint.y - aCadstarCentre.y );
2872 
2873  return retval;
2874 }
2875 
2876 
2877 wxPoint CADSTAR_SCH_ARCHIVE_LOADER::applyTransform( const wxPoint& aPoint,
2878  const wxPoint& aMoveVector, const double& aRotationAngleDeciDeg,
2879  const double& aScalingFactor, const wxPoint& aTransformCentre, const bool& aMirrorInvert )
2880 {
2881  wxPoint retVal = aPoint;
2882 
2883  if( aScalingFactor != 1.0 )
2884  {
2885  //scale point
2886  retVal -= aTransformCentre;
2887  retVal.x = KiROUND( retVal.x * aScalingFactor );
2888  retVal.y = KiROUND( retVal.y * aScalingFactor );
2889  retVal += aTransformCentre;
2890  }
2891 
2892  if( aMirrorInvert )
2893  {
2894  MIRROR( retVal.x, aTransformCentre.x );
2895  }
2896 
2897  if( aRotationAngleDeciDeg != 0.0 )
2898  {
2899  RotatePoint( &retVal, aTransformCentre, aRotationAngleDeciDeg );
2900  }
2901 
2902  if( aMoveVector != wxPoint{ 0, 0 } )
2903  {
2904  retVal += aMoveVector;
2905  }
2906 
2907  return retVal;
2908 }
2909 
2910 
2912 {
2913  return NormalizeAnglePos( ArcTangente( aPoint.y, aPoint.x ) );
2914 }
2915 
2916 
2918 {
2919  return sqrt(
2920  ( (double) aPoint.x * (double) aPoint.x ) + ( (double) aPoint.y * (double) aPoint.y ) );
2921 }
Field Reference of part, i.e. "IC21".
std::map< NETELEMENT_ID, BLOCK_TERM > BlockTerminals
int getKiCadUnitNumberFromGate(const GATE_ID &aCadstarGateID)
power input (GND, VCC for ICs). Must be connected to a power output.
wxPoint m_designCenter
Used for calculating the required offset to apply to the Cadstar design so that it fits in KiCad canv...
LIB_FIELD * FindField(const wxString &aFieldName)
Find a field within this symbol matching aFieldName and returns it or NULL if not found.
Definition: lib_symbol.cpp:955
int sign(T val)
Definition: util.h:103
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:49
LAYER_ID LayerID
Move all objects in the Symdef to this layer.
void GetPins(LIB_PINS &aList, int aUnit=0, int aConvert=0) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:695
ELECTRICAL_PINTYPE getKiCadPinType(const PART::PIN_TYPE &aPinType)
std::map< wxString, LIB_SYMBOL * > m_powerSymLibMap
Map of KiCad Power Symbol Library items.
SCH_SYMBOL * loadSchematicSymbol(const SYMBOL &aCadstarSymbol, const LIB_SYMBOL &aKiCadPart, double &aComponentOrientationDeciDeg)
void SetShape(PINSHEETLABEL_SHAPE aShape)
Definition: sch_text.h:163
virtual std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:79
std::map< ROUTECODE_ID, ROUTECODE > RouteCodes
ITERATOR begin(int aType=UNDEFINED_TYPE)
Definition: multivector.h:188
int Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Function Intersect()
T NormalizeAngleNeg(T Angle)
Normalize angle to be in the 0.0 .
Definition: trigo.h:267
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib=false)
Replace illegal LIB_ID item name characters with underscores '_'.
Definition: lib_id.cpp:347
int getKiCadLength(long long aCadstarLength)
std::map< PART_ID, TERMINAL_TO_PINNUM_MAP > m_pinNumsMap
Map of pin numbers in CADSTAR parts.
std::vector< INTERSECTION > INTERSECTIONS
std::pair< wxPoint, wxSize > getFigureExtentsKiCad(const FIGURE &aCadstarFigure)
std::map< TERMINAL_ID, TERMINAL > Terminals
void loadShapeVertices(const std::vector< VERTEX > &aCadstarVertices, LINECODE_ID aCadstarLineCodeID, LAYER_ID aCadstarSheetID, SCH_LAYER_ID aKiCadSchLayerID, const wxPoint &aMoveVector={ 0, 0 }, const double &aRotationAngleDeciDeg=0.0, const double &aScalingFactor=1.0, const wxPoint &aTransformCentre={ 0, 0 }, const bool &aMirrorInvert=false)
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 Merge(const EDA_RECT &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: eda_rect.cpp:432
Container for project specific data.
Definition: project.h:62
std::map< PART_DEFINITION_PIN_ID, PIN > Pins
const wxString PartNameFieldName
PART::DEFINITION::PIN getPartDefinitionPin(const PART &aCadstarPart, const GATE_ID &aGateID, const TERMINAL_ID &aTerminalID)
void AddField(LIB_FIELD *aField)
Add a field.
Definition: lib_symbol.cpp:884
void SetPosition(const wxPoint &aPosition) override
Definition: sch_symbol.h:642
LIB_FIELD & GetFootprintField()
Return reference to the footprint field.
Definition: lib_symbol.cpp:995
int getLineThickness(const LINECODE_ID &aCadstarLineCodeID)
void SetOrientation(int aOrientation)
Compute the new transform matrix based on aOrientation for the symbol which is applied to the current...
wxString ReferenceName
This is the name which identifies the symbol in the library Multiple components may exist with the sa...
wxPoint GetStartPoint() const
Definition: sch_line.h:90
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:665
long SignalNum
This is undefined if the net has been given a name.
void SetFields(const std::vector< SCH_FIELD > &aFields)
Set multiple schematic fields.
Definition: sch_sheet.h:96
Holds all the data relating to one schematic.
Definition: schematic.h:59
std::map< ATTRIBUTE_ID, ATTRNAME > AttributeNames
void SetSize(const wxSize &aSize)
Definition: sch_bus_entry.h:64
void loadLibrarySymbolShapeVertices(const std::vector< VERTEX > &aCadstarVertices, wxPoint aSymbolOrigin, LIB_SYMBOL *aSymbol, int aGateNumber)
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
#define SIGNALNAME_ORIGIN_ATTRID
long ScaleRatioNumerator
Documentation symbols can be arbitrarily scaled when added to a design.
std::map< SYMDEF_ID, SYMDEF_SCM > SymbolDefinitions
wxString getAttributeName(const ATTRIBUTE_ID &aCadstarAttributeID)
TEXT_FIELD_NAME
These are special fields in text objects enclosed between the tokens '<@' and '>' such as <@[FIELD_NA...
wxString GetName() const override
Definition: lib_symbol.h:133
TYPE Type
Determines what the associated layer is, whether parent, child or clone.
Define a symbol library graphical text item.
Definition: lib_text.h:39
int GetTop() const
Definition: eda_rect.h:113
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:55
double getAngleTenthDegree(const long long &aCadstarAngle)
std::map< LINECODE_ID, LINECODE > LineCodes
void SetLineWidth(const int aSize)
Definition: sch_line.cpp:271
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
int GetLeft() const
Definition: eda_rect.h:112
wxPoint GetPosition() const override
Definition: lib_text.h:93
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:129
std::map< LAYER_ID, SCH_SHEET * > m_sheetMap
Map between Cadstar and KiCad Sheets.
void SetItalic(bool isItalic)
Definition: eda_text.h:186
Field object used in symbol libraries.
Definition: lib_field.h:59
EDA_RECT GetTextBox(int aLine=-1, bool aInvertY=false) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:229
double RAD2DEG(double rad)
Definition: trigo.h:232
pin for passive symbols: must be connected, and can be connected to any pin
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:701
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:253
void SetUnitCount(int aCount, bool aDuplicateDrawItems=true)
Set the units per symbol count.
void SetVisible(bool aVisible)
Definition: eda_text.h:192
std::map< NETELEMENT_ID, DANGLER > Danglers
std::map< FIGURE_ID, FIGURE > Figures
double GetTextAngle() const
Definition: eda_text.h:181
long ScaleRatioDenominator
Documentation symbols can be arbitrarily scaled when added to a design.
TEXTCODE getTextCode(const TEXTCODE_ID &aCadstarTextCodeID)
unknown electrical properties: creates always a warning when connected
std::map< PART_GATE_ID, SYMDEF_ID > m_partSymbolsMap
Map holding the symbols loaded so far for a particular PART_ID and GATE_ID.
bool ReplaceIllegalFileNameChars(std::string *aName, int aReplaceChar)
Checks aName for illegal file name characters.
Definition: string.cpp:834
#define SYMBOL_NAME_ATTRID
Symbol Name attribute ID - used for placement of designators on the schematic.
void CalcRadiusAngles()
Calculate the radius and angle of an arc using the start, end, and center points.
Definition: lib_arc.cpp:537
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: sch_screen.h:125
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
bool IsPower() const
Definition: lib_symbol.cpp:411
bool HasLocation
Flag to know if this ATTRIBUTE_VALUE has a location i.e.
ALIGNMENT Alignment
In CADSTAR The default alignment for a TEXT object (when "(No Alignment()" is selected) Bottom Left o...
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:244
std::vector< SCH_FIELD > SCH_FIELDS
A container for several SCH_FIELD items.
Definition: sch_symbol.h:63
void Load(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, SCH_PLUGIN::SCH_PLUGIN_RELEASER *aSchPlugin, const wxFileName &aLibraryFileName)
Loads a CADSTAR PCB Archive file into the KiCad BOARD object given.
long long getCadstarAngle(const double &aAngleTenthDegree)
LIB_FIELD & GetValueField()
Return reference to the value field.
Definition: lib_symbol.cpp:979
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:228
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
const SHAPE_LINE_CHAIN Reverse() const
Function Reverse()
void applyTextSettings(EDA_TEXT *aKiCadTextItem, const TEXTCODE_ID &aCadstarTextCodeID, const ALIGNMENT &aCadstarAlignment, const JUSTIFICATION &aCadstarJustification, const long long aCadstarOrientAngle=0, bool aMirrored=false)
POINT getLocationOfNetElement(const NET_SCH &aNet, const NETELEMENT_ID &aNetElementID)
int GetTextThickness() const
Definition: eda_text.h:167
std::map< wxString, wxString > FilenamesToTextMap
CADSTAR doesn't have user defined text fields but does allow loading text from a file.
void SetName(const wxString &aName)
Set a user definable field name to aName.
Definition: lib_field.cpp:386
std::pair< PART_ID, GATE_ID > PART_GATE_ID
long Modifier1
It seems this is related to weight. 400=Normal, 700=Bold.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:103
Define a library symbol object.
Definition: lib_symbol.h:96
LAYER_ID AssocLayerID
Parent or Child linked sheet.
PLOT_DASH_TYPE getLineStyle(const LINECODE_ID &aCadstarLineCodeID)
const PAGE_INFO & GetPageSettings() const
Definition: sch_screen.h:124
int FindSegment(const VECTOR2I &aP, int aThreshold=1) const
Function FindSegment()
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
LAYER_ID LayerID
Sheet on which symbol is located.
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
Definition: sch_sheet.cpp:300
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:123
LIB_FIELD & GetReferenceField()
Return reference to the reference designator field.
Definition: lib_symbol.cpp:987
void SetPageNumber(const SCH_SHEET_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
Definition: sch_sheet.cpp:1136
POINT Origin
Origin of the component (this is used as the reference point when placing the component in the design...
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:116
wxString GetName(bool aUseDefaultName=true) const
Return the field name.
Definition: lib_field.cpp:363
long ScaleRatioNumerator
Symbols can be arbitrarily scaled in CADSTAR.
std::vector< LAYER_ID > SheetOrder
A vector to also store the order in which sheets are to be displayed.
The base class for drawable items used by schematic library symbols.
Definition: lib_item.h:61
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:164
ALIGNMENT Alignment
In CADSTAR The default alignment for a TEXT object (when "(No Alignment()" is selected) Bottom Left o...
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Finds a point on the line chain that is closest to point aP.
This file contains miscellaneous commonly used macros and functions.
void SetEndPoint(const wxPoint &aPosition)
Definition: sch_line.h:94
int GetBottom() const
Definition: eda_rect.h:114
Loads a csa file into a KiCad SCHEMATIC object.
std::map< PART_ID, LIB_SYMBOL * > m_partMap
Map between Cadstar and KiCad Parts.
void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition: mirror.h:40
void loadSymbolFieldAttribute(const ATTRIBUTE_LOCATION &aCadstarAttrLoc, const double &aComponentOrientationDeciDeg, bool aIsMirrored, SCH_FIELD *aKiCadField)
int GetTextHeight() const
Definition: eda_text.h:251
ITERATOR end(int aType=UNDEFINED_TYPE)
Definition: multivector.h:194
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
Some attributes are defined within the part definition, whilst others are defined in the part itself.
void loadGraphicStaightSegment(const wxPoint &aStartPoint, const wxPoint &aEndPoint, const LINECODE_ID &aCadstarLineCodeID, const LAYER_ID &aCadstarSheetID, const SCH_LAYER_ID &aKiCadSchLayerID, const wxPoint &aMoveVector={ 0, 0 }, const double &aRotationAngleDeciDeg=0.0, const double &aScalingFactor=1.0, const wxPoint &aTransformCentre={ 0, 0 }, const bool &aMirrorInvert=false)
std::set< TEXT_FIELD_NAME > InconsistentTextFields
Text fields need to be updated in CADSTAR and it is possible that they are not consistent across text...
void SetNumber(const wxString &aNumber)
Definition: lib_pin.h:118
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:119
const std::vector< wxPoint > & GetPolyPoints() const
Definition: lib_polyline.h:54
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:88
T NormalizeAngle180(T Angle)
Normalize angle to be in the -180.0 .. 180.0 range.
Definition: trigo.h:376
int GetUnit() const
Definition: lib_item.h:259
void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
Definition: lib_symbol.h:568
void loadSheetAndChildSheets(LAYER_ID aCadstarSheetID, wxPoint aPosition, wxSize aSheetSize, const SCH_SHEET_PATH &aParentSheet)
void SetLineStyle(const PLOT_DASH_TYPE aStyle)
Definition: sch_line.cpp:239
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
Definition: sch_symbol.cpp:711
Represents a point in x,y coordinates.
void SetEnd(const wxPoint &aPoint)
Definition: lib_arc.h:96
ALIGNMENT
From CADSTAR Help: "Text Alignment enables you to define the position of an alignment origin for all ...
wxPoint applyTransform(const wxPoint &aPoint, const wxPoint &aMoveVector={ 0, 0 }, const double &aRotationAngleDeciDeg=0.0, const double &aScalingFactor=1.0, const wxPoint &aTransformCentre={ 0, 0 }, const bool &aMirrorInvert=false)
Field Value of part, i.e. "3.3K".
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:114
SCH_ITEM * Duplicate(bool doClone=false) const
Routine to create a new copy of given item.
Definition: sch_item.cpp:78
#define NULL
const SHAPE_LINE_CHAIN ConvertToPolyline(double aAccuracy=0.005 *PCB_IU_PER_MM) const
Constructs a SHAPE_LINE_CHAIN of segments from a given arc.
Definition: shape_arc.cpp:417
const std::vector< VECTOR2I > & CPoints() const
std::map< ATTRIBUTE_ID, ATTRCOL > AttributeColors
long TERMINAL_ID
Terminal is the pin identifier in the schematic.
std::map< NETELEMENT_ID, SYM_TERM > Terminals
std::map< PART_ID, PART > PartDefinitions
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:53
SYMDEF_ID getSymDefFromName(const wxString &aSymdefName, const wxString &aSymDefAlternate)
iterator end()
Definition: sch_rtree.h:250
long Width
Defaults to 0 if using system fonts or, if using CADSTAR font, default to equal height (1:1 aspect ra...
void SetPosition(const wxPoint &aPosition) override
Definition: sch_junction.h:93
const wxSize & GetTextSize() const
Definition: eda_text.h:245
std::map< SYMBOL_ID, SCH_GLOBALLABEL * > m_globalLabelsMap
Map between Cadstar and KiCad Global Labels.
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:209
std::map< BUS_ID, std::shared_ptr< BUS_ALIAS > > m_busesMap
Map of Cadstar and KiCad Buses.
void SetLayer(SCH_LAYER_ID aLayer)
Set the layer this item is on.
Definition: sch_item.h:279
void SetStartPoint(const wxPoint &aPosition)
Definition: sch_line.h:91
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:421
int GetRight() const
Definition: eda_rect.h:111
wxPoint GetStart() const
Definition: lib_arc.h:92
SCH_TEXT * getKiCadSchText(const TEXT &aCadstarTextElement)
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
Definition: sch_symbol.cpp:274
EDA_RECT GetBodyBoundingBox() const
Return a bounding box for the symbol body but not the fields.
int getSheetNumber(LAYER_ID aCadstarSheetID)
void SetDescription(const wxString &aDescription)
Definition: lib_symbol.h:140
void loadChildSheets(LAYER_ID aCadstarSheetID, const SCH_SHEET_PATH &aSheet)
GATE_ID GateID
The gate this symbol represents within the associated Part.
Definition of file extensions used in Kicad.
void loadSymDefIntoLibrary(const SYMDEF_ID &aSymdefID, const PART *aCadstarPart, const GATE_ID &aGateID, LIB_SYMBOL *aSymbol)
std::map< TERMINAL_ID, TERMINAL > Terminals
std::map< TERMINAL_ID, SYMPINNAME_LABEL > PinNames
Identifier of the pin in the PCB Equivalent to KiCad's Pin Number.
EDA_ITEM * GetParent() const
Definition: eda_item.h:115
void SetLabelSpinStyle(LABEL_SPIN_STYLE aSpinStyle) override
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_text.cpp:1471
#define _(s)
PART getPart(const PART_ID &aCadstarPartID)
SYMDEF_ID SymdefID
Normally documentation symbols only have TEXT, FIGURE and TEXT_LOCATION objects which are all drawn o...
void AddDrawItem(LIB_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
Definition: lib_symbol.cpp:655
SCH_LAYER_ID
Eeschema drawing layers.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:65
void loadItemOntoKiCadSheet(LAYER_ID aCadstarSheetID, SCH_ITEM *aItem)
#define PART_NAME_ATTRID
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
std::pair< BLOCK_ID, TERMINAL_ID > BLOCK_PIN_ID
std::map< REUSEBLOCK_ID, REUSEBLOCK > ReuseBlocks
static void FixTextPositionNoAlignment(EDA_TEXT *aKiCadTextItem)
Corrects the position of a text element that had NO_ALIGNMENT in CADSTAR.
void AddPoint(const wxPoint &aPoint)
std::map< NETELEMENT_ID, BUS_TERM > BusTerminals
ROUTECODE getRouteCode(const ROUTECODE_ID &aCadstarRouteCodeID)
long Param1
Either Units or X step, depending on Type (see GRID_TYPE for more details)
std::map< BLOCK_PIN_ID, SCH_HIERLABEL * > m_sheetPinMap
Map between Cadstar and KiCad Sheets Pins.
wxPoint GetPosition() const override
Definition: sch_text.h:237
wxPoint GetPosition() const override
Definition: sch_sheet.h:379
void applyToLibraryFieldAttribute(const ATTRIBUTE_LOCATION &aCadstarAttrLoc, wxPoint aSymbolOrigin, LIB_FIELD *aKiCadField)
LABEL_SPIN_STYLE MirrorY()
Mirror the label spin style across the Y axis or simply swaps left and right.
Definition: sch_text.cpp:185
SCH_FIELD * FindField(const wxString &aFieldName, bool aIncludeDefaultFields=true)
Search for a SCH_FIELD with aFieldName.
Definition: sch_symbol.cpp:733
SCH_PLUGIN::SCH_PLUGIN_RELEASER * m_plugin
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:473
POINT Origin
Origin of the component (this is used as the reference point when placing the component in the design...
static const long UNDEFINED_VALUE
int SegmentCount() const
Function SegmentCount()
void SetMultilineAllowed(bool aAllow)
Definition: eda_text.h:202
void SetHeightMils(int aHeightInMils)
Definition: page_info.cpp:257
Corresponds to CADSTAR "origin".
< Nodename = "VARIANT" or "VMASTER" (master variant
ALIGNMENT mirrorX(const ALIGNMENT &aCadstarAlignment)
void fixUpLibraryPins(LIB_SYMBOL *aSymbolToFix, int aGateNumber)
LAYER_ID LayerID
The sheet block is on (TODO: verify this is true)
std::vector< LAYER_ID > findOrphanSheets()
std::map< SYMBOL_ID, SCH_SYMBOL * > m_powerSymMap
Map between Cadstar and KiCad Power Symbols.
LABEL_SPIN_STYLE RotateCCW()
Definition: sch_text.cpp:151
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
Definition: string.cpp:895
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:54
PLOT_DASH_TYPE
Dashed line types.
Definition: plotter.h:104
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:75
static wxString generateLibName(const wxString &aRefName, const wxString &aAlternateName)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
ITERATOR_BASE< LIB_ITEM, MULTIVECTOR< LIB_ITEM, FIRST_TYPE_VAL, LAST_TYPE_VAL >, typename ITEM_PTR_VECTOR::iterator > ITERATOR
The const iterator.
Definition: multivector.h:164
int KiCadUnitDivider
Use this value to convert units in this CSA file to KiCad units.
void SetTextWidth(int aWidth)
Definition: eda_text.h:247
constexpr double SCH_IU_PER_MM
JUSTIFICATION Justification
Note: Justification has no effect on single lines of text.
void ClearPoints()
Definition: lib_polyline.h:50
Helper object to release a SCH_PLUGIN in the context of a potential thrown exception through its dest...
Definition: sch_io_mgr.h:473
bool HidePinNames
Specifies whether to display the pin names/identifier in the schematic symbol or not.
void SetUnit(int aUnit)
Definition: lib_item.h:258
JUSTIFICATION
From CADSTAR Help: "Multi Line Text can also be justified as Left, Centre or Right.
bool LocatePathOfScreen(SCH_SCREEN *aScreen, SCH_SHEET_PATH *aList)
Search the existing hierarchy for an instance of screen loaded from aFileName.
Definition: sch_sheet.cpp:666
std::vector< CUTOUT > Cutouts
Not Applicable to OPENSHAPE Type.
SEG Segment(int aIndex)
Function Segment()
std::map< TEXTCODE_ID, TEXTCODE > TextCodes
LABEL_SPIN_STYLE MirrorX()
Mirror the label spin style across the X axis or simply swaps up and bottom.
Definition: sch_text.cpp:168
Param1 = Units, Param2 = Divisor.
size_t GetFieldCount() const
Definition: lib_symbol.h:361
LABEL_SPIN_STYLE getSpinStyle(const long long &aCadstarOrientation, bool aMirror)
int GetTextWidth() const
Definition: eda_text.h:248
Schematic symbol object.
Definition: sch_symbol.h:78
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...
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).
const char * name
Definition: DXF_plotter.cpp:59
int getComponentOrientation(double aOrientAngleDeciDeg, double &aReturnedOrientationDeciDeg)
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition: pin_type.h:35
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:144
wxString Name
This is undefined (wxEmptyString) if the net is unnamed.
iterator begin()
Definition: sch_rtree.h:245
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:208
usual pin input: must be connected
wxSize GetSize() const
Definition: sch_sheet.h:105
SHAPE_LINE_CHAIN.
void SetFPFilters(const wxArrayString &aFilters)
Definition: lib_symbol.h:181
void SetPower()
Definition: lib_symbol.cpp:420
T NormalizeAnglePos(T Angle)
Normalize angle to be in the 0.0 .
Definition: trigo.h:279
long Param2
Either Divisor or Y step, depending on Type (see GRID_TYPE for more details)
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
Definition: sch_symbol.cpp:471
wxString GetName(bool aUseDefaultName=true) const
Return the field name.
Definition: sch_field.cpp:548
JUSTIFICATION Justification
Note: Justification has no effect on single lines of text.
EE_RTREE & Items()
Definition: sch_screen.h:102
wxPoint getKiCadLibraryPoint(wxPoint aCadstarPoint, wxPoint aCadstarCentre)
void SetWidthMils(int aWidthInMils)
Definition: page_info.cpp:243
VECTOR2I A
Definition: seg.h:48
wxPoint GetEnd() const
Definition: lib_arc.h:95
Handle the component boundary box.
Definition: eda_rect.h:42
const std::string KiCadSchematicFileExtension
std::map< LAYER_ID, SHEET_NAME > SheetNames
void SetTextHeight(int aHeight)
Definition: eda_text.h:250
LAYER_ID LayerID
Sheet on which bus is located.
void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition: lib_symbol.h:576
static bool ClassOf(const EDA_ITEM *aItem)
Definition: sch_sheet.h:67
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:70
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
Some attributes are defined within the part definition, whilst others are defined in the part.
std::map< ATTRIBUTE_ID, TEXT_LOCATION > TextLocations
This contains location of any attributes, including designator position.
POINT Position
Pad position within the component's coordinate frame.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
ALIGNMENT rotate180(const ALIGNMENT &aCadstarAlignment)
wxPoint Centre() const
Definition: eda_rect.h:55
wxString Alternate
This is in addition to ReferenceName.
Class for a wire to bus entry.
wxPoint getKiCadPoint(wxPoint aCadstarPoint)
const wxPoint & GetTextPos() const
Definition: eda_text.h:254
void SetPosition(const wxPoint &aPosition) override
Definition: lib_item.h:212
void SetStart(const wxPoint &aPoint)
Definition: lib_arc.h:93
input or output (like port for a microprocessor)
wxString getNetName(const NET_SCH &aNet)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:166
wxString LAYER_ID
ID of a Sheet (if schematic) or board Layer (if PCB)
LABEL_SPIN_STYLE getSpinStyleDeciDeg(const double &aOrientationDeciDeg)
void Update(SCH_ITEM *aItem)
Update aItem's bounding box in the tree.
Definition: sch_screen.cpp:253
virtual void SetTextAngle(double aAngle)
Definition: eda_text.h:174
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:182
void SetLabelSpinStyle(LABEL_SPIN_STYLE aSpinStyle) override
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_text.cpp:1020
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:108
virtual const EDA_RECT GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:75
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: lib_text.cpp:77
void Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Function Replace()
virtual void SetLabelSpinStyle(LABEL_SPIN_STYLE aSpinStyle)
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_text.cpp:317
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
bool isAttributeVisible(const ATTRIBUTE_ID &aCadstarAttributeID)
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...
void SetPosition(const wxPoint &aPosition) override
Definition: sch_text.h:238
std::map< DOCUMENTATION_SYMBOL_ID, DOCUMENTATION_SYMBOL > DocumentationSymbols
std::map< NETELEMENT_ID, JUNCTION_SCH > Junctions
static constexpr int Millimeter2iu(double mm)
void SetBold(bool aBold)
Definition: eda_text.h:189
void SetPosition(const wxPoint &aPosition) override
Definition: sch_field.cpp:693
NO_ALIGNMENT has different meaning depending on the object type.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:197
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:133
std::map< TEXT_FIELD_NAME, wxString > TextFieldToValuesMap
Values for the text field elements used in the CADSTAR design extracted from the text element instanc...
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
void loadFigure(const FIGURE &aCadstarFigure, const LAYER_ID &aCadstarSheetIDOverride, SCH_LAYER_ID aKiCadSchLayerID, const wxPoint &aMoveVector={ 0, 0 }, const double &aRotationAngleDeciDeg=0.0, const double &aScalingFactor=1.0, const wxPoint &aTransformCentre={ 0, 0 }, const bool &aMirrorInvert=false)
static const std::map< TEXT_FIELD_NAME, wxString > CADSTAR_TO_KICAD_FIELDS
Map between CADSTAR fields and KiCad text variables.
bool AddInstance(const KIID_PATH &aInstance)
Add a new instance aSheetPath to the instance list.
Definition: sch_sheet.cpp:1094
Represents a cutout in a closed shape (e.g.
const wxSize GetSize() const
Definition: eda_rect.h:91
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
wxPoint GetPosition() const override
Definition: lib_arc.h:71
Represents a vertex in a shape.
LIB_SYMBOL * getScaledLibPart(const LIB_SYMBOL *aSymbol, long long aScalingFactorNumerator, long long aScalingFactorDenominator)
VECTOR2I B
Definition: seg.h:49
wxPoint GetEndPoint() const
Definition: sch_line.h:93