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