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