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