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 = wxT( "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( wxT( "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( wxT( "${" ) ) )
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  wxT( "%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 = wxT( "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, wxT( "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( wxT( "#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( wxT( "***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( wxT( "in" ) ) )
669  else if( libSymDef.Alternate.Lower().Contains( wxT( "bi" ) ) )
671  else if( libSymDef.Alternate.Lower().Contains( wxT( "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, wxT( "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( wxT( "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( wxT( "$%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( wxT( "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, wxT( "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  // Ensure there are no items on this unit (e.g. if we already previously loaded the symbol from
1312  // the part definition)
1313  std::vector<LIB_ITEM*> drawItems = aSymbol->GetUnitDrawItems( gateNumber, 0 );
1314 
1315  for( LIB_ITEM* item : drawItems )
1316  aSymbol->RemoveDrawItem( item );
1317 
1318  for( std::pair<FIGURE_ID, FIGURE> figPair : symbol.Figures )
1319  {
1320  FIGURE fig = figPair.second;
1321  int lineThickness = getLineThickness( fig.LineCodeID );
1322 
1323  loadLibrarySymbolShapeVertices( fig.Shape.Vertices, symbol.Origin, aSymbol, gateNumber,
1324  lineThickness );
1325 
1326  for( CUTOUT c : fig.Shape.Cutouts )
1327  {
1328  loadLibrarySymbolShapeVertices( c.Vertices, symbol.Origin, aSymbol, gateNumber,
1329  lineThickness );
1330  }
1331  }
1332 
1333  TERMINAL_TO_PINNUM_MAP pinNumMap;
1334 
1335  for( std::pair<TERMINAL_ID, TERMINAL> termPair : symbol.Terminals )
1336  {
1337  TERMINAL term = termPair.second;
1338  wxString pinNum = wxString::Format( wxT( "%ld" ), term.ID );
1339  wxString pinName = wxEmptyString;
1340  LIB_PIN* pin = new LIB_PIN( aSymbol );
1341 
1342  if( aCadstarPart )
1343  {
1344  PART::DEFINITION::PIN csPin = getPartDefinitionPin( *aCadstarPart, aGateID, term.ID );
1345 
1346  pinName = HandleTextOverbar( csPin.Label );
1347  pinNum = HandleTextOverbar( csPin.Name );
1348 
1349  if( pinNum.IsEmpty() )
1350  {
1351  if( !csPin.Identifier.IsEmpty() )
1352  pinNum = csPin.Identifier;
1353  else if( csPin.ID == UNDEFINED_VALUE )
1354  pinNum = wxString::Format( wxT( "%ld" ), term.ID );
1355  else
1356  pinNum = wxString::Format( wxT( "%ld" ), csPin.ID );
1357  }
1358 
1359  pin->SetType( getKiCadPinType( csPin.Type ) );
1360 
1361  pinNumMap.insert( { term.ID, pinNum } );
1362  }
1363  else
1364  {
1365  // If no part is defined, we don't know the pin type. Assume passive pin
1366  pin->SetType( ELECTRICAL_PINTYPE::PT_PASSIVE );
1367  }
1368 
1369  pin->SetPosition( getKiCadLibraryPoint( term.Position, symbol.Origin ) );
1370  pin->SetLength( 0 ); //CADSTAR Pins are just a point (have no length)
1371  pin->SetShape( GRAPHIC_PINSHAPE::LINE );
1372  pin->SetUnit( gateNumber );
1373  pin->SetNumber( pinNum );
1374  pin->SetName( pinName );
1375 
1376  int pinNumberHeight = getTextHeightFromTextCode( wxT( "TC0" ) ); // TC0 is the default CADSTAR text size for name/number
1377  int pinNameHeight = getTextHeightFromTextCode( wxT( "TC0" ) );
1378 
1379  if( symbol.PinNumberLocations.count( term.ID ) )
1380  {
1381  PIN_NUM_LABEL_LOC pinNumLocation = symbol.PinNumberLocations.at( term.ID );
1382  pinNumberHeight = getTextHeightFromTextCode( pinNumLocation.TextCodeID );
1383  }
1384 
1385  if( symbol.PinLabelLocations.count( term.ID ) )
1386  {
1387  PIN_NUM_LABEL_LOC pinNameLocation = symbol.PinLabelLocations.at( term.ID );
1388  pinNameHeight = getTextHeightFromTextCode( pinNameLocation.TextCodeID );
1389  }
1390 
1391  pin->SetNumberTextSize( pinNumberHeight );
1392  pin->SetNameTextSize( pinNameHeight );
1393 
1394  if( aSymbol->IsPower() )
1395  {
1396  pin->SetVisible( false );
1398  pin->SetName( aSymbol->GetName() );
1399  }
1400 
1401  aSymbol->AddDrawItem( pin );
1402  }
1403 
1404  fixUpLibraryPins( aSymbol, gateNumber );
1405 
1406  if(aCadstarPart)
1407  m_pinNumsMap.insert( { aCadstarPart->ID + aGateID, pinNumMap } );
1408 
1409  for( std::pair<TEXT_ID, TEXT> textPair : symbol.Texts )
1410  {
1411  TEXT csText = textPair.second;
1412 
1413  LIB_TEXT* libtext = new LIB_TEXT( aSymbol );
1414  libtext->SetText( csText.Text );
1415  libtext->SetUnit( gateNumber );
1416  libtext->SetPosition( getKiCadLibraryPoint( csText.Position, symbol.Origin ) );
1417  libtext->SetMultilineAllowed( true ); // temporarily so that we calculate bbox correctly
1418 
1419  applyTextSettings( libtext,
1420  csText.TextCodeID,
1421  csText.Alignment,
1422  csText.Justification,
1423  csText.OrientAngle,
1424  csText.Mirror );
1425 
1426  // Split out multi line text items into individual text elements
1427  if( csText.Text.Contains( wxT( "\n" ) ) )
1428  {
1429  wxArrayString strings;
1430  wxStringSplit( csText.Text, strings, '\n' );
1431  wxPoint firstLinePos;
1432 
1433  for( size_t ii = 0; ii < strings.size(); ++ii )
1434  {
1435  EDA_RECT bbox = libtext->GetTextBox( ii, true );
1436  wxPoint linePos = { bbox.GetLeft(), -bbox.GetBottom() };
1437 
1438  RotatePoint( &linePos, libtext->GetTextPos(), -libtext->GetTextAngle() );
1439 
1440  LIB_TEXT* line = static_cast<LIB_TEXT*>( libtext->Clone() );
1441  line->SetText( strings[ii] );
1442  line->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
1443  line->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
1444  line->SetTextPos( linePos );
1445 
1446  // Multiline text not allowed in LIB_TEXT
1447  line->SetMultilineAllowed( false );
1448  aSymbol->AddDrawItem( line );
1449  }
1450 
1451  delete libtext;
1452  }
1453  else
1454  {
1455  // Multiline text not allowed in LIB_TEXT
1456  libtext->SetMultilineAllowed( false );
1457  aSymbol->AddDrawItem( libtext );
1458  }
1459  }
1460 
1461  if( symbol.TextLocations.find( SYMBOL_NAME_ATTRID ) != symbol.TextLocations.end() )
1462  {
1463  TEXT_LOCATION textLoc = symbol.TextLocations.at( SYMBOL_NAME_ATTRID );
1464  LIB_FIELD* field = &aSymbol->GetReferenceField();
1465  applyToLibraryFieldAttribute( textLoc, symbol.Origin, field );
1466  field->SetUnit( gateNumber );
1467  }
1468 
1469  // Hide the value field for now (it might get unhidden if an attribute exists in the cadstar
1470  // design with the text "Value"
1471  aSymbol->GetValueField().SetVisible( false );
1472 
1473  if( symbol.TextLocations.find( PART_NAME_ATTRID ) != symbol.TextLocations.end() )
1474  {
1475  TEXT_LOCATION textLoc = symbol.TextLocations.at( PART_NAME_ATTRID );
1476  LIB_FIELD* field = aSymbol->FindField( PartNameFieldName );
1477 
1478  if( !field )
1479  {
1480  int fieldID = aSymbol->GetFieldCount();
1481  field = new LIB_FIELD( aSymbol, fieldID );
1482  field->SetName( PartNameFieldName );
1483  aSymbol->AddField( field );
1484  }
1485 
1486  wxASSERT( field->GetName() == PartNameFieldName );
1487  applyToLibraryFieldAttribute( textLoc, symbol.Origin, field );
1488 
1489  if( aCadstarPart )
1490  {
1491  wxString partName = aCadstarPart->Name;
1492  partName.Replace( wxT( "\n" ), wxT( "\\n" ) );
1493  partName.Replace( wxT( "\r" ), wxT( "\\r" ) );
1494  partName.Replace( wxT( "\t" ), wxT( "\\t" ) );
1495  field->SetText( partName );
1496  }
1497 
1498  field->SetUnit( gateNumber );
1500  }
1501 
1502  if( aCadstarPart )
1503  {
1504  wxString footprintRefName = wxEmptyString;
1505  wxString footprintAlternateName = wxEmptyString;
1506 
1507  auto loadLibraryField =
1508  [&]( ATTRIBUTE_VALUE& aAttributeVal )
1509  {
1510  wxString attrName = getAttributeName( aAttributeVal.AttributeID );
1511 
1512  // Remove invalid field characters
1513  aAttributeVal.Value.Replace( wxT( "\n" ), wxT( "\\n" ) );
1514  aAttributeVal.Value.Replace( wxT( "\r" ), wxT( "\\r" ) );
1515  aAttributeVal.Value.Replace( wxT( "\t" ), wxT( "\\t" ) );
1516 
1517  //TODO: Handle "links": In cadstar a field can be a "link" if its name starts
1518  // with the characters "Link ". Need to figure out how to convert them to
1519  // equivalent in KiCad.
1520 
1521  if( attrName == wxT( "(PartDefinitionNameStem)" ) )
1522  {
1523  //Space not allowed in Reference field
1524  aAttributeVal.Value.Replace( wxT( " " ), "_" );
1525  aSymbol->GetReferenceField().SetText( aAttributeVal.Value );
1526  return;
1527  }
1528  else if( attrName == wxT( "(PartDescription)" ) )
1529  {
1530  aSymbol->SetDescription( aAttributeVal.Value );
1531  return;
1532  }
1533  else if( attrName == wxT( "(PartDefinitionReferenceName)" ) )
1534  {
1535  footprintRefName = aAttributeVal.Value;
1536  return;
1537  }
1538  else if( attrName == wxT( "(PartDefinitionAlternateName)" ) )
1539  {
1540  footprintAlternateName = aAttributeVal.Value;
1541  return;
1542  }
1543 
1544  LIB_FIELD* attrField = aSymbol->FindField( attrName );
1545 
1546  if( !attrField )
1547  {
1548  int fieldID = aSymbol->GetFieldCount();
1549  attrField = new LIB_FIELD( aSymbol, fieldID );
1550  attrField->SetName( attrName );
1551  aSymbol->AddField( attrField );
1552  }
1553 
1554  wxASSERT( attrField->GetName() == attrName );
1555  attrField->SetText( aAttributeVal.Value );
1556  attrField->SetUnit( gateNumber );
1557 
1558  ATTRIBUTE_ID& attrid = aAttributeVal.AttributeID;
1559  attrField->SetVisible( isAttributeVisible( attrid ) );
1560 
1561  if( aAttributeVal.HasLocation )
1562  {
1563  // #1 Check if the part itself defined a location for the field
1564  applyToLibraryFieldAttribute( aAttributeVal.AttributeLocation, symbol.Origin,
1565  attrField );
1566  }
1567  else if( symbol.TextLocations.find( aAttributeVal.AttributeID )
1568  != symbol.TextLocations.end() )
1569  {
1570  // #2 Look in the symbol definition: Text locations
1571  TEXT_LOCATION symTxtLoc = symbol.TextLocations.at( aAttributeVal.AttributeID );
1572  applyToLibraryFieldAttribute( symTxtLoc, symbol.Origin, attrField );
1573  }
1574  else if( symbol.AttributeValues.find( attrid ) != symbol.AttributeValues.end()
1575  && symbol.AttributeValues.at( attrid ).HasLocation )
1576  {
1577  // #3 Look in the symbol definition: Attribute values
1578  ATTRIBUTE_VALUE symAttrVal = symbol.AttributeValues.at( attrid );
1579  applyToLibraryFieldAttribute( symAttrVal.AttributeLocation, symbol.Origin,
1580  attrField );
1581  }
1582  else
1583  {
1584  attrField->SetVisible( false );
1585  applyTextSettings( attrField, wxT( "TC1" ), ALIGNMENT::NO_ALIGNMENT,
1587  }
1588  };
1589 
1590  // Load all attributes in the Part Definition
1591  for( std::pair<ATTRIBUTE_ID,
1592  ATTRIBUTE_VALUE> attr : aCadstarPart->Definition.AttributeValues )
1593  {
1594  ATTRIBUTE_VALUE attrVal = attr.second;
1595  loadLibraryField( attrVal );
1596  }
1597 
1598  // Load all attributes in the Part itself.
1599  for( std::pair<ATTRIBUTE_ID, ATTRIBUTE_VALUE> attr : aCadstarPart->AttributeValues )
1600  {
1601  ATTRIBUTE_VALUE attrVal = attr.second;
1602  loadLibraryField( attrVal );
1603  }
1604 
1605  wxString fpNameInLibrary = generateLibName( footprintRefName, footprintAlternateName );
1606  wxArrayString fpFilters;
1607  fpFilters.Add( fpNameInLibrary );
1608 
1609  aSymbol->SetFPFilters( fpFilters );
1610 
1611  // Assume that the PCB footprint library name will be the same as the schematic filename
1612  wxFileName schFilename( Filename );
1613  wxString libName = schFilename.GetName();
1614 
1615  aSymbol->GetFootprintField().SetText( libName + wxT( ":" ) + fpNameInLibrary );
1616  }
1617 
1618  if( aCadstarPart && aCadstarPart->Definition.HidePinNames )
1619  {
1620  aSymbol->SetShowPinNames( false );
1621  aSymbol->SetShowPinNumbers( false );
1622  }
1623 }
1624 
1625 
1626 void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
1627  wxPoint aSymbolOrigin,
1628  LIB_SYMBOL* aSymbol,
1629  int aGateNumber,
1630  int aLineThickness )
1631 {
1632  const VERTEX* prev = &aCadstarVertices.at( 0 );
1633  const VERTEX* cur;
1634 
1635  wxASSERT_MSG( prev->Type == VERTEX_TYPE::POINT, wxT( "First vertex should always be a point." ) );
1636 
1637  for( size_t i = 1; i < aCadstarVertices.size(); i++ )
1638  {
1639  cur = &aCadstarVertices.at( i );
1640 
1641  LIB_SHAPE* shape = nullptr;
1642  bool cw = false;
1643  wxPoint startPoint = getKiCadLibraryPoint( prev->End, aSymbolOrigin );
1644  wxPoint endPoint = getKiCadLibraryPoint( cur->End, aSymbolOrigin );
1645  wxPoint centerPoint;
1646 
1649  {
1650  centerPoint = ( startPoint + endPoint ) / 2;
1651  }
1652  else
1653  {
1654  centerPoint = getKiCadLibraryPoint( cur->Center, aSymbolOrigin );
1655  }
1656 
1657 
1658  switch( cur->Type )
1659  {
1660  case VERTEX_TYPE::POINT:
1661  shape = new LIB_SHAPE( aSymbol, SHAPE_T::POLY );
1662  shape->AddPoint( startPoint );
1663  shape->AddPoint( endPoint );
1664  break;
1665 
1668  cw = true;
1670 
1673  shape = new LIB_SHAPE( aSymbol, SHAPE_T::ARC );
1674 
1675  shape->SetPosition( centerPoint );
1676 
1677  if( cw )
1678  {
1679  shape->SetStart( endPoint );
1680  shape->SetEnd( startPoint );
1681  }
1682  else
1683  {
1684  shape->SetStart( startPoint );
1685  shape->SetEnd( endPoint );
1686  }
1687 
1688  break;
1689  }
1690 
1691  shape->SetUnit( aGateNumber );
1692  shape->SetWidth( aLineThickness );
1693  aSymbol->AddDrawItem( shape );
1694 
1695  prev = cur;
1696  }
1697 }
1698 
1699 
1701  const ATTRIBUTE_LOCATION& aCadstarAttrLoc, wxPoint aSymbolOrigin, LIB_FIELD* aKiCadField )
1702 {
1703  aKiCadField->SetTextPos( getKiCadLibraryPoint( aCadstarAttrLoc.Position, aSymbolOrigin ) );
1704 
1705  applyTextSettings( aKiCadField,
1706  aCadstarAttrLoc.TextCodeID,
1707  aCadstarAttrLoc.Alignment,
1708  aCadstarAttrLoc.Justification,
1709  aCadstarAttrLoc.OrientAngle,
1710  aCadstarAttrLoc.Mirror );
1711 }
1712 
1713 
1715  const LIB_SYMBOL& aKiCadPart,
1716  double& aComponentOrientationDeciDeg )
1717 {
1718  LIB_ID libId( m_libraryFileName.GetName(), aKiCadPart.GetName() );
1719  int unit = getKiCadUnitNumberFromGate( aCadstarSymbol.GateID );
1720 
1721  SCH_SHEET_PATH sheetpath;
1722  SCH_SHEET* kiSheet = m_sheetMap.at( aCadstarSymbol.LayerID );
1723  m_rootSheet->LocatePathOfScreen( kiSheet->GetScreen(), &sheetpath );
1724 
1725  SCH_SYMBOL* symbol = new SCH_SYMBOL( aKiCadPart, libId, &sheetpath, unit );
1726 
1727  if( aCadstarSymbol.IsComponent )
1728  {
1729  symbol->SetRef( &sheetpath, aCadstarSymbol.ComponentRef.Designator );
1730  }
1731 
1732  symbol->SetPosition( getKiCadPoint( aCadstarSymbol.Origin ) );
1733 
1734  double compAngleDeciDeg = getAngleTenthDegree( aCadstarSymbol.OrientAngle );
1735  int compOrientation = 0;
1736 
1737  if( aCadstarSymbol.Mirror )
1738  {
1739  compAngleDeciDeg = -compAngleDeciDeg;
1740  compOrientation += SYMBOL_ORIENTATION_T::SYM_MIRROR_Y;
1741  }
1742 
1743  compOrientation += getComponentOrientation( compAngleDeciDeg, aComponentOrientationDeciDeg );
1744 
1745  if( NormalizeAngle180( compAngleDeciDeg ) != NormalizeAngle180( aComponentOrientationDeciDeg ) )
1746  {
1747  m_reporter->Report( wxString::Format( _( "Symbol '%s' is rotated by an angle of %.1f "
1748  "degrees in the original CADSTAR design but "
1749  "KiCad only supports rotation angles multiples "
1750  "of 90 degrees. The connecting wires will need "
1751  "manual fixing." ),
1752  aCadstarSymbol.ComponentRef.Designator,
1753  compAngleDeciDeg / 10.0 ),
1755  }
1756 
1757  symbol->SetOrientation( compOrientation );
1758 
1759  if( m_sheetMap.find( aCadstarSymbol.LayerID ) == m_sheetMap.end() )
1760  {
1761  m_reporter->Report( wxString::Format( _( "Symbol '%s' references sheet ID '%s' which does "
1762  "not exist in the design. The symbol was not "
1763  "loaded." ),
1764  aCadstarSymbol.ComponentRef.Designator,
1765  aCadstarSymbol.LayerID ),
1767 
1768  delete symbol;
1769  return nullptr;
1770  }
1771 
1772  wxString gate = ( aCadstarSymbol.GateID.IsEmpty() ) ? wxT( "A" ) : aCadstarSymbol.GateID;
1773  wxString partGateIndex = aCadstarSymbol.PartRef.RefID + gate;
1774 
1775  //Handle pin swaps
1776  if( m_pinNumsMap.find( partGateIndex ) != m_pinNumsMap.end() )
1777  {
1778  TERMINAL_TO_PINNUM_MAP termNumMap = m_pinNumsMap.at( partGateIndex );
1779 
1780  std::map<wxString, LIB_PIN*> pinNumToLibPinMap;
1781 
1782  for( auto& term : termNumMap )
1783  {
1784  wxString pinNum = term.second;
1785  pinNumToLibPinMap.insert( { pinNum,
1786  symbol->GetLibSymbolRef()->GetPin( term.second ) } );
1787  }
1788 
1789  auto replacePinNumber = [&]( wxString aOldPinNum, wxString aNewPinNum )
1790  {
1791  if( aOldPinNum == aNewPinNum )
1792  return;
1793 
1794  LIB_PIN* libpin = pinNumToLibPinMap.at( aOldPinNum );
1795  libpin->SetNumber( HandleTextOverbar( aNewPinNum ) );
1796  };
1797 
1798  //Older versions of Cadstar used pin numbers
1799  for( auto& pinPair : aCadstarSymbol.PinNumbers )
1800  {
1801  SYMBOL::PIN_NUM pin = pinPair.second;
1802 
1803  replacePinNumber( termNumMap.at( pin.TerminalID ),
1804  wxString::Format( wxT( "%ld" ), pin.PinNum ) );
1805  }
1806 
1807  //Newer versions of Cadstar use pin names
1808  for( auto& pinPair : aCadstarSymbol.PinNames )
1809  {
1810  SYMPINNAME_LABEL pin = pinPair.second;
1811  replacePinNumber( termNumMap.at( pin.TerminalID ), pin.NameOrLabel );
1812  }
1813 
1814  symbol->UpdatePins();
1815  }
1816 
1817  kiSheet->GetScreen()->Append( symbol );
1818 
1819  return symbol;
1820 }
1821 
1822 
1824  const ATTRIBUTE_LOCATION& aCadstarAttrLoc, const double& aComponentOrientationDeciDeg,
1825  bool aIsMirrored, SCH_FIELD* aKiCadField )
1826 {
1827  aKiCadField->SetPosition( getKiCadPoint( aCadstarAttrLoc.Position ) );
1828  aKiCadField->SetVisible( true );
1829 
1830  ALIGNMENT alignment = aCadstarAttrLoc.Alignment;
1831 
1832  double textAngle = getAngleTenthDegree( aCadstarAttrLoc.OrientAngle );
1833  long long cadstarAngle = getCadstarAngle( textAngle - aComponentOrientationDeciDeg );
1834 
1835  if( aIsMirrored )
1836  {
1837  // We need to change the aligment when the symbol is mirrored based on the text orientation
1838  // To ensure the anchor point is the same in KiCad.
1839 
1840  int textIsVertical = KiROUND( textAngle / 900.0 ) % 2;
1841 
1842  if( textIsVertical )
1843  alignment = rotate180( alignment );
1844 
1845  alignment = mirrorX( alignment );
1846  }
1847 
1848  applyTextSettings( aKiCadField,
1849  aCadstarAttrLoc.TextCodeID,
1850  alignment,
1851  aCadstarAttrLoc.Justification,
1852  cadstarAngle,
1853  aCadstarAttrLoc.Mirror );
1854 }
1855 
1856 
1858  double aOrientAngleDeciDeg, double& aReturnedOrientationDeciDeg )
1859 {
1860  int compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_0;
1861 
1862  int oDeg = (int) NormalizeAngle180( aOrientAngleDeciDeg );
1863 
1864  if( oDeg >= -450 && oDeg <= 450 )
1865  {
1866  compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_0;
1867  aReturnedOrientationDeciDeg = 0.0;
1868  }
1869  else if( oDeg >= 450 && oDeg <= 1350 )
1870  {
1871  compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_90;
1872  aReturnedOrientationDeciDeg = 900.0;
1873  }
1874  else if( oDeg >= 1350 || oDeg <= -1350 )
1875  {
1876  compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_180;
1877  aReturnedOrientationDeciDeg = 1800.0;
1878  }
1879  else
1880  {
1881  compOrientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_270;
1882  aReturnedOrientationDeciDeg = 2700.0;
1883  }
1884 
1885  return compOrientation;
1886 }
1887 
1888 
1890  const NET_SCH& aNet, const NETELEMENT_ID& aNetElementID )
1891 {
1892  // clang-format off
1893  auto logUnknownNetElementError =
1894  [&]()
1895  {
1896  m_reporter->Report( wxString::Format( _( "Net %s references unknown net element %s. "
1897  "The net was not properly loaded and may "
1898  "require manual fixing." ),
1899  getNetName( aNet ),
1900  aNetElementID ),
1902 
1903  return POINT();
1904  };
1905  // clang-format on
1906 
1907  if( aNetElementID.Contains( wxT( "J" ) ) ) // Junction
1908  {
1909  if( aNet.Junctions.find( aNetElementID ) == aNet.Junctions.end() )
1910  return logUnknownNetElementError();
1911 
1912  return aNet.Junctions.at( aNetElementID ).Location;
1913  }
1914  else if( aNetElementID.Contains( wxT( "P" ) ) ) // Terminal/Pin of a symbol
1915  {
1916  if( aNet.Terminals.find( aNetElementID ) == aNet.Terminals.end() )
1917  return logUnknownNetElementError();
1918 
1919  SYMBOL_ID symid = aNet.Terminals.at( aNetElementID ).SymbolID;
1920  TERMINAL_ID termid = aNet.Terminals.at( aNetElementID ).TerminalID;
1921 
1922  if( Schematic.Symbols.find( symid ) == Schematic.Symbols.end() )
1923  return logUnknownNetElementError();
1924 
1925  SYMBOL sym = Schematic.Symbols.at( symid );
1926  SYMDEF_ID symdefid = sym.SymdefID;
1927  wxPoint symbolOrigin = sym.Origin;
1928 
1929  if( Library.SymbolDefinitions.find( symdefid ) == Library.SymbolDefinitions.end() )
1930  return logUnknownNetElementError();
1931 
1932  wxPoint libpinPosition =
1933  Library.SymbolDefinitions.at( symdefid ).Terminals.at( termid ).Position;
1934  wxPoint libOrigin = Library.SymbolDefinitions.at( symdefid ).Origin;
1935 
1936  wxPoint pinOffset = libpinPosition - libOrigin;
1937  pinOffset.x = ( pinOffset.x * sym.ScaleRatioNumerator ) / sym.ScaleRatioDenominator;
1938  pinOffset.y = ( pinOffset.y * sym.ScaleRatioNumerator ) / sym.ScaleRatioDenominator;
1939 
1940  wxPoint pinPosition = symbolOrigin + pinOffset;
1941 
1942  double compAngleDeciDeg = getAngleTenthDegree( sym.OrientAngle );
1943 
1944  if( sym.Mirror )
1945  pinPosition.x = ( 2 * symbolOrigin.x ) - pinPosition.x;
1946 
1947  double adjustedOrientationDecideg;
1948  getComponentOrientation( compAngleDeciDeg, adjustedOrientationDecideg );
1949 
1950  RotatePoint( &pinPosition, symbolOrigin, -adjustedOrientationDecideg );
1951 
1952  POINT retval;
1953  retval.x = pinPosition.x;
1954  retval.y = pinPosition.y;
1955 
1956  return retval;
1957  }
1958  else if( aNetElementID.Contains( wxT( "BT" ) ) ) // Bus Terminal
1959  {
1960  if( aNet.BusTerminals.find( aNetElementID ) == aNet.BusTerminals.end() )
1961  return logUnknownNetElementError();
1962 
1963  return aNet.BusTerminals.at( aNetElementID ).SecondPoint;
1964  }
1965  else if( aNetElementID.Contains( wxT( "BLKT" ) ) ) // Block Terminal (sheet hierarchy connection)
1966  {
1967  if( aNet.BlockTerminals.find( aNetElementID ) == aNet.BlockTerminals.end() )
1968  return logUnknownNetElementError();
1969 
1970  BLOCK_ID blockid = aNet.BlockTerminals.at( aNetElementID ).BlockID;
1971  TERMINAL_ID termid = aNet.BlockTerminals.at( aNetElementID ).TerminalID;
1972 
1973  if( Schematic.Blocks.find( blockid ) == Schematic.Blocks.end() )
1974  return logUnknownNetElementError();
1975 
1976  return Schematic.Blocks.at( blockid ).Terminals.at( termid ).Position;
1977  }
1978  else if( aNetElementID.Contains( wxT( "D" ) ) ) // Dangler
1979  {
1980  if( aNet.Danglers.find( aNetElementID ) == aNet.Danglers.end() )
1981  return logUnknownNetElementError();
1982 
1983  return aNet.Danglers.at( aNetElementID ).Position;
1984  }
1985  else
1986  {
1987  return logUnknownNetElementError();
1988  }
1989 
1990  return POINT();
1991 }
1992 
1993 
1995 {
1996  wxString netname = aNet.Name;
1997 
1998  if( netname.IsEmpty() )
1999  netname = wxString::Format( wxT( "$%ld" ), aNet.SignalNum );
2000 
2001  return netname;
2002 }
2003 
2004 
2006  const wxPoint& aEndPoint, const LINECODE_ID& aCadstarLineCodeID,
2007  const LAYER_ID& aCadstarSheetID, const SCH_LAYER_ID& aKiCadSchLayerID,
2008  const wxPoint& aMoveVector, const double& aRotationAngleDeciDeg,
2009  const double& aScalingFactor, const wxPoint& aTransformCentre, const bool& aMirrorInvert )
2010 {
2011  SCH_LINE* segment = new SCH_LINE();
2012 
2013  segment->SetLayer( aKiCadSchLayerID );
2014  segment->SetLineWidth( KiROUND( getLineThickness( aCadstarLineCodeID ) * aScalingFactor ) );
2015  segment->SetLineStyle( getLineStyle( aCadstarLineCodeID ) );
2016 
2017  //Apply transforms
2018  wxPoint startPoint = applyTransform( aStartPoint, aMoveVector, aRotationAngleDeciDeg,
2019  aScalingFactor, aTransformCentre, aMirrorInvert );
2020  wxPoint endPoint = applyTransform( aEndPoint, aMoveVector, aRotationAngleDeciDeg,
2021  aScalingFactor, aTransformCentre, aMirrorInvert );
2022 
2023  segment->SetStartPoint( startPoint );
2024  segment->SetEndPoint( endPoint );
2025 
2026  loadItemOntoKiCadSheet( aCadstarSheetID, segment );
2027 }
2028 
2029 
2030 void CADSTAR_SCH_ARCHIVE_LOADER::loadShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
2031  LINECODE_ID aCadstarLineCodeID, LAYER_ID aCadstarSheetID, SCH_LAYER_ID aKiCadSchLayerID,
2032  const wxPoint& aMoveVector, const double& aRotationAngleDeciDeg,
2033  const double& aScalingFactor, const wxPoint& aTransformCentre, const bool& aMirrorInvert )
2034 {
2035  const VERTEX* prev = &aCadstarVertices.at( 0 );
2036  const VERTEX* cur;
2037 
2038  wxASSERT_MSG(
2039  prev->Type == VERTEX_TYPE::POINT, wxT( "First vertex should always be a point vertex" ) );
2040 
2041  for( size_t ii = 1; ii < aCadstarVertices.size(); ii++ )
2042  {
2043  cur = &aCadstarVertices.at( ii );
2044 
2045  wxPoint startPoint = getKiCadPoint( prev->End );
2046  wxPoint endPoint = getKiCadPoint( cur->End );
2047  wxPoint centerPoint = getKiCadPoint( cur->Center );
2048  bool cw = false;
2049 
2052  {
2053  centerPoint = ( startPoint + endPoint ) / 2;
2054  }
2055 
2056  switch( cur->Type )
2057  {
2060  cw = true;
2064  {
2065  double arcStartAngle = getPolarAngle( startPoint - centerPoint );
2066  double arcEndAngle = getPolarAngle( endPoint - centerPoint );
2067  double arcAngleDeciDeg = arcEndAngle - arcStartAngle;
2068 
2069  if( cw )
2070  arcAngleDeciDeg = NormalizeAnglePos( arcAngleDeciDeg );
2071  else
2072  arcAngleDeciDeg = NormalizeAngleNeg( arcAngleDeciDeg );
2073 
2074  SHAPE_ARC tempArc( centerPoint, startPoint, arcAngleDeciDeg / 10.0 );
2075  SHAPE_LINE_CHAIN arcSegments = tempArc.ConvertToPolyline( Millimeter2iu( 0.1 ) );
2076 
2077  // Load the arc as a series of piece-wise segments
2078 
2079  for( int jj = 0; jj < arcSegments.SegmentCount(); jj++ )
2080  {
2081  wxPoint segStart = (wxPoint) arcSegments.Segment( jj ).A;
2082  wxPoint segEnd = (wxPoint) arcSegments.Segment( jj ).B;
2083 
2084  loadGraphicStaightSegment( segStart, segEnd, aCadstarLineCodeID, aCadstarSheetID,
2085  aKiCadSchLayerID, aMoveVector, aRotationAngleDeciDeg,
2086  aScalingFactor, aTransformCentre, aMirrorInvert );
2087  }
2088  }
2089  break;
2090 
2091  case VERTEX_TYPE::POINT:
2092  loadGraphicStaightSegment( startPoint, endPoint, aCadstarLineCodeID, aCadstarSheetID,
2093  aKiCadSchLayerID, aMoveVector, aRotationAngleDeciDeg,
2094  aScalingFactor, aTransformCentre, aMirrorInvert );
2095  break;
2096 
2097  default:
2098  wxFAIL_MSG( wxT( "Unknown CADSTAR Vertex type" ) );
2099  }
2100 
2101 
2102  prev = cur;
2103  }
2104 }
2105 
2106 
2108  const LAYER_ID& aCadstarSheetIDOverride, SCH_LAYER_ID aKiCadSchLayerID,
2109  const wxPoint& aMoveVector, const double& aRotationAngleDeciDeg,
2110  const double& aScalingFactor, const wxPoint& aTransformCentre, const bool& aMirrorInvert )
2111 {
2112  loadShapeVertices( aCadstarFigure.Shape.Vertices, aCadstarFigure.LineCodeID,
2113  aCadstarSheetIDOverride, aKiCadSchLayerID, aMoveVector,
2114  aRotationAngleDeciDeg, aScalingFactor, aTransformCentre, aMirrorInvert );
2115 
2116  for( CUTOUT cutout : aCadstarFigure.Shape.Cutouts )
2117  {
2118  loadShapeVertices( cutout.Vertices, aCadstarFigure.LineCodeID, aCadstarSheetIDOverride,
2119  aKiCadSchLayerID, aMoveVector, aRotationAngleDeciDeg, aScalingFactor,
2120  aTransformCentre, aMirrorInvert );
2121  }
2122 }
2123 
2124 
2126  LAYER_ID aCadstarSheetID, const wxPoint& aPosition, wxSize aSheetSize,
2127  const SCH_SHEET_PATH& aParentSheet )
2128 {
2129  wxCHECK_MSG( m_sheetMap.find( aCadstarSheetID ) == m_sheetMap.end(), ,
2130  wxT( "Sheet already loaded!" ) );
2131 
2132  SCH_SHEET* sheet = new SCH_SHEET( aParentSheet.Last(), aPosition );
2133  SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
2134  SCH_SHEET_PATH instance( aParentSheet );
2135 
2136  sheet->SetSize( aSheetSize );
2137  sheet->SetScreen( screen );
2138 
2139  wxString name = Sheets.SheetNames.at( aCadstarSheetID );
2140 
2141  SCH_FIELD& sheetNameField = sheet->GetFields()[SHEETNAME];
2142  SCH_FIELD& filenameField = sheet->GetFields()[SHEETFILENAME];
2143 
2144  sheetNameField.SetText( name );
2145 
2146  int sheetNum = getSheetNumber( aCadstarSheetID );
2147  wxString loadedFilename = wxFileName( Filename ).GetName();
2148  std::string filename = wxString::Format( wxT( "%s_%02d" ), loadedFilename, sheetNum ).ToStdString();
2149 
2150  ReplaceIllegalFileNameChars( &filename );
2151  filename += wxT( "." ) + KiCadSchematicFileExtension;
2152 
2153  filenameField.SetText( filename );
2154 
2155  wxFileName fn( m_schematic->Prj().GetProjectPath() + filename );
2156  sheet->GetScreen()->SetFileName( fn.GetFullPath() );
2157  aParentSheet.Last()->GetScreen()->Append( sheet );
2158  instance.push_back( sheet );
2159  sheet->AddInstance( instance );
2160 
2161  wxString pageNumStr = wxString::Format( wxT( "%d" ), getSheetNumber( aCadstarSheetID ) );
2162  sheet->SetPageNumber( instance, pageNumStr );
2163 
2164  sheet->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
2165 
2166  m_sheetMap.insert( { aCadstarSheetID, sheet } );
2167 
2168  loadChildSheets( aCadstarSheetID, instance );
2169 }
2170 
2171 
2173  const SCH_SHEET_PATH& aSheet )
2174 {
2175  wxCHECK_MSG( m_sheetMap.find( aCadstarSheetID ) != m_sheetMap.end(), ,
2176  wxT( "FIXME! Parent sheet should be loaded before attempting to load subsheets" ) );
2177 
2178  for( std::pair<BLOCK_ID, BLOCK> blockPair : Schematic.Blocks )
2179  {
2180  BLOCK& block = blockPair.second;
2181 
2182  if( block.LayerID == aCadstarSheetID && block.Type == BLOCK::TYPE::CHILD )
2183  {
2184  if( block.AssocLayerID == wxT( "NO_LINK" ) )
2185  {
2186  if( block.Figures.size() > 0 )
2187  {
2188  m_reporter->Report( wxString::Format( _( "The block ID %s (Block name: '%s') "
2189  "is drawn on sheet '%s' but is not "
2190  "linked to another sheet in the "
2191  "design. KiCad requires all sheet "
2192  "symbols to be associated to a sheet, "
2193  "so the block was not loaded." ),
2194  block.ID, block.Name,
2195  Sheets.SheetNames.at( aCadstarSheetID ) ),
2197  }
2198 
2199  continue;
2200  }
2201 
2202  // In KiCad you can only draw rectangular shapes whereas in Cadstar arbitrary shapes
2203  // are allowed. We will calculate the extents of the Cadstar shape and draw a rectangle
2204 
2205  std::pair<wxPoint, wxSize> blockExtents;
2206 
2207  if( block.Figures.size() > 0 )
2208  {
2209  blockExtents = getFigureExtentsKiCad( block.Figures.begin()->second );
2210  }
2211  else
2212  {
2213  THROW_IO_ERROR( wxString::Format( _( "The CADSTAR schematic might be corrupt: "
2214  "Block %s references a child sheet but has no "
2215  "Figure defined." ),
2216  block.ID ) );
2217  }
2218 
2219  loadSheetAndChildSheets( block.AssocLayerID, blockExtents.first, blockExtents.second,
2220  aSheet );
2221 
2222  // Hide all KiCad sheet properties (sheet name/filename is not applicable in CADSTAR)
2223  SCH_SHEET* loadedSheet = m_sheetMap.at( block.AssocLayerID );
2224  SCH_FIELDS fields = loadedSheet->GetFields();
2225 
2226  for( SCH_FIELD& field : fields )
2227  {
2228  field.SetVisible( false );
2229  }
2230 
2231  if( block.HasBlockLabel )
2232  {
2233  //@todo use below code when KiCad supports multi-line fields
2234  /*
2235  // Add the block label as a separate field
2236  SCH_FIELD blockNameField( getKiCadPoint( block.BlockLabel.Position ), 2,
2237  loadedSheet, wxString( wxT( "Block name" ) ) );
2238  blockNameField.SetText( block.Name );
2239  blockNameField.SetVisible( true );
2240 
2241  applyTextSettings( &blockNameField,
2242  block.BlockLabel.TextCodeID,
2243  block.BlockLabel.Alignment,
2244  block.BlockLabel.Justification,
2245  block.BlockLabel.OrientAngle,
2246  block.BlockLabel.Mirror );
2247 
2248  fields.push_back( blockNameField );*/
2249 
2250  // For now as as a text item (supports multi-line properly)
2251  SCH_TEXT* kiTxt = new SCH_TEXT();
2252 
2253  kiTxt->SetParent( m_schematic );
2254  kiTxt->SetPosition( getKiCadPoint( block.BlockLabel.Position ) );
2255  kiTxt->SetText( block.Name );
2256 
2257  applyTextSettings( kiTxt,
2258  block.BlockLabel.TextCodeID,
2259  block.BlockLabel.Alignment,
2260  block.BlockLabel.Justification,
2261  block.BlockLabel.OrientAngle,
2262  block.BlockLabel.Mirror );
2263 
2264  loadItemOntoKiCadSheet( aCadstarSheetID, kiTxt );
2265  }
2266 
2267  loadedSheet->SetFields( fields );
2268  }
2269  }
2270 }
2271 
2272 
2273 std::vector<CADSTAR_SCH_ARCHIVE_LOADER::LAYER_ID> CADSTAR_SCH_ARCHIVE_LOADER::findOrphanSheets()
2274 {
2275  std::vector<LAYER_ID> childSheets, orphanSheets;
2276 
2277  //Find all sheets that are child of another
2278  for( std::pair<BLOCK_ID, BLOCK> blockPair : Schematic.Blocks )
2279  {
2280  BLOCK& block = blockPair.second;
2281  LAYER_ID& assocSheetID = block.AssocLayerID;
2282 
2283  if( block.Type == BLOCK::TYPE::CHILD )
2284  childSheets.push_back( assocSheetID );
2285  }
2286 
2287  //Add sheets that do not have a parent
2288  for( LAYER_ID sheetID : Sheets.SheetOrder )
2289  {
2290  if( std::find( childSheets.begin(), childSheets.end(), sheetID ) == childSheets.end() )
2291  orphanSheets.push_back( sheetID );
2292  }
2293 
2294  return orphanSheets;
2295 }
2296 
2297 
2299 {
2300  int i = 1;
2301 
2302  for( LAYER_ID sheetID : Sheets.SheetOrder )
2303  {
2304  if( sheetID == aCadstarSheetID )
2305  return i;
2306 
2307  ++i;
2308  }
2309 
2310  return -1;
2311 }
2312 
2313 
2315 {
2316  wxCHECK_MSG( aItem, /*void*/, wxT( "aItem is null" ) );
2317 
2318  if( aCadstarSheetID == wxT( "ALL_SHEETS" ) )
2319  {
2320  SCH_ITEM* duplicateItem;
2321 
2322  for( std::pair<LAYER_ID, SHEET_NAME> sheetPair : Sheets.SheetNames )
2323  {
2324  LAYER_ID sheetID = sheetPair.first;
2325  duplicateItem = aItem->Duplicate();
2326  m_sheetMap.at( sheetID )->GetScreen()->Append( aItem->Duplicate() );
2327  }
2328 
2329  //Get rid of the extra copy:
2330  delete aItem;
2331  aItem = duplicateItem;
2332  }
2333  else if( aCadstarSheetID == wxT( "NO_SHEET" ) )
2334  {
2335  wxASSERT_MSG(
2336  false, wxT( "Trying to add an item to NO_SHEET? This might be a documentation symbol." ) );
2337  }
2338  else
2339  {
2340  if( m_sheetMap.find( aCadstarSheetID ) != m_sheetMap.end() )
2341  {
2342  m_sheetMap.at( aCadstarSheetID )->GetScreen()->Append( aItem );
2343  }
2344  else
2345  {
2346  delete aItem;
2347  wxASSERT_MSG( false, wxT( "Unknown Sheet ID." ) );
2348  }
2349  }
2350 }
2351 
2352 
2354  const wxString& aSymdefName, const wxString& aSymDefAlternate )
2355 {
2356  // Do a case-insensitive comparison
2357  for( std::pair<SYMDEF_ID, SYMDEF_SCM> symPair : Library.SymbolDefinitions )
2358  {
2359  SYMDEF_ID id = symPair.first;
2360  SYMDEF_SCM symdef = symPair.second;
2361 
2362  if( symdef.ReferenceName.Lower() == aSymdefName.Lower()
2363  && symdef.Alternate.Lower() == aSymDefAlternate.Lower() )
2364  {
2365  return id;
2366  }
2367  }
2368 
2369  return SYMDEF_ID();
2370 }
2371 
2372 
2374 {
2375  // Use CADSTAR visibility settings to determine if an attribute is visible
2376  if( AttrColors.AttributeColors.find( aCadstarAttributeID ) != AttrColors.AttributeColors.end() )
2377  {
2378  return AttrColors.AttributeColors.at( aCadstarAttributeID ).IsVisible;
2379  }
2380 
2381  return false; // If there is no visibility setting, assume not displayed
2382 }
2383 
2384 
2386 {
2387  wxCHECK( Assignments.Codedefs.LineCodes.find( aCadstarLineCodeID )
2388  != Assignments.Codedefs.LineCodes.end(),
2389  Mils2iu( DEFAULT_WIRE_WIDTH_MILS ) );
2390 
2391  return getKiCadLength( Assignments.Codedefs.LineCodes.at( aCadstarLineCodeID ).Width );
2392 }
2393 
2394 
2396 {
2397  wxCHECK( Assignments.Codedefs.LineCodes.find( aCadstarLineCodeID )
2398  != Assignments.Codedefs.LineCodes.end(),
2400 
2401  // clang-format off
2402  switch( Assignments.Codedefs.LineCodes.at( aCadstarLineCodeID ).Style )
2403  {
2406  case LINESTYLE::DASHDOTDOT: return PLOT_DASH_TYPE::DASHDOT; //TODO: update in future
2407  case LINESTYLE::DOT: return PLOT_DASH_TYPE::DOT;
2409  default: return PLOT_DASH_TYPE::DEFAULT;
2410  }
2411  // clang-format on
2412 
2413  return PLOT_DASH_TYPE();
2414 }
2415 
2416 
2418  const TEXTCODE_ID& aCadstarTextCodeID )
2419 {
2420  wxCHECK( Assignments.Codedefs.TextCodes.find( aCadstarTextCodeID )
2421  != Assignments.Codedefs.TextCodes.end(),
2422  TEXTCODE() );
2423 
2424  return Assignments.Codedefs.TextCodes.at( aCadstarTextCodeID );
2425 }
2426 
2427 
2429 {
2430  TEXTCODE txtCode = getTextCode( aCadstarTextCodeID );
2431 
2432  return KiROUND( (double) getKiCadLength( txtCode.Height ) * TXT_HEIGHT_RATIO );
2433 }
2434 
2435 
2436 wxString CADSTAR_SCH_ARCHIVE_LOADER::getAttributeName( const ATTRIBUTE_ID& aCadstarAttributeID )
2437 {
2438  wxCHECK( Assignments.Codedefs.AttributeNames.find( aCadstarAttributeID )
2440  wxEmptyString );
2441 
2442  return Assignments.Codedefs.AttributeNames.at( aCadstarAttributeID ).Name;
2443 }
2444 
2445 
2447  const PART_ID& aCadstarPartID )
2448 {
2449  wxCHECK( Parts.PartDefinitions.find( aCadstarPartID ) != Parts.PartDefinitions.end(), PART() );
2450 
2451  return Parts.PartDefinitions.at( aCadstarPartID );
2452 }
2453 
2454 
2456  const ROUTECODE_ID& aCadstarRouteCodeID )
2457 {
2458  wxCHECK( Assignments.Codedefs.RouteCodes.find( aCadstarRouteCodeID )
2459  != Assignments.Codedefs.RouteCodes.end(),
2460  ROUTECODE() );
2461 
2462  return Assignments.Codedefs.RouteCodes.at( aCadstarRouteCodeID );
2463 }
2464 
2465 
2466 CADSTAR_SCH_ARCHIVE_LOADER::PART::DEFINITION::PIN CADSTAR_SCH_ARCHIVE_LOADER::getPartDefinitionPin(
2467  const PART& aCadstarPart, const GATE_ID& aGateID, const TERMINAL_ID& aTerminalID )
2468 {
2469  for( std::pair<PART_DEFINITION_PIN_ID, PART::DEFINITION::PIN> pinPair :
2470  aCadstarPart.Definition.Pins )
2471  {
2472  PART::DEFINITION::PIN partPin = pinPair.second;
2473 
2474  if( partPin.TerminalGate == aGateID && partPin.TerminalPin == aTerminalID )
2475  return partPin;
2476  }
2477 
2478  return PART::DEFINITION::PIN();
2479 }
2480 
2481 
2483 {
2484  switch( aPinType )
2485  {
2486  case PART::PIN_TYPE::UNCOMMITTED: return ELECTRICAL_PINTYPE::PT_PASSIVE;
2487  case PART::PIN_TYPE::INPUT: return ELECTRICAL_PINTYPE::PT_INPUT;
2488  case PART::PIN_TYPE::OUTPUT_OR: return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
2489  case PART::PIN_TYPE::OUTPUT_NOT_OR: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2490  case PART::PIN_TYPE::OUTPUT_NOT_NORM_OR: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2491  case PART::PIN_TYPE::POWER: return ELECTRICAL_PINTYPE::PT_POWER_IN;
2492  case PART::PIN_TYPE::GROUND: return ELECTRICAL_PINTYPE::PT_POWER_IN;
2493  case PART::PIN_TYPE::TRISTATE_BIDIR: return ELECTRICAL_PINTYPE::PT_BIDI;
2494  case PART::PIN_TYPE::TRISTATE_INPUT: return ELECTRICAL_PINTYPE::PT_INPUT;
2495  case PART::PIN_TYPE::TRISTATE_DRIVER: return ELECTRICAL_PINTYPE::PT_OUTPUT;
2496  }
2497 
2499 }
2500 
2502 {
2503  if( aCadstarGateID.IsEmpty() )
2504  return 1;
2505 
2506  return (int) aCadstarGateID.Upper().GetChar( 0 ) - (int) wxUniChar( 'A' ) + 1;
2507 }
2508 
2509 
2510 LABEL_SPIN_STYLE CADSTAR_SCH_ARCHIVE_LOADER::getSpinStyle( const long long& aCadstarOrientation,
2511  bool aMirror )
2512 {
2513  double orientationDeciDegree = getAngleTenthDegree( aCadstarOrientation );
2514  LABEL_SPIN_STYLE spinStyle = getSpinStyleDeciDeg( orientationDeciDegree );
2515 
2516  if( aMirror )
2517  {
2518  spinStyle = spinStyle.RotateCCW();
2519  spinStyle = spinStyle.RotateCCW();
2520  }
2521 
2522  return spinStyle;
2523 }
2524 
2525 
2527  const double& aOrientationDeciDeg )
2528 {
2530 
2531  int oDeg = (int) NormalizeAngle180( aOrientationDeciDeg );
2532 
2533  if( oDeg >= -450 && oDeg <= 450 )
2534  spinStyle = LABEL_SPIN_STYLE::RIGHT; // 0deg
2535  else if( oDeg >= 450 && oDeg <= 1350 )
2536  spinStyle = LABEL_SPIN_STYLE::UP; // 90deg
2537  else if( oDeg >= 1350 || oDeg <= -1350 )
2538  spinStyle = LABEL_SPIN_STYLE::LEFT; // 180deg
2539  else
2540  spinStyle = LABEL_SPIN_STYLE::BOTTOM; // 270deg
2541 
2542  return spinStyle;
2543 }
2544 
2545 
2548 {
2549  switch( aCadstarAlignment )
2550  {
2551  // Change left to right:
2556 
2557  //Change right to left:
2561 
2562  // Center alignment does not mirror:
2565  case ALIGNMENT::TOPCENTER: return aCadstarAlignment;
2566 
2567  // Shouldn't be here
2568  default: wxFAIL_MSG( wxT( "Unknown Cadstar Alignment" ) ); return aCadstarAlignment;
2569  }
2570 }
2571 
2572 
2575 {
2576  switch( aCadstarAlignment )
2577  {
2588 
2589  // Shouldn't be here
2590  default: wxFAIL_MSG( wxT( "Unknown Cadstar Alignment" ) ); return aCadstarAlignment;
2591  }
2592 }
2593 
2594 
2596  const TEXTCODE_ID& aCadstarTextCodeID,
2597  const ALIGNMENT& aCadstarAlignment,
2598  const JUSTIFICATION& aCadstarJustification,
2599  const long long aCadstarOrientAngle,
2600  bool aMirrored )
2601 {
2602  // Justification ignored for now as not supported in Eeschema, but leaving this code in
2603  // place for future upgrades.
2604  // TODO update this when Eeschema supports justification independent of anchor position.
2605 
2606  TEXTCODE textCode = getTextCode( aCadstarTextCodeID );
2607  int textHeight = KiROUND( (double) getKiCadLength( textCode.Height ) * TXT_HEIGHT_RATIO );
2608  int textWidth = getKiCadLength( textCode.Width );
2609 
2610  // Ensure we have no Cadstar overbar characters
2611  wxString escapedText = HandleTextOverbar( aKiCadTextItem->GetText() );
2612  aKiCadTextItem->SetText( escapedText );
2613 
2614  // The width is zero for all non-cadstar fonts. Using a width equal to 2/3 the height seems
2615  // to work well for most fonts.
2616  if( textWidth == 0 )
2617  textWidth = getKiCadLength( 2 * textCode.Height / 3 );
2618 
2619  aKiCadTextItem->SetTextWidth( textWidth );
2620  aKiCadTextItem->SetTextHeight( textHeight );
2621  aKiCadTextItem->SetTextThickness( getKiCadLength( textCode.LineWidth ) );
2622  aKiCadTextItem->SetTextAngle( getAngleTenthDegree( aCadstarOrientAngle ) );
2623  aKiCadTextItem->SetBold( textCode.Font.Modifier1 == FONT_BOLD );
2624  aKiCadTextItem->SetItalic( textCode.Font.Italic );
2625 
2626  ALIGNMENT textAlignment = aCadstarAlignment;
2627 
2628  // KiCad mirrors the justification and alignment when the symbol is mirrored but CADSTAR
2629  // specifies it post-mirroring. In contrast, if the text item itself is mirrored (not
2630  // supported in KiCad), CADSTAR specifies the alignment and justification pre-mirroring
2631  if( aMirrored )
2632  textAlignment = mirrorX( aCadstarAlignment );
2633 
2634  auto setAlignment = [&]( EDA_TEXT* aText, ALIGNMENT aAlignment )
2635  {
2636  switch( aAlignment )
2637  {
2638  case ALIGNMENT::NO_ALIGNMENT: // Bottom left of the first line
2639  //No exact KiCad equivalent, so lets move the position of the text
2640  FixTextPositionNoAlignment( aText );
2642  case ALIGNMENT::BOTTOMLEFT:
2645  break;
2646 
2650  break;
2651 
2655  break;
2656 
2657  case ALIGNMENT::CENTERLEFT:
2660  break;
2661 
2665  break;
2666 
2670  break;
2671 
2672  case ALIGNMENT::TOPLEFT:
2675  break;
2676 
2677  case ALIGNMENT::TOPCENTER:
2680  break;
2681 
2682  case ALIGNMENT::TOPRIGHT:
2685  break;
2686  }
2687  };
2688 
2689  LABEL_SPIN_STYLE spin = getSpinStyle( aCadstarOrientAngle, aMirrored );
2690  EDA_ITEM* textEdaItem = dynamic_cast<EDA_ITEM*>( aKiCadTextItem );
2691  wxCHECK( textEdaItem, /* void */ ); // ensure this is a EDA_ITEM
2692 
2693  switch( textEdaItem->Type() )
2694  {
2695  // Some KiCad schematic text items only permit a limited amount of angles
2696  // and text justifications
2697  case LIB_TEXT_T:
2698  case SCH_FIELD_T:
2699  case LIB_FIELD_T:
2700  {
2701  // Spin style not used. All text justifications are permitted. However, only orientations
2702  // of 0 deg or 90 deg are supported
2703  double angleDeciDeg = NormalizeAnglePos( aKiCadTextItem->GetTextAngle() );
2704  int quadrant = KiROUND( angleDeciDeg / 900.0 );
2705  quadrant %= 4;
2706 
2707  switch( quadrant )
2708  {
2709  case 0:
2710  angleDeciDeg = 0;
2711  break;
2712  case 1:
2713  angleDeciDeg = 900;
2714  break;
2715  case 2:
2716  angleDeciDeg = 0;
2717  textAlignment = rotate180( textAlignment );
2718  break;
2719  case 3:
2720  angleDeciDeg = 900;
2721  textAlignment = rotate180( textAlignment );
2722  break;
2723  default: wxFAIL_MSG( wxT( "Unknown Quadrant" ) );
2724  }
2725 
2726  aKiCadTextItem->SetTextAngle( angleDeciDeg );
2727  setAlignment( aKiCadTextItem, textAlignment );
2728  }
2729  return;
2730 
2731  case SCH_TEXT_T:
2732  {
2733  // Note spin style in a SCH_TEXT results in a vertical alignment GR_TEXT_VJUSTIFY_BOTTOM
2734  // so need to adjust the location of the text element based on Cadstar's original text
2735  // alignment (anchor position).
2736  setAlignment( aKiCadTextItem, textAlignment );
2737  EDA_RECT bb = textEdaItem->GetBoundingBox();
2738  int off = static_cast<SCH_TEXT*>( aKiCadTextItem )->GetTextOffset();
2739  wxPoint pos;
2740 
2741  // Change the anchor point of the text item to make it match the same bounding box
2742  // And correct the error introduced by the text offsetting in KiCad
2743  switch( spin )
2744  {
2745  case LABEL_SPIN_STYLE::BOTTOM: pos = { bb.GetRight() - off, bb.GetTop() }; break;
2746  case LABEL_SPIN_STYLE::UP: pos = { bb.GetRight() - off, bb.GetBottom() }; break;
2747  case LABEL_SPIN_STYLE::LEFT: pos = { bb.GetRight() , bb.GetBottom() + off }; break;
2748  case LABEL_SPIN_STYLE::RIGHT: pos = { bb.GetLeft() , bb.GetBottom() + off }; break;
2749  }
2750 
2751  aKiCadTextItem->SetTextPos( pos );
2752  }
2754 
2755  // We don't want to change position of net labels as that would break connectivity
2756  case SCH_LABEL_T:
2757  case SCH_GLOBAL_LABEL_T:
2758  case SCH_HIER_LABEL_T:
2759  case SCH_SHEET_PIN_T:
2760  static_cast<SCH_TEXT*>( aKiCadTextItem )->SetLabelSpinStyle( spin );
2761  return;
2762 
2763  default:
2764  wxFAIL_MSG( wxT( "Unexpected item type" ) );
2765  return;
2766  }
2767 }
2768 
2769 
2771 {
2772  SCH_TEXT* kiTxt = new SCH_TEXT();
2773 
2774  kiTxt->SetParent( m_schematic ); // set to the schematic for now to avoid asserts
2775  kiTxt->SetPosition( getKiCadPoint( aCadstarTextElement.Position ) );
2776  kiTxt->SetText( aCadstarTextElement.Text );
2777 
2778  applyTextSettings( kiTxt,
2779  aCadstarTextElement.TextCodeID,
2780  aCadstarTextElement.Alignment,
2781  aCadstarTextElement.Justification,
2782  aCadstarTextElement.OrientAngle,
2783  aCadstarTextElement.Mirror );
2784 
2785  return kiTxt;
2786 }
2787 
2788 
2790  long long aScalingFactorNumerator,
2791  long long aScalingFactorDenominator )
2792 {
2793  LIB_SYMBOL* retval = new LIB_SYMBOL( *aSymbol );
2794 
2795  if( aScalingFactorNumerator == aScalingFactorDenominator )
2796  return retval; // 1:1 scale, nothing to do
2797 
2798  auto scaleLen =
2799  [&]( int aLength ) -> int
2800  {
2801  return( aLength * aScalingFactorNumerator ) / aScalingFactorDenominator;
2802  };
2803 
2804  auto scalePt =
2805  [&]( wxPoint aCoord ) -> wxPoint
2806  {
2807  return wxPoint( scaleLen( aCoord.x ), scaleLen( aCoord.y ) );
2808  };
2809 
2810  auto scaleSize =
2811  [&]( wxSize aSize ) -> wxSize
2812  {
2813  return wxSize( scaleLen( aSize.x ), scaleLen( aSize.y ) );
2814  };
2815 
2816  LIB_ITEMS_CONTAINER& items = retval->GetDrawItems();
2817 
2818  for( LIB_ITEM& item : items )
2819  {
2820  switch( item.Type() )
2821  {
2822  case KICAD_T::LIB_SHAPE_T:
2823  {
2824  LIB_SHAPE& shape = static_cast<LIB_SHAPE&>( item );
2825 
2826  if( shape.GetShape() == SHAPE_T::ARC )
2827  {
2828  shape.SetPosition( scalePt( shape.GetPosition() ) );
2829  shape.SetStart( scalePt( shape.GetStart() ) );
2830  shape.SetEnd( scalePt( shape.GetEnd() ) );
2831  }
2832  else if( shape.GetShape() == SHAPE_T::POLY )
2833  {
2834  SHAPE_LINE_CHAIN& poly = shape.GetPolyShape().Outline( 0 );
2835 
2836  for( size_t ii = 0; ii < poly.GetPointCount(); ++ii )
2837  poly.SetPoint( ii, scalePt( (wxPoint) poly.CPoint( ii ) ) );
2838  }
2839  }
2840  break;
2841 
2842  case KICAD_T::LIB_PIN_T:
2843  {
2844  LIB_PIN& pin = static_cast<LIB_PIN&>( item );
2845 
2846  pin.SetPosition( scalePt( pin.GetPosition() ) );
2847  pin.SetLength( scaleLen( pin.GetLength() ) );
2848  }
2849  break;
2850 
2851  case KICAD_T::LIB_TEXT_T:
2852  {
2853  LIB_TEXT& txt = static_cast<LIB_TEXT&>( item );
2854 
2855  txt.SetPosition( scalePt( txt.GetPosition() ) );
2856  txt.SetTextSize( scaleSize( txt.GetTextSize() ) );
2857  }
2858  break;
2859 
2860  default:
2861  break;
2862  }
2863 
2864  }
2865 
2866  return retval;
2867 }
2868 
2869 
2870 void CADSTAR_SCH_ARCHIVE_LOADER::fixUpLibraryPins( LIB_SYMBOL* aSymbolToFix, int aGateNumber )
2871 {
2872  auto compLambda = []( const VECTOR2I& aA, const VECTOR2I& aB )
2873  {
2874  return LexicographicalCompare( aA, aB ) < 0;
2875  };
2876 
2877  // Store a list of vertical or horizontal segments in the symbol
2878  // Note: Need the custom comparison function to ensure the map is sorted correctly
2879  std::map<VECTOR2I, SHAPE_LINE_CHAIN, decltype( compLambda )> uniqueSegments( compLambda );
2880 
2881  LIB_ITEMS_CONTAINER::ITERATOR shapeIt = aSymbolToFix->GetDrawItems().begin( LIB_SHAPE_T );
2882 
2883  for( ; shapeIt != aSymbolToFix->GetDrawItems().end( LIB_SHAPE_T ); ++shapeIt )
2884  {
2885  LIB_SHAPE& shape = static_cast<LIB_SHAPE&>( *shapeIt );
2886 
2887  if( aGateNumber > 0 && shape.GetUnit() != aGateNumber )
2888  continue;
2889 
2890  if( shape.GetShape() != SHAPE_T::POLY )
2891  continue;
2892 
2893  SHAPE_LINE_CHAIN poly = shape.GetPolyShape().Outline( 0 );
2894 
2895  if( poly.GetPointCount() == 2 )
2896  {
2897  VECTOR2I pt0 = poly.CPoint( 0 );
2898  VECTOR2I pt1 = poly.CPoint( 1 );
2899 
2900  if( pt0 != pt1 && uniqueSegments.count( pt0 ) == 0 && uniqueSegments.count( pt1 ) == 0 )
2901  {
2902  // we are only interested in vertical or horizontal segments
2903  if( pt0.x == pt1.x || pt0.y == pt1.y )
2904  {
2905  uniqueSegments.insert( { pt0, poly } );
2906  uniqueSegments.insert( { pt1, poly } );
2907  }
2908  }
2909  }
2910  }
2911 
2912  LIB_PINS pins;
2913  aSymbolToFix->GetPins( pins, aGateNumber );
2914 
2915  for( auto& pin : pins )
2916  {
2917  auto setPinOrientation =
2918  [&]( double aAngleRad )
2919  {
2920  int oDeg = (int) NormalizeAngle180( RAD2DEG( aAngleRad ) );
2921 
2922  if( oDeg >= -45 && oDeg <= 45 )
2923  pin->SetOrientation( 'R' ); // 0 degrees
2924  else if( oDeg >= 45 && oDeg <= 135 )
2925  pin->SetOrientation( 'U' ); // 90 degrees
2926  else if( oDeg >= 135 || oDeg <= -135 )
2927  pin->SetOrientation( 'L' ); // 180 degrees
2928  else
2929  pin->SetOrientation( 'D' ); // -90 degrees
2930  };
2931 
2932  if( uniqueSegments.count( pin->GetPosition() ) )
2933  {
2934  SHAPE_LINE_CHAIN& poly = uniqueSegments.at( pin->GetPosition() );
2935 
2936  VECTOR2I otherPt = poly.CPoint( 0 );
2937 
2938  if( otherPt == pin->GetPosition() )
2939  otherPt = poly.CPoint( 1 );
2940 
2941  VECTOR2I vec( otherPt - pin->GetPosition() );
2942 
2943  pin->SetLength( vec.EuclideanNorm() );
2944  setPinOrientation( vec.Angle() );
2945  }
2946  }
2947 }
2948 
2949 
2951  const FIGURE& aCadstarFigure )
2952 {
2953  wxPoint upperLeft( Assignments.Settings.DesignLimit.x, 0 );
2954  wxPoint lowerRight( 0, Assignments.Settings.DesignLimit.y );
2955 
2956  for( const VERTEX& v : aCadstarFigure.Shape.Vertices )
2957  {
2958  if( upperLeft.x > v.End.x )
2959  upperLeft.x = v.End.x;
2960 
2961  if( upperLeft.y < v.End.y )
2962  upperLeft.y = v.End.y;
2963 
2964  if( lowerRight.x < v.End.x )
2965  lowerRight.x = v.End.x;
2966 
2967  if( lowerRight.y > v.End.y )
2968  lowerRight.y = v.End.y;
2969  }
2970 
2971  for( CUTOUT cutout : aCadstarFigure.Shape.Cutouts )
2972  {
2973  for( const VERTEX& v : aCadstarFigure.Shape.Vertices )
2974  {
2975  if( upperLeft.x > v.End.x )
2976  upperLeft.x = v.End.x;
2977 
2978  if( upperLeft.y < v.End.y )
2979  upperLeft.y = v.End.y;
2980 
2981  if( lowerRight.x < v.End.x )
2982  lowerRight.x = v.End.x;
2983 
2984  if( lowerRight.y > v.End.y )
2985  lowerRight.y = v.End.y;
2986  }
2987  }
2988 
2989  wxPoint upperLeftKiCad = getKiCadPoint( upperLeft );
2990  wxPoint lowerRightKiCad = getKiCadPoint( lowerRight );
2991 
2992  wxPoint size = lowerRightKiCad - upperLeftKiCad;
2993 
2994  return { upperLeftKiCad, wxSize( abs( size.x ), abs( size.y ) ) };
2995 }
2996 
2997 
2998 wxPoint CADSTAR_SCH_ARCHIVE_LOADER::getKiCadPoint( const wxPoint& aCadstarPoint )
2999 {
3000  wxPoint retval;
3001 
3002  retval.x = getKiCadLength( aCadstarPoint.x - m_designCenter.x );
3003  retval.y = -getKiCadLength( aCadstarPoint.y - m_designCenter.y );
3004 
3005  return retval;
3006 }
3007 
3008 
3009 wxPoint CADSTAR_SCH_ARCHIVE_LOADER::getKiCadLibraryPoint( const wxPoint& aCadstarPoint,
3010  const wxPoint& aCadstarCentre )
3011 {
3012  wxPoint retval;
3013 
3014  retval.x = getKiCadLength( aCadstarPoint.x - aCadstarCentre.x );
3015  retval.y = getKiCadLength( aCadstarPoint.y - aCadstarCentre.y );
3016 
3017  return retval;
3018 }
3019 
3020 
3021 wxPoint CADSTAR_SCH_ARCHIVE_LOADER::applyTransform( const wxPoint& aPoint,
3022  const wxPoint& aMoveVector, const double& aRotationAngleDeciDeg,
3023  const double& aScalingFactor, const wxPoint& aTransformCentre, const bool& aMirrorInvert )
3024 {
3025  wxPoint retVal = aPoint;
3026 
3027  if( aScalingFactor != 1.0 )
3028  {
3029  //scale point
3030  retVal -= aTransformCentre;
3031  retVal.x = KiROUND( retVal.x * aScalingFactor );
3032  retVal.y = KiROUND( retVal.y * aScalingFactor );
3033  retVal += aTransformCentre;
3034  }
3035 
3036  if( aMirrorInvert )
3037  {
3038  MIRROR( retVal.x, aTransformCentre.x );
3039  }
3040 
3041  if( aRotationAngleDeciDeg != 0.0 )
3042  {
3043  RotatePoint( &retVal, aTransformCentre, aRotationAngleDeciDeg );
3044  }
3045 
3046  if( aMoveVector != wxPoint{ 0, 0 } )
3047  {
3048  retVal += aMoveVector;
3049  }
3050 
3051  return retVal;
3052 }
3053 
3054 
3055 double CADSTAR_SCH_ARCHIVE_LOADER::getPolarAngle( const wxPoint& aPoint )
3056 {
3057  return NormalizeAnglePos( ArcTangente( aPoint.y, aPoint.x ) );
3058 }
3059 
3060 
3061 double CADSTAR_SCH_ARCHIVE_LOADER::getPolarRadius( const wxPoint& aPoint )
3062 {
3063  return sqrt(
3064  ( (double) aPoint.x * (double) aPoint.x ) + ( (double) aPoint.y * (double) aPoint.y ) );
3065 }
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:756
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:414
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:959
void SetPosition(const wxPoint &aPosition) override
Definition: sch_symbol.h:646
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:135
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:705
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.cpp:320
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:106
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:122
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:121
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:741
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:459
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
void RemoveDrawItem(LIB_ITEM *aItem)
Remove draw aItem from list.
Definition: lib_symbol.cpp:690
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:102
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:342
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:1210
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
std::vector< struct LIB_SYMBOL_UNIT > GetUnitDrawItems()
Return a list of LIB_ITEM objects separated by unit and convert number.
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:165
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:123
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:110
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:266
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:131
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
Definition: sch_symbol.cpp:751
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:335
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:425
int GetRight() const
Definition: eda_rect.h:120
SCH_TEXT * getKiCadSchText(const TEXT &aCadstarTextElement)
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
Definition: sch_symbol.cpp:307
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:1564
#define _(s)
PART getPart(const PART_ID &aCadstarPartID)
void SetWidth(int aWidth)
Definition: eda_shape.h:97
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:716
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:379
void applyToLibraryFieldAttribute(const ATTRIBUTE_LOCATION &aCadstarAttrLoc, wxPoint aSymbolOrigin, LIB_FIELD *aKiCadField)
LABEL_SPIN_STYLE MirrorY()
Mirror the label spin style across the Y axis or simply swaps left and right.
Definition: sch_text.cpp:198
SCH_FIELD * FindField(const wxString &aFieldName, bool aIncludeDefaultFields=true)
Search for a SCH_FIELD with aFieldName.
Definition: sch_symbol.cpp:773
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:227
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:265
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:729
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:104
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:468
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:504
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:1216
ALIGNMENT rotate180(const ALIGNMENT &aCadstarAlignment)
wxPoint Centre() const
Definition: eda_rect.h:64
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:230
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:101
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:1059
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:100
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:1165
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