KiCad PCB EDA Suite
sch_altium_plugin.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 Thomas Pointhuber <thomas.pointhuber@gmx.at>
5  * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <memory>
26 
27 #include "altium_parser_sch.h"
31 
32 #include <schematic.h>
33 
34 #include <lib_arc.h>
35 #include <lib_bezier.h>
36 #include <lib_circle.h>
37 #include <lib_id.h>
38 #include <lib_item.h>
39 #include <lib_pin.h>
40 #include <lib_polyline.h>
41 #include <lib_rectangle.h>
42 #include <lib_text.h>
43 
44 #include <bus_alias.h>
45 #include <sch_bitmap.h>
46 #include <sch_bus_entry.h>
47 #include <sch_symbol.h>
48 #include <sch_junction.h>
49 #include <sch_line.h>
50 #include <sch_no_connect.h>
51 #include <sch_screen.h>
52 #include <sch_sheet.h>
53 #include <sch_text.h>
54 
55 #include <bezier_curves.h>
56 #include <compoundfilereader.h>
57 #include <kicad_string.h>
58 #include <sch_edit_frame.h>
60 
61 
62 const wxPoint GetRelativePosition( const wxPoint& aPosition, const SCH_COMPONENT* aComponent )
63 {
64  TRANSFORM t = aComponent->GetTransform().InverseTransform();
65  return t.TransformCoordinate( aPosition - aComponent->GetPosition() );
66 }
67 
68 
70 {
71  int red = color & 0x0000FF;
72  int green = ( color & 0x00FF00 ) >> 8;
73  int blue = ( color & 0xFF0000 ) >> 16;
74 
75  return COLOR4D().FromCSSRGBA( red, green, blue, 1.0 );
76 }
77 
79 {
80  m_rootSheet = nullptr;
81  m_currentSheet = nullptr;
82  m_schematic = nullptr;
83 }
84 
85 
87 {
88 }
89 
90 
91 const wxString SCH_ALTIUM_PLUGIN::GetName() const
92 {
93  return "Altium";
94 }
95 
96 
98 {
99  return "SchDoc";
100 }
101 
102 
104 {
105  return "SchLib";
106 }
107 
108 
110 {
111  return 0;
112 }
113 
114 
115 bool SCH_ALTIUM_PLUGIN::CheckHeader( const wxString& aFileName )
116 {
117  // TODO
118 
119  return true;
120 }
121 
122 
124 {
125  if( m_libName.IsEmpty() )
126  {
127  // Try to come up with a meaningful name
129 
130  if( m_libName.IsEmpty() )
131  {
132  wxFileName fn( m_rootSheet->GetFileName() );
133  m_libName = fn.GetName();
134  }
135 
136  if( m_libName.IsEmpty() )
137  m_libName = "noname";
138 
139  m_libName += "-altium-import";
141  }
142 
143  return m_libName;
144 }
145 
146 
148 {
150 
151  return fn;
152 }
153 
154 
155 SCH_SHEET* SCH_ALTIUM_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchematic,
156  SCH_SHEET* aAppendToMe, const PROPERTIES* aProperties )
157 {
158  wxASSERT( !aFileName || aSchematic != NULL );
159 
160  wxFileName fileName( aFileName );
161  fileName.SetExt( KiCadSchematicFileExtension );
162  m_schematic = aSchematic;
163 
164  // Delete on exception, if I own m_rootSheet, according to aAppendToMe
165  std::unique_ptr<SCH_SHEET> deleter( aAppendToMe ? nullptr : m_rootSheet );
166 
167  if( aAppendToMe )
168  {
169  wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
170  m_rootSheet = &aSchematic->Root();
171  }
172  else
173  {
174  m_rootSheet = new SCH_SHEET( aSchematic );
175  m_rootSheet->SetFileName( fileName.GetFullPath() );
176  }
177 
178  if( !m_rootSheet->GetScreen() )
179  {
180  SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
181  screen->SetFileName( aFileName );
182  m_rootSheet->SetScreen( screen );
183  }
184 
185  SYMBOL_LIB_TABLE* libTable = m_schematic->Prj().SchSymbolLibTable();
186 
187  wxCHECK_MSG( libTable, NULL, "Could not load symbol lib table." );
188 
189  m_pi.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
190 
193  if( !libTable->HasLibrary( getLibName() ) )
194  {
195  // Create a new empty symbol library.
196  m_pi->CreateSymbolLib( getLibFileName().GetFullPath() );
197  wxString libTableUri = "${KIPRJMOD}/" + getLibFileName().GetFullName();
198 
199  // Add the new library to the project symbol library table.
200  libTable->InsertRow( new SYMBOL_LIB_TABLE_ROW( getLibName(), libTableUri,
201  wxString( "KiCad" ) ) );
202 
203  // Save project symbol library table.
204  wxFileName fn( m_schematic->Prj().GetProjectPath(),
206 
207  // So output formatter goes out of scope and closes the file before reloading.
208  {
209  FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() );
210  libTable->Format( &formatter, 0 );
211  }
212 
213  // Reload the symbol library table.
215  m_schematic->Prj().SchSymbolLibTable();
216  }
217 
219  ParseAltiumSch( aFileName );
220 
221  m_pi->SaveLibrary( getLibFileName().GetFullPath() );
222 
223  return m_rootSheet;
224 }
225 
226 
227 /*wxString SCH_EAGLE_PLUGIN::fixSymbolName( const wxString& aName )
228 {
229  wxString ret = LIB_ID::FixIllegalChars( aName, LIB_ID::ID_SCH );
230 
231  return ret;
232 }*/
233 
234 void SCH_ALTIUM_PLUGIN::ParseAltiumSch( const wxString& aFileName )
235 {
236  // Open file
237  FILE* fp = wxFopen( aFileName, "rb" );
238 
239  if( fp == nullptr )
240  {
241  wxLogError( wxString::Format( _( "Cannot open file '%s'" ), aFileName ) );
242  return;
243  }
244 
245  fseek( fp, 0, SEEK_END );
246  long len = ftell( fp );
247 
248  if( len < 0 )
249  {
250  fclose( fp );
251  THROW_IO_ERROR( "Reading error, cannot determine length of file" );
252  }
253 
254  std::unique_ptr<unsigned char[]> buffer( new unsigned char[len] );
255  fseek( fp, 0, SEEK_SET );
256 
257  size_t bytesRead = fread( buffer.get(), sizeof( unsigned char ), len, fp );
258  fclose( fp );
259 
260  if( static_cast<size_t>( len ) != bytesRead )
261  THROW_IO_ERROR( "Reading error" );
262 
263  try
264  {
265  CFB::CompoundFileReader reader( buffer.get(), bytesRead );
266  Parse( reader );
267  }
268  catch( CFB::CFBException& exception )
269  {
270  THROW_IO_ERROR( exception.what() );
271  }
272 }
273 
274 
275 void SCH_ALTIUM_PLUGIN::Parse( const CFB::CompoundFileReader& aReader )
276 {
277  const CFB::COMPOUND_FILE_ENTRY* file = FindStream( aReader, "FileHeader" );
278 
279  if( file == nullptr )
280  THROW_IO_ERROR( "FileHeader not found" );
281 
282  ALTIUM_PARSER reader( aReader, file );
283 
284  if( reader.GetRemainingBytes() <= 0 )
285  {
286  THROW_IO_ERROR( "FileHeader does not contain any data" );
287  }
288  else
289  {
290  std::map<wxString, wxString> properties = reader.ReadProperties();
291 
292  int recordId = ALTIUM_PARSER::PropertiesReadInt( properties, "RECORD", 0 );
293  ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
294 
295  if( record != ALTIUM_SCH_RECORD::HEADER )
296  THROW_IO_ERROR( "Header expected" );
297  }
298 
299  // Prepare some local variables
300  wxASSERT( m_altiumPortsCurrentSheet.empty() );
301  wxASSERT( !m_currentTitleBlock );
302 
303  m_currentTitleBlock = std::make_unique<TITLE_BLOCK>();
304 
305  // index is required required to resolve OWNERINDEX
306  for( int index = 0; reader.GetRemainingBytes() > 0; index++ )
307  {
308  std::map<wxString, wxString> properties = reader.ReadProperties();
309 
310  int recordId = ALTIUM_PARSER::PropertiesReadInt( properties, "RECORD", 0 );
311  ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
312 
313  // see: https://github.com/vadmium/python-altium/blob/master/format.md
314  switch( record )
315  {
317  THROW_IO_ERROR( "Header already parsed" );
319  ParseComponent( index, properties );
320  break;
322  ParsePin( properties );
323  break;
325  break;
327  ParseLabel( properties );
328  break;
330  ParseBezier( properties );
331  break;
333  ParsePolyline( properties );
334  break;
336  ParsePolygon( properties );
337  break;
339  break;
341  break;
343  ParseRoundRectangle( properties );
344  break;
346  break;
348  ParseArc( properties );
349  break;
351  ParseLine( properties );
352  break;
354  ParseRectangle( properties );
355  break;
357  ParseSheetSymbol( index, properties );
358  break;
360  ParseSheetEntry( properties );
361  break;
363  ParsePowerPort( properties );
364  break;
366  // Ports are parsed after the sheet was parsed
367  // This is required because we need all electrical connection points before placing.
368  m_altiumPortsCurrentSheet.emplace_back( properties );
369  break;
371  ParseNoERC( properties );
372  break;
374  ParseNetLabel( properties );
375  break;
377  ParseBus( properties );
378  break;
380  ParseWire( properties );
381  break;
383  break;
385  ParseJunction( properties );
386  break;
388  break;
390  ParseSheet( properties );
391  break;
393  ParseSheetName( properties );
394  break;
396  ParseFileName( properties );
397  break;
399  ParseDesignator( properties );
400  break;
402  ParseBusEntry( properties );
403  break;
405  break;
407  ParseParameter( properties );
408  break;
410  break;
412  break;
414  break;
416  break;
418  break;
420  break;
422  break;
424  break;
426  break;
428  break;
430  break;
432  break;
433  default:
434  wxLogError( wxString::Format( "Unknown Record id: %d", recordId ) );
435  break;
436  }
437  }
438 
439  if( reader.HasParsingError() )
440  THROW_IO_ERROR( "stream was not parsed correctly!" );
441 
442  if( reader.GetRemainingBytes() != 0 )
443  THROW_IO_ERROR( "stream is not fully parsed" );
444 
445  // assign LIB_PART -> COMPONENT
446  for( auto component : m_components )
447  {
448  auto kpart = m_symbols.find( component.first );
449 
450  if( kpart == m_symbols.end() )
451  THROW_IO_ERROR( "every component should have a symbol attached" );
452 
453  m_pi->SaveSymbol( getLibFileName().GetFullPath(), new LIB_PART( *( kpart->second ) ),
454  m_properties.get() );
455 
456  component.second->SetLibSymbol( kpart->second );
457  }
458 
459  // Handle title blocks
461  m_currentTitleBlock.reset();
462 
463  // Handle Ports
464  for( const ASCH_PORT& port : m_altiumPortsCurrentSheet )
465  ParsePort( port );
466 
468 
469  m_components.clear();
470  m_symbols.clear();
471 
472  // Otherwise we cannot save the imported sheet?
474 }
475 
476 
477 bool SCH_ALTIUM_PLUGIN::IsComponentPartVisible( int aOwnerindex, int aOwnerpartdisplaymode ) const
478 {
479  const auto& component = m_altiumComponents.find( aOwnerindex );
480 
481  if( component == m_altiumComponents.end() )
482  return false;
483 
484  return component->second.displaymode == aOwnerpartdisplaymode;
485 }
486 
487 
489  const std::map<wxString, wxString>& aProperties )
490 {
491  auto pair = m_altiumComponents.insert( { aIndex, ASCH_COMPONENT( aProperties ) } );
492  const ASCH_COMPONENT& elem = pair.first->second;
493 
494  // TODO: this is a hack until we correctly apply all transformations to every element
495  wxString name = wxString::Format( "%d%s_%s",
496  elem.orientation,
497  elem.isMirrored ? "_mirrored" : "",
498  elem.libreference );
500 
501  LIB_PART* kpart = new LIB_PART( wxEmptyString );
502  kpart->SetName( name );
503  kpart->SetDescription( elem.componentdescription );
504  kpart->SetLibId( libId );
505  m_symbols.insert( { aIndex, kpart } );
506 
507  // each component has its own symbol for now
508  SCH_COMPONENT* component = new SCH_COMPONENT();
509 
510  component->SetPosition( elem.location + m_sheetOffset );
511  //component->SetOrientation( elem.orientation ); // TODO: keep it simple for now, and only set position
512  component->SetLibId( libId );
513  //component->SetLibSymbol( kpart ); // this has to be done after parsing the LIB_PART!
514 
515  component->SetUnit( elem.currentpartid );
516 
517  m_currentSheet->GetScreen()->Append( component );
518 
519  m_components.insert( { aIndex, component } );
520 }
521 
522 
523 void SCH_ALTIUM_PLUGIN::ParsePin( const std::map<wxString, wxString>& aProperties )
524 {
525  ASCH_PIN elem( aProperties );
526 
527  const auto& symbol = m_symbols.find( elem.ownerindex );
528 
529  if( symbol == m_symbols.end() )
530  {
531  // TODO: e.g. can depend on Template (RECORD=39
532  wxLogWarning( wxString::Format( "Pin has non-existent ownerindex %d",
533  elem.ownerindex ) );
534  return;
535  }
536 
538  return;
539 
540  const auto& component = m_components.at( symbol->first );
541 
542  LIB_PIN* pin = new LIB_PIN( symbol->second );
543  symbol->second->AddDrawItem( pin );
544 
545  pin->SetUnit( elem.ownerpartid );
546 
547  pin->SetName( elem.name );
548  pin->SetNumber( elem.designator );
549  pin->SetLength( elem.pinlength );
550 
551  wxPoint pinLocation = elem.location; // the location given is not the connection point!
552 
553  switch( elem.orientation )
554  {
557  pinLocation.x += elem.pinlength;
558  break;
561  pinLocation.y -= elem.pinlength;
562  break;
565  pinLocation.x -= elem.pinlength;
566  break;
569  pinLocation.y += elem.pinlength;
570  break;
571  default:
572  wxLogWarning( "Pin has unexpected orientation" );
573  break;
574  }
575 
576  // TODO: position can be sometimes off a little bit!
577  pin->SetPosition( GetRelativePosition( pinLocation + m_sheetOffset, component ) );
578  // TODO: the following fix is even worse for now?
579  // pin->SetPosition( GetRelativePosition( elem.kicadLocation, component ) );
580 
581  switch( elem.electrical )
582  {
585  break;
588  break;
591  break;
594  break;
597  break;
600  break;
603  break;
606  break;
608  default:
610  wxLogWarning( "Pin has unexpected electrical type" );
611  break;
612  }
613 
615  wxLogWarning( "Pin has unexpected outer edge type" );
616 
618  wxLogWarning( "Pin has unexpected inner edge type" );
619 
621  {
622  switch( elem.symbolInnerEdge )
623  {
626  break;
627  default:
629  break;
630  }
631  }
633  {
634  switch( elem.symbolInnerEdge )
635  {
638  break;
639  default:
641  break;
642  }
643  }
645  {
647  }
648  else
649  {
650  switch( elem.symbolInnerEdge )
651  {
654  break;
655  default:
656  pin->SetShape( GRAPHIC_PINSHAPE::LINE ); // nothing to do
657  break;
658  }
659  }
660 }
661 
662 
664 {
665  switch( justification )
666  {
667  default:
673  break;
678  break;
683  break;
684  }
685 
686  switch( justification )
687  {
688  default:
694  break;
699  break;
704  break;
705  }
706 }
707 
708 
709 void SCH_ALTIUM_PLUGIN::ParseLabel( const std::map<wxString, wxString>& aProperties )
710 {
711  ASCH_LABEL elem( aProperties );
712 
713  // TODO: text variable support
714  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
715  {
716  SCH_TEXT* text = new SCH_TEXT( elem.location + m_sheetOffset, elem.text );
717 
719 
720  size_t fontId = static_cast<int>( elem.fontId );
721 
722  if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
723  {
724  const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
725  text->SetItalic( font.italic );
726  text->SetBold( font.bold );
727  text->SetTextSize( { font.size / 2, font.size / 2 } );
728  }
729 
730  text->SetFlags( IS_NEW );
731  m_currentSheet->GetScreen()->Append( text );
732  }
733  else
734  {
735  const auto& symbol = m_symbols.find( elem.ownerindex );
736 
737  if( symbol == m_symbols.end() )
738  {
739  // TODO: e.g. can depend on Template (RECORD=39
740  wxLogWarning( wxString::Format( "Label has non-existent ownerindex %d",
741  elem.ownerindex ) );
742  return;
743  }
744 
745  const auto& component = m_components.at( symbol->first );
746 
747  LIB_TEXT* text = new LIB_TEXT( symbol->second );
748  symbol->second->AddDrawItem( text );
749 
750  text->SetUnit( elem.ownerpartid );
751 
752  text->SetPosition( GetRelativePosition( elem.location + m_sheetOffset, component ) );
753  text->SetText( elem.text );
755 
756  size_t fontId = static_cast<int>( elem.fontId );
757 
758  if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
759  {
760  const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
761  text->SetItalic( font.italic );
762  text->SetBold( font.bold );
763  text->SetTextSize( { font.size / 2, font.size / 2 } );
764  }
765  }
766 }
767 
768 
769 void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProperties )
770 {
771  ASCH_BEZIER elem( aProperties );
772 
773  if( elem.points.size() < 2 )
774  {
775  wxLogWarning( wxString::Format( "Bezier has %d control points. At least 2 are expected.",
776  static_cast<int>( elem.points.size() ) ) );
777  return;
778  }
779 
780  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
781  {
782  for( size_t i = 0; i + 1 < elem.points.size(); i += 3 )
783  {
784  if( i + 2 == elem.points.size() )
785  {
786  // special case: single line
787  SCH_LINE* line = new SCH_LINE( elem.points.at( i ) + m_sheetOffset,
789 
790  line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
791  line->SetLineWidth( elem.lineWidth );
793 
794  line->SetFlags( IS_NEW );
795  m_currentSheet->GetScreen()->Append( line );
796  }
797  else
798  {
799  // simulate bezier using line segments
800  std::vector<wxPoint> bezierPoints;
801  std::vector<wxPoint> polyPoints;
802  for( size_t j = i; j < elem.points.size() && j < i + 4; j++ )
803  {
804  bezierPoints.push_back( elem.points.at( j ) + m_sheetOffset );
805  }
806 
807  BEZIER_POLY converter( bezierPoints );
808  converter.GetPoly( polyPoints );
809 
810  for( size_t k = 0; k + 1 < polyPoints.size(); k++ )
811  {
812  SCH_LINE* line = new SCH_LINE( polyPoints.at( k ) + m_sheetOffset,
814 
815  line->SetEndPoint( polyPoints.at( k + 1 ) + m_sheetOffset );
816  line->SetLineWidth( elem.lineWidth );
817 
818  line->SetFlags( IS_NEW );
819  m_currentSheet->GetScreen()->Append( line );
820  }
821  }
822  }
823  }
824  else
825  {
826  const auto& symbol = m_symbols.find( elem.ownerindex );
827 
828  if( symbol == m_symbols.end() )
829  {
830  // TODO: e.g. can depend on Template (RECORD=39
831  wxLogWarning( wxString::Format( "Bezier has non-existent ownerindex %d",
832  elem.ownerindex ) );
833  return;
834  }
835 
837  return;
838 
839  const auto& component = m_components.at( symbol->first );
840 
841  for( size_t i = 0; i + 1 < elem.points.size(); i += 3 )
842  {
843  if( i + 2 == elem.points.size() )
844  {
845  // special case: single line
846  LIB_POLYLINE* line = new LIB_POLYLINE( symbol->second );
847  symbol->second->AddDrawItem( line );
848 
849  line->SetUnit( elem.ownerpartid );
850 
851  for( size_t j = i; j < elem.points.size() && j < i + 2; j++ )
852  {
853  line->AddPoint( GetRelativePosition( elem.points.at( j ) + m_sheetOffset,
854  component ) );
855  }
856 
857  line->SetWidth( elem.lineWidth );
858  }
859  else
860  {
861  // bezier always has maximum of 4 control points
862  LIB_BEZIER* bezier = new LIB_BEZIER( symbol->second );
863  symbol->second->AddDrawItem( bezier );
864 
865  bezier->SetUnit( elem.ownerpartid );
866 
867  for( size_t j = i; j < elem.points.size() && j < i + 4; j++ )
868  {
869  bezier->AddPoint( GetRelativePosition( elem.points.at( j ) + m_sheetOffset,
870  component ) );
871  }
872 
873  bezier->SetWidth( elem.lineWidth );
874  }
875  }
876  }
877 }
878 
879 
880 void SCH_ALTIUM_PLUGIN::ParsePolyline( const std::map<wxString, wxString>& aProperties )
881 {
882  ASCH_POLYLINE elem( aProperties );
883 
884  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
885  {
887  switch( elem.linestyle )
888  {
889  default:
894  }
895 
896  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
897  {
898  SCH_LINE* line = new SCH_LINE( elem.points.at( i ) + m_sheetOffset,
900 
901  line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
902  line->SetLineWidth( elem.lineWidth );
903  line->SetLineStyle( dashType );
904 
905  line->SetFlags( IS_NEW );
906  m_currentSheet->GetScreen()->Append( line );
907  }
908  }
909  else
910  {
911  const auto& symbol = m_symbols.find( elem.ownerindex );
912  if( symbol == m_symbols.end() )
913  {
914  // TODO: e.g. can depend on Template (RECORD=39
915  wxLogWarning( wxString::Format( "Polyline has non-existent ownerindex %d",
916  elem.ownerindex ) );
917  return;
918  }
919 
921  return;
922 
923  const auto& component = m_components.at( symbol->first );
924 
925  LIB_POLYLINE* line = new LIB_POLYLINE( symbol->second );
926  symbol->second->AddDrawItem( line );
927 
928  line->SetUnit( elem.ownerpartid );
929 
930  for( wxPoint& point : elem.points )
931  {
932  line->AddPoint( GetRelativePosition( point + m_sheetOffset, component ) );
933  }
934 
935  line->SetWidth( elem.lineWidth );
936  }
937 }
938 
939 
940 void SCH_ALTIUM_PLUGIN::ParsePolygon( const std::map<wxString, wxString>& aProperties )
941 {
942  ASCH_POLYGON elem( aProperties );
943 
944  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
945  {
946  // TODO: we cannot fill this polygon, only draw it for now
947  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
948  {
949  SCH_LINE* line =
951  line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
952  line->SetLineWidth( elem.lineWidth );
954 
955  line->SetFlags( IS_NEW );
956  m_currentSheet->GetScreen()->Append( line );
957  }
958 
959  // close polygon
960  SCH_LINE* line =
962  line->SetEndPoint( elem.points.back() + m_sheetOffset );
963  line->SetLineWidth( elem.lineWidth );
965 
966  line->SetFlags( IS_NEW );
967  m_currentSheet->GetScreen()->Append( line );
968  }
969  else
970  {
971  const auto& symbol = m_symbols.find( elem.ownerindex );
972 
973  if( symbol == m_symbols.end() )
974  {
975  // TODO: e.g. can depend on Template (RECORD=39
976  wxLogWarning( wxString::Format( "Polygon has non-existent ownerindex %d",
977  elem.ownerindex ) );
978  return;
979  }
980 
982  return;
983 
984  const auto& component = m_components.at( symbol->first );
985 
986  LIB_POLYLINE* line = new LIB_POLYLINE( symbol->second );
987  symbol->second->AddDrawItem( line );
988 
989  line->SetUnit( elem.ownerpartid );
990 
991  for( wxPoint& point : elem.points )
992  line->AddPoint( GetRelativePosition( point + m_sheetOffset, component ) );
993 
994  line->AddPoint( GetRelativePosition( elem.points.front() + m_sheetOffset, component ) );
995 
996  line->SetWidth( elem.lineWidth );
997 
998  if( !elem.isSolid )
1000  else if( elem.color == elem.areacolor )
1002  else
1004  }
1005 }
1006 
1007 
1008 void SCH_ALTIUM_PLUGIN::ParseRoundRectangle( const std::map<wxString, wxString>& aProperties )
1009 {
1010  ASCH_ROUND_RECTANGLE elem( aProperties );
1011 
1012  wxPoint sheetTopRight = elem.topRight + m_sheetOffset;
1013  wxPoint sheetBottomLeft = elem.bottomLeft + m_sheetOffset;
1014 
1015  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1016  {
1017  const wxPoint topLeft = { sheetBottomLeft.x, sheetTopRight.y };
1018  const wxPoint bottomRight = { sheetTopRight.x, sheetBottomLeft.y };
1019 
1020  // TODO: we cannot fill this rectangle, only draw it for now
1021  // TODO: misses rounded edges
1022  SCH_LINE* lineTop = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1023  lineTop->SetEndPoint( topLeft );
1024  lineTop->SetLineWidth( elem.lineWidth );
1025  lineTop->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1026  lineTop->SetFlags( IS_NEW );
1027  m_currentSheet->GetScreen()->Append( lineTop );
1028 
1029  SCH_LINE* lineBottom = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1030  lineBottom->SetEndPoint( bottomRight );
1031  lineBottom->SetLineWidth( elem.lineWidth );
1032  lineBottom->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1033  lineBottom->SetFlags( IS_NEW );
1034  m_currentSheet->GetScreen()->Append( lineBottom );
1035 
1036  SCH_LINE* lineRight = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1037  lineRight->SetEndPoint( bottomRight );
1038  lineRight->SetLineWidth( elem.lineWidth );
1039  lineRight->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1040  lineRight->SetFlags( IS_NEW );
1041  m_currentSheet->GetScreen()->Append( lineRight );
1042 
1043  SCH_LINE* lineLeft = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1044  lineLeft->SetEndPoint( topLeft );
1045  lineLeft->SetLineWidth( elem.lineWidth );
1046  lineLeft->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1047  lineLeft->SetFlags( IS_NEW );
1048  m_currentSheet->GetScreen()->Append( lineLeft );
1049  }
1050  else
1051  {
1052  const auto& symbol = m_symbols.find( elem.ownerindex );
1053 
1054  if( symbol == m_symbols.end() )
1055  {
1056  // TODO: e.g. can depend on Template (RECORD=39
1057  wxLogWarning( wxString::Format( "Rounded Rectangle has non-existent ownerindex %d",
1058  elem.ownerindex ) );
1059  return;
1060  }
1061 
1063  return;
1064 
1065  const auto& component = m_components.at( symbol->first );
1066 
1067  // TODO: misses rounded edges
1068  LIB_RECTANGLE* rect = new LIB_RECTANGLE( symbol->second );
1069  symbol->second->AddDrawItem( rect );
1070 
1071  rect->SetUnit( elem.ownerpartid );
1072 
1073  rect->SetPosition( GetRelativePosition( elem.topRight + m_sheetOffset, component ) );
1074  rect->SetEnd( GetRelativePosition( elem.bottomLeft + m_sheetOffset, component ) );
1075  rect->SetWidth( elem.lineWidth );
1076 
1077  if( !elem.isSolid )
1079  else if( elem.color == elem.areacolor )
1081  else
1083  }
1084 }
1085 
1086 
1087 void SCH_ALTIUM_PLUGIN::ParseArc( const std::map<wxString, wxString>& aProperties )
1088 {
1089  ASCH_ARC elem( aProperties );
1090 
1091  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1092  {
1093  wxLogError( "Arc drawing is not possible for now on schematic." );
1094  }
1095  else
1096  {
1097  const auto& symbol = m_symbols.find( elem.ownerindex );
1098  if( symbol == m_symbols.end() )
1099  {
1100  // TODO: e.g. can depend on Template (RECORD=39
1101  wxLogWarning( wxString::Format( "Arc has non-existent ownerindex %d",
1102  elem.ownerindex ) );
1103  return;
1104  }
1105 
1107  return;
1108 
1109  const auto& component = m_components.at( symbol->first );
1110 
1111  if( elem.startAngle == 0 && ( elem.endAngle == 0 || elem.endAngle == 360 ) )
1112  {
1113  LIB_CIRCLE* circle = new LIB_CIRCLE( symbol->second );
1114  symbol->second->AddDrawItem( circle );
1115 
1116  circle->SetUnit( elem.ownerpartid );
1117 
1118  circle->SetPosition( GetRelativePosition( elem.center + m_sheetOffset, component ) );
1119  circle->SetRadius( elem.radius );
1120  circle->SetWidth( elem.lineWidth );
1121  }
1122  else
1123  {
1124  LIB_ARC* arc = new LIB_ARC( symbol->second );
1125  symbol->second->AddDrawItem( arc );
1126 
1127  arc->SetUnit( elem.ownerpartid );
1128 
1129  // TODO: correct?
1130  arc->SetPosition( GetRelativePosition( elem.center + m_sheetOffset, component ) );
1131  arc->SetRadius( elem.radius );
1132  arc->SetFirstRadiusAngle( elem.startAngle * 10. );
1133  arc->SetSecondRadiusAngle( elem.endAngle * 10. );
1134  }
1135  }
1136 }
1137 
1138 
1139 void SCH_ALTIUM_PLUGIN::ParseLine( const std::map<wxString, wxString>& aProperties )
1140 {
1141  ASCH_LINE elem( aProperties );
1142 
1143  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1144  {
1145  // close polygon
1147  line->SetEndPoint( elem.point2 + m_sheetOffset );
1148  line->SetLineWidth( elem.lineWidth );
1149  line->SetLineStyle( PLOT_DASH_TYPE::SOLID ); // TODO?
1150 
1151  line->SetFlags( IS_NEW );
1152  m_currentSheet->GetScreen()->Append( line );
1153  }
1154  else
1155  {
1156  const auto& symbol = m_symbols.find( elem.ownerindex );
1157 
1158  if( symbol == m_symbols.end() )
1159  {
1160  // TODO: e.g. can depend on Template (RECORD=39
1161  wxLogWarning( wxString::Format( "Line has non-existent ownerindex %d",
1162  elem.ownerindex ) );
1163  return;
1164  }
1165 
1167  return;
1168 
1169  const auto& component = m_components.at( symbol->first );
1170 
1171  LIB_POLYLINE* line = new LIB_POLYLINE( symbol->second );
1172  symbol->second->AddDrawItem( line );
1173 
1174  line->SetUnit( elem.ownerpartid );
1175 
1176  line->AddPoint( GetRelativePosition( elem.point1 + m_sheetOffset, component ) );
1177  line->AddPoint( GetRelativePosition( elem.point2 + m_sheetOffset, component ) );
1178 
1179  line->SetWidth( elem.lineWidth );
1180  }
1181 }
1182 
1183 
1184 void SCH_ALTIUM_PLUGIN::ParseRectangle( const std::map<wxString, wxString>& aProperties )
1185 {
1186  ASCH_RECTANGLE elem( aProperties );
1187 
1188  wxPoint sheetTopRight = elem.topRight + m_sheetOffset;
1189  wxPoint sheetBottomLeft = elem.bottomLeft + m_sheetOffset;
1190 
1191  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1192  {
1193  const wxPoint topLeft = { sheetBottomLeft.x, sheetTopRight.y };
1194  const wxPoint bottomRight = { sheetTopRight.x, sheetBottomLeft.y };
1195 
1196  // TODO: we cannot fill this rectangle, only draw it for now
1197  SCH_LINE* lineTop = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1198  lineTop->SetEndPoint( topLeft );
1199  lineTop->SetLineWidth( elem.lineWidth );
1200  lineTop->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1201  lineTop->SetFlags( IS_NEW );
1202  m_currentSheet->GetScreen()->Append( lineTop );
1203 
1204  SCH_LINE* lineBottom = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1205  lineBottom->SetEndPoint( bottomRight );
1206  lineBottom->SetLineWidth( elem.lineWidth );
1207  lineBottom->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1208  lineBottom->SetFlags( IS_NEW );
1209  m_currentSheet->GetScreen()->Append( lineBottom );
1210 
1211  SCH_LINE* lineRight = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1212  lineRight->SetEndPoint( bottomRight );
1213  lineRight->SetLineWidth( elem.lineWidth );
1214  lineRight->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1215  lineRight->SetFlags( IS_NEW );
1216  m_currentSheet->GetScreen()->Append( lineRight );
1217 
1218  SCH_LINE* lineLeft = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1219  lineLeft->SetEndPoint( topLeft );
1220  lineLeft->SetLineWidth( elem.lineWidth );
1221  lineLeft->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1222  lineLeft->SetFlags( IS_NEW );
1223  m_currentSheet->GetScreen()->Append( lineLeft );
1224  }
1225  else
1226  {
1227  const auto& symbol = m_symbols.find( elem.ownerindex );
1228 
1229  if( symbol == m_symbols.end() )
1230  {
1231  // TODO: e.g. can depend on Template (RECORD=39
1232  wxLogWarning( wxString::Format( "Rectangle has non-existent ownerindex %d",
1233  elem.ownerindex ) );
1234  return;
1235  }
1236 
1238  return;
1239 
1240  const auto& component = m_components.at( symbol->first );
1241 
1242  LIB_RECTANGLE* rect = new LIB_RECTANGLE( symbol->second );
1243  symbol->second->AddDrawItem( rect );
1244 
1245  rect->SetUnit( elem.ownerpartid );
1246 
1247  rect->SetPosition( GetRelativePosition( sheetTopRight, component ) );
1248  rect->SetEnd( GetRelativePosition( sheetBottomLeft, component ) );
1249  rect->SetWidth( elem.lineWidth );
1250 
1251  if( !elem.isSolid )
1253  else if( elem.color == elem.areacolor )
1255  else
1257  }
1258 }
1259 
1260 
1262  int aIndex, const std::map<wxString, wxString>& aProperties )
1263 {
1264  ASCH_SHEET_SYMBOL elem( aProperties );
1265 
1266  SCH_SHEET* sheet = new SCH_SHEET( m_currentSheet, elem.location + m_sheetOffset );
1267  SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
1268 
1269  sheet->SetSize( elem.size );
1270 
1271  sheet->SetBorderColor( GetColorFromInt( elem.color ) );
1272  if( elem.isSolid )
1273  sheet->SetBackgroundColor( GetColorFromInt( elem.areacolor ) );
1274 
1275  sheet->SetScreen( screen );
1276 
1277  sheet->SetFlags( IS_NEW );
1278  m_currentSheet->GetScreen()->Append( sheet );
1279 
1280  m_sheets.insert( { aIndex, sheet } );
1281 }
1282 
1283 
1284 void SCH_ALTIUM_PLUGIN::ParseSheetEntry( const std::map<wxString, wxString>& aProperties )
1285 {
1286  ASCH_SHEET_ENTRY elem( aProperties );
1287 
1288  const auto& sheet = m_sheets.find( elem.ownerindex );
1289  if( sheet == m_sheets.end() )
1290  {
1291  wxLogError( wxString::Format( "Sheet Entry has non-existent ownerindex %d",
1292  elem.ownerindex ) );
1293  return;
1294  }
1295 
1296  SCH_SHEET_PIN* sheetPin = new SCH_SHEET_PIN( sheet->second );
1297  sheet->second->AddPin( sheetPin );
1298 
1299  sheetPin->SetText( elem.name );
1301  //sheetPin->SetLabelSpinStyle( getSpinStyle( term.OrientAngle, false ) );
1302  //sheetPin->SetPosition( getKiCadPoint( term.Position ) );
1303 
1304  wxPoint pos = sheet->second->GetPosition();
1305  wxSize size = sheet->second->GetSize();
1306 
1307  switch( elem.side )
1308  {
1309  default:
1311  sheetPin->SetPosition( { pos.x, pos.y + elem.distanceFromTop } );
1313  sheetPin->SetEdge( SHEET_SIDE::SHEET_LEFT_SIDE );
1314  break;
1316  sheetPin->SetPosition( { pos.x + size.x, pos.y + elem.distanceFromTop } );
1319  break;
1321  sheetPin->SetPosition( { pos.x + elem.distanceFromTop, pos.y } );
1323  sheetPin->SetEdge( SHEET_SIDE::SHEET_TOP_SIDE );
1324  break;
1326  sheetPin->SetPosition( { pos.x + elem.distanceFromTop, pos.y + size.y } );
1329  break;
1330  }
1331 
1332  switch( elem.iotype )
1333  {
1334  default:
1337  break;
1340  break;
1343  break;
1346  break;
1347  }
1348 }
1349 
1350 
1352 {
1353  if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE || aStyle == ASCH_POWER_PORT_STYLE::ARROW )
1354  {
1355  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart );
1356  aKPart->AddDrawItem( line1 );
1357  line1->SetWidth( Mils2iu( 10 ) );
1358  line1->AddPoint( { 0, 0 } );
1359  line1->AddPoint( { 0, Mils2iu( -50 ) } );
1360 
1361  if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE )
1362  {
1363  LIB_CIRCLE* circle = new LIB_CIRCLE( aKPart );
1364  aKPart->AddDrawItem( circle );
1365  circle->SetWidth( Mils2iu( 5 ) );
1366  circle->SetRadius( Mils2iu( 25 ) );
1367  circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -75 ) } );
1368  }
1369  else
1370  {
1371  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1372  aKPart->AddDrawItem( line2 );
1373  line2->SetWidth( Mils2iu( 10 ) );
1374  line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
1375  line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } );
1376  line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
1377  line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
1378  }
1379 
1380  return { 0, Mils2iu( 150 ) };
1381  }
1382  else if( aStyle == ASCH_POWER_PORT_STYLE::WAVE )
1383  {
1384  LIB_POLYLINE* line = new LIB_POLYLINE( aKPart );
1385  aKPart->AddDrawItem( line );
1386  line->SetWidth( Mils2iu( 10 ) );
1387  line->AddPoint( { 0, 0 } );
1388  line->AddPoint( { 0, Mils2iu( -72 ) } );
1389 
1390  LIB_BEZIER* bezier = new LIB_BEZIER( aKPart );
1391  aKPart->AddDrawItem( bezier );
1392  bezier->SetWidth( Mils2iu( 5 ) );
1393  bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -50 ) } );
1394  bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -87 ) } );
1395  bezier->AddPoint( { Mils2iu( -30 ), Mils2iu( -63 ) } );
1396  bezier->AddPoint( { Mils2iu( -30 ), Mils2iu( -100 ) } );
1397 
1398  return { 0, Mils2iu( 150 ) };
1399  }
1400  else if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND
1402  || aStyle == ASCH_POWER_PORT_STYLE::EARTH
1403  || aStyle == ASCH_POWER_PORT_STYLE::GOST_ARROW )
1404  {
1405  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart );
1406  aKPart->AddDrawItem( line1 );
1407  line1->SetWidth( Mils2iu( 10 ) );
1408  line1->AddPoint( { 0, 0 } );
1409  line1->AddPoint( { 0, Mils2iu( -100 ) } );
1410 
1411  if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND )
1412  {
1413  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1414  aKPart->AddDrawItem( line2 );
1415  line2->SetWidth( Mils2iu( 10 ) );
1416  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1417  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
1418 
1419  LIB_POLYLINE* line3 = new LIB_POLYLINE( aKPart );
1420  aKPart->AddDrawItem( line3 );
1421  line3->SetWidth( Mils2iu( 10 ) );
1422  line3->AddPoint( { Mils2iu( -70 ), Mils2iu( -130 ) } );
1423  line3->AddPoint( { Mils2iu( 70 ), Mils2iu( -130 ) } );
1424 
1425  LIB_POLYLINE* line4 = new LIB_POLYLINE( aKPart );
1426  aKPart->AddDrawItem( line4 );
1427  line4->SetWidth( Mils2iu( 10 ) );
1428  line4->AddPoint( { Mils2iu( -40 ), Mils2iu( -160 ) } );
1429  line4->AddPoint( { Mils2iu( 40 ), Mils2iu( -160 ) } );
1430 
1431  LIB_POLYLINE* line5 = new LIB_POLYLINE( aKPart );
1432  aKPart->AddDrawItem( line5 );
1433  line5->SetWidth( Mils2iu( 10 ) );
1434  line5->AddPoint( { Mils2iu( -10 ), Mils2iu( -190 ) } );
1435  line5->AddPoint( { Mils2iu( 10 ), Mils2iu( -190 ) } );
1436  }
1437  else if( aStyle == ASCH_POWER_PORT_STYLE::SIGNAL_GROUND )
1438  {
1439  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1440  aKPart->AddDrawItem( line2 );
1441  line2->SetWidth( Mils2iu( 10 ) );
1442  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1443  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
1444  line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -200 ) } );
1445  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1446  }
1447  else if( aStyle == ASCH_POWER_PORT_STYLE::EARTH )
1448  {
1449  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1450  aKPart->AddDrawItem( line2 );
1451  line2->SetWidth( Mils2iu( 10 ) );
1452  line2->AddPoint( { Mils2iu( -150 ), Mils2iu( -200 ) } );
1453  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1454  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
1455  line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -200 ) } );
1456 
1457  LIB_POLYLINE* line3 = new LIB_POLYLINE( aKPart );
1458  aKPart->AddDrawItem( line3 );
1459  line3->SetWidth( Mils2iu( 10 ) );
1460  line3->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
1461  line3->AddPoint( { Mils2iu( -50 ), Mils2iu( -200 ) } );
1462  }
1463  else // ASCH_POWER_PORT_STYLE::GOST_ARROW
1464  {
1465  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1466  aKPart->AddDrawItem( line2 );
1467  line2->SetWidth( Mils2iu( 10 ) );
1468  line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
1469  line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
1470  line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } );
1471 
1472  return { 0, Mils2iu( 150 ) }; // special case
1473  }
1474 
1475  return { 0, Mils2iu( 250 ) };
1476  }
1477  else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_POWER_GROUND
1478  || aStyle == ASCH_POWER_PORT_STYLE::GOST_EARTH )
1479  {
1480  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart );
1481  aKPart->AddDrawItem( line1 );
1482  line1->SetWidth( Mils2iu( 10 ) );
1483  line1->AddPoint( { 0, 0 } );
1484  line1->AddPoint( { 0, Mils2iu( -160 ) } );
1485 
1486  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1487  aKPart->AddDrawItem( line2 );
1488  line2->SetWidth( Mils2iu( 10 ) );
1489  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -160 ) } );
1490  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -160 ) } );
1491 
1492  LIB_POLYLINE* line3 = new LIB_POLYLINE( aKPart );
1493  aKPart->AddDrawItem( line3 );
1494  line3->SetWidth( Mils2iu( 10 ) );
1495  line3->AddPoint( { Mils2iu( -60 ), Mils2iu( -200 ) } );
1496  line3->AddPoint( { Mils2iu( 60 ), Mils2iu( -200 ) } );
1497 
1498  LIB_POLYLINE* line4 = new LIB_POLYLINE( aKPart );
1499  aKPart->AddDrawItem( line4 );
1500  line4->SetWidth( Mils2iu( 10 ) );
1501  line4->AddPoint( { Mils2iu( -20 ), Mils2iu( -240 ) } );
1502  line4->AddPoint( { Mils2iu( 20 ), Mils2iu( -240 ) } );
1503 
1505  return { 0, Mils2iu( 300 ) };
1506 
1507  LIB_CIRCLE* circle = new LIB_CIRCLE( aKPart );
1508  aKPart->AddDrawItem( circle );
1509  circle->SetWidth( Mils2iu( 10 ) );
1510  circle->SetRadius( Mils2iu( 120 ) );
1511  circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -160 ) } );
1512 
1513  return { 0, Mils2iu( 350 ) };
1514  }
1515  else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_BAR )
1516  {
1517  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart );
1518  aKPart->AddDrawItem( line1 );
1519  line1->SetWidth( Mils2iu( 10 ) );
1520  line1->AddPoint( { 0, 0 } );
1521  line1->AddPoint( { 0, Mils2iu( -200 ) } );
1522 
1523  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1524  aKPart->AddDrawItem( line2 );
1525  line2->SetWidth( Mils2iu( 10 ) );
1526  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -200 ) } );
1527  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -200 ) } );
1528 
1529  return { 0, Mils2iu( 250 ) };
1530  }
1531  else
1532  {
1533  if( aStyle != ASCH_POWER_PORT_STYLE::BAR )
1534  wxLogWarning( "Power Port has unknown style, use bar instead. " );
1535 
1536  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart );
1537  aKPart->AddDrawItem( line1 );
1538  line1->SetWidth( Mils2iu( 10 ) );
1539  line1->AddPoint( { 0, 0 } );
1540  line1->AddPoint( { 0, Mils2iu( -100 ) } );
1541 
1542  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1543  aKPart->AddDrawItem( line2 );
1544  line2->SetWidth( Mils2iu( 10 ) );
1545  line2->AddPoint( { Mils2iu( -50 ), Mils2iu( -100 ) } );
1546  line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -100 ) } );
1547 
1548  return { 0, Mils2iu( 150 ) };
1549  }
1550 }
1551 
1552 
1553 void SCH_ALTIUM_PLUGIN::ParsePowerPort( const std::map<wxString, wxString>& aProperties )
1554 {
1555  ASCH_POWER_PORT elem( aProperties );
1556 
1557  LIB_ID libId = AltiumToKiCadLibID( getLibName(), elem.text );
1558 
1559  LIB_PART* kpart = nullptr;
1560 
1561  const auto& symbol = m_powerSymbols.find( elem.text );
1562  if( symbol != m_powerSymbols.end() )
1563  {
1564  kpart = symbol->second; // cache hit
1565  }
1566  else
1567  {
1568  kpart = new LIB_PART( wxEmptyString );
1569  kpart->SetPower();
1570  kpart->SetName( elem.text );
1571  kpart->GetReferenceField().SetText( "#PWR" );
1572  kpart->GetValueField().SetText( elem.text );
1573  kpart->GetValueField().SetVisible( true ); // TODO: why does this not work?
1574  kpart->SetDescription( wxString::Format( _( "Power symbol creates a global label with name '%s'" ),
1575  elem.text ) );
1576  kpart->SetKeyWords( "power-flag" );
1577  kpart->SetLibId( libId );
1578 
1579  // generate graphic
1580  LIB_PIN* pin = new LIB_PIN( kpart );
1581  kpart->AddDrawItem( pin );
1582 
1583  pin->SetName( elem.text );
1584  pin->SetPosition( { 0, 0 } );
1585  pin->SetLength( 0 );
1586 
1587  // marks the pin as a global label
1589  pin->SetVisible( false );
1590 
1591  wxPoint valueFieldPos = HelperGeneratePowerPortGraphics( kpart, elem.style );
1592 
1593  kpart->GetValueField().SetPosition( valueFieldPos );
1594 
1595  // this has to be done after parsing the LIB_PART!
1596  m_pi->SaveSymbol( getLibFileName().GetFullPath(), kpart, m_properties.get() );
1597  m_powerSymbols.insert( { elem.text, kpart } );
1598  }
1599 
1600  SCH_SHEET_PATH sheetpath;
1602 
1603  // each component has its own symbol for now
1604  SCH_COMPONENT* component = new SCH_COMPONENT();
1605  component->SetRef( &sheetpath, "#PWR?" );
1606  component->SetValue( elem.text );
1607  component->SetLibId( libId );
1608  component->SetLibSymbol( new LIB_PART( *kpart ) );
1609 
1610  SCH_FIELD* valueField = component->GetField( VALUE_FIELD );
1611 
1612  // TODO: Why do I need to set those a second time?
1613  valueField->SetVisible( true );
1614  valueField->SetPosition( kpart->GetValueField().GetPosition() );
1615 
1616  component->SetPosition( elem.location + m_sheetOffset );
1617 
1618  switch( elem.orientation )
1619  {
1622  valueField->SetTextAngle( -900. );
1624  break;
1627  valueField->SetTextAngle( -1800. );
1629  break;
1632  valueField->SetTextAngle( -2700. );
1634  break;
1637  valueField->SetTextAngle( 0. );
1639  break;
1640  default:
1641  wxLogWarning( "Pin has unexpected orientation" );
1642  break;
1643  }
1644 
1645  m_currentSheet->GetScreen()->Append( component );
1646 }
1647 
1648 
1650 {
1651  // Get both connection points where we could connect to
1652  wxPoint start = aElem.location + m_sheetOffset;
1653  wxPoint end = start;
1654 
1655  switch( aElem.style )
1656  {
1657  default:
1659  case ASCH_PORT_STYLE::LEFT:
1662  end.x += aElem.width;
1663  break;
1665  case ASCH_PORT_STYLE::TOP:
1668  end.y -= aElem.width;
1669  break;
1670  }
1671 
1672  // Check which connection points exists in the schematic
1673  SCH_SCREEN* screen = m_currentSheet->GetScreen();
1674 
1675  bool startIsWireTerminal = screen->IsTerminalPoint( start, LAYER_WIRE );
1676  bool startIsBusTerminal = screen->IsTerminalPoint( start, LAYER_BUS );
1677 
1678  bool endIsWireTerminal = screen->IsTerminalPoint( end, LAYER_WIRE );
1679  bool endIsBusTerminal = screen->IsTerminalPoint( end, LAYER_BUS );
1680 
1681  // check if any of the points is a terminal point
1682  // TODO: there seems a problem to detect approximated connections towards component pins?
1683  bool connectionFound = startIsWireTerminal
1684  || startIsBusTerminal
1685  || endIsWireTerminal
1686  || endIsBusTerminal;
1687 
1688  if( !connectionFound )
1689  {
1690  wxLogError( wxString::Format( "There is a Port for \"%s\", but no connections towards it?",
1691  aElem.name ) );
1692  }
1693 
1694  // Select label position. In case both match, we will add a line later.
1695  wxPoint position = ( startIsWireTerminal || startIsBusTerminal ) ? start : end;
1696 
1697  SCH_TEXT* const label = new SCH_GLOBALLABEL( position, aElem.name );
1698  // TODO: detect correct label type depending on sheet settings, etc.
1699  // label = new SCH_HIERLABEL( elem.location + m_sheetOffset, elem.name );
1700 
1701  switch( aElem.iotype )
1702  {
1703  default:
1706  break;
1709  break;
1712  break;
1715  break;
1716  }
1717 
1718  switch( aElem.style )
1719  {
1720  default:
1722  case ASCH_PORT_STYLE::LEFT:
1725  if( ( startIsWireTerminal || startIsBusTerminal ) )
1727  else
1729  break;
1731  case ASCH_PORT_STYLE::TOP:
1734  if( ( startIsWireTerminal || startIsBusTerminal ) )
1736  else
1738  break;
1739  }
1740 
1741  label->SetFlags( IS_NEW );
1742  m_currentSheet->GetScreen()->Append( label );
1743 
1744  // This is a hack, for the case both connection points are valid: add a small wire
1745  if( ( startIsWireTerminal && endIsWireTerminal ) || !connectionFound )
1746  {
1747  SCH_LINE* wire = new SCH_LINE( start, SCH_LAYER_ID::LAYER_WIRE );
1748  wire->SetEndPoint( end );
1749  wire->SetLineWidth( Mils2iu( 2 ) );
1750  wire->SetFlags( IS_NEW );
1751  m_currentSheet->GetScreen()->Append( wire );
1752  }
1753  else if( startIsBusTerminal && endIsBusTerminal )
1754  {
1755  SCH_LINE* wire = new SCH_LINE( start, SCH_LAYER_ID::LAYER_BUS );
1756  wire->SetEndPoint( end );
1757  wire->SetLineWidth( Mils2iu( 2 ) );
1758  wire->SetFlags( IS_NEW );
1759  m_currentSheet->GetScreen()->Append( wire );
1760  }
1761 }
1762 
1763 
1764 void SCH_ALTIUM_PLUGIN::ParseNoERC( const std::map<wxString, wxString>& aProperties )
1765 {
1766  ASCH_NO_ERC elem( aProperties );
1767 
1768  if( elem.isActive )
1769  {
1770  SCH_NO_CONNECT* noConnect = new SCH_NO_CONNECT( elem.location + m_sheetOffset );
1771 
1772  noConnect->SetFlags( IS_NEW );
1773  m_currentSheet->GetScreen()->Append( noConnect );
1774  }
1775 }
1776 
1777 
1778 void SCH_ALTIUM_PLUGIN::ParseNetLabel( const std::map<wxString, wxString>& aProperties )
1779 {
1780  ASCH_NET_LABEL elem( aProperties );
1781 
1782  SCH_LABEL* label = new SCH_LABEL( elem.location + m_sheetOffset, elem.text );
1783 
1784  switch( elem.orientation )
1785  {
1788  break;
1791  break;
1794  break;
1797  break;
1798  default:
1799  break;
1800  }
1801 
1802  label->SetFlags( IS_NEW );
1803  m_currentSheet->GetScreen()->Append( label );
1804 }
1805 
1806 
1807 void SCH_ALTIUM_PLUGIN::ParseBus( const std::map<wxString, wxString>& aProperties )
1808 {
1809  ASCH_BUS elem( aProperties );
1810 
1811  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
1812  {
1813  SCH_LINE* bus =
1814  new SCH_LINE( elem.points.at( i ) + m_sheetOffset, SCH_LAYER_ID::LAYER_BUS );
1815  bus->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
1816  bus->SetLineWidth( elem.lineWidth );
1817 
1818  bus->SetFlags( IS_NEW );
1819  m_currentSheet->GetScreen()->Append( bus );
1820  }
1821 }
1822 
1823 
1824 void SCH_ALTIUM_PLUGIN::ParseWire( const std::map<wxString, wxString>& aProperties )
1825 {
1826  ASCH_WIRE elem( aProperties );
1827 
1828  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
1829  {
1830  SCH_LINE* wire =
1831  new SCH_LINE( elem.points.at( i ) + m_sheetOffset, SCH_LAYER_ID::LAYER_WIRE );
1832  wire->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
1833  wire->SetLineWidth( elem.lineWidth );
1834 
1835  wire->SetFlags( IS_NEW );
1836  m_currentSheet->GetScreen()->Append( wire );
1837  }
1838 }
1839 
1840 
1841 void SCH_ALTIUM_PLUGIN::ParseJunction( const std::map<wxString, wxString>& aProperties )
1842 {
1843  ASCH_JUNCTION elem( aProperties );
1844 
1845  SCH_JUNCTION* junction = new SCH_JUNCTION( elem.location + m_sheetOffset );
1846 
1847  junction->SetFlags( IS_NEW );
1848  m_currentSheet->GetScreen()->Append( junction );
1849 }
1850 
1851 
1852 void SCH_ALTIUM_PLUGIN::ParseSheet( const std::map<wxString, wxString>& aProperties )
1853 {
1854  m_altiumSheet = std::make_unique<ASCH_SHEET>( aProperties );
1855 
1856  PAGE_INFO pageInfo;
1857 
1858  bool isPortrait = m_altiumSheet->sheetOrientation == ASCH_SHEET_WORKSPACEORIENTATION::PORTRAIT;
1859  switch( m_altiumSheet->sheetSize )
1860  {
1861  default:
1862  case ASCH_SHEET_SIZE::A4:
1863  pageInfo.SetType( "A4", isPortrait );
1864  break;
1865  case ASCH_SHEET_SIZE::A3:
1866  pageInfo.SetType( "A3", isPortrait );
1867  break;
1868  case ASCH_SHEET_SIZE::A2:
1869  pageInfo.SetType( "A2", isPortrait );
1870  break;
1871  case ASCH_SHEET_SIZE::A1:
1872  pageInfo.SetType( "A1", isPortrait );
1873  break;
1874  case ASCH_SHEET_SIZE::A0:
1875  pageInfo.SetType( "A0", isPortrait );
1876  break;
1877  case ASCH_SHEET_SIZE::A:
1878  pageInfo.SetType( "A", isPortrait );
1879  break;
1880  case ASCH_SHEET_SIZE::B:
1881  pageInfo.SetType( "B", isPortrait );
1882  break;
1883  case ASCH_SHEET_SIZE::C:
1884  pageInfo.SetType( "C", isPortrait );
1885  break;
1886  case ASCH_SHEET_SIZE::D:
1887  pageInfo.SetType( "D", isPortrait );
1888  break;
1889  case ASCH_SHEET_SIZE::E:
1890  pageInfo.SetType( "E", isPortrait );
1891  break;
1893  pageInfo.SetType( "USLetter", isPortrait );
1894  break;
1896  pageInfo.SetType( "USLegal", isPortrait );
1897  break;
1899  pageInfo.SetType( "A3", isPortrait ); // TODO: use User
1900  break;
1902  pageInfo.SetType( "A", isPortrait );
1903  break;
1905  pageInfo.SetType( "B", isPortrait );
1906  break;
1908  pageInfo.SetType( "C", isPortrait );
1909  break;
1911  pageInfo.SetType( "D", isPortrait );
1912  break;
1914  pageInfo.SetType( "E", isPortrait );
1915  break;
1916  }
1917 
1918  m_currentSheet->GetScreen()->SetPageSettings( pageInfo );
1919 
1920  m_sheetOffset = { 0, pageInfo.GetHeightIU() };
1921 }
1922 
1923 
1925 {
1926  switch( aOrientation )
1927  {
1928  default:
1930  aField.SetTextAngle( 0 );
1931  break;
1933  aField.SetTextAngle( 900 );
1934  break;
1936  aField.SetTextAngle( 1800 );
1937  break;
1939  aField.SetTextAngle( 2700 );
1940  break;
1941  }
1942 }
1943 
1944 
1945 void SCH_ALTIUM_PLUGIN::ParseSheetName( const std::map<wxString, wxString>& aProperties )
1946 {
1947  ASCH_SHEET_NAME elem( aProperties );
1948 
1949  const auto& sheet = m_sheets.find( elem.ownerindex );
1950  if( sheet == m_sheets.end() )
1951  {
1952  wxLogError( wxString::Format( "Sheet Name has non-existent ownerindex %d",
1953  elem.ownerindex ) );
1954  return;
1955  }
1956 
1957  SCH_FIELD& sheetNameField = sheet->second->GetFields()[SHEETNAME];
1958 
1959  sheetNameField.SetPosition( elem.location + m_sheetOffset );
1960  sheetNameField.SetText( elem.text );
1961  sheetNameField.SetVisible( !elem.isHidden );
1962 
1965 
1966  SetFieldOrientation( sheetNameField, elem.orientation );
1967 }
1968 
1969 
1970 void SCH_ALTIUM_PLUGIN::ParseFileName( const std::map<wxString, wxString>& aProperties )
1971 {
1972  ASCH_FILE_NAME elem( aProperties );
1973 
1974  const auto& sheet = m_sheets.find( elem.ownerindex );
1975  if( sheet == m_sheets.end() )
1976  {
1977  wxLogError( wxString::Format( "File Name has non-existent ownerindex %d",
1978  elem.ownerindex ) );
1979  return;
1980  }
1981 
1982  SCH_FIELD& filenameField = sheet->second->GetFields()[SHEETFILENAME];
1983 
1984  filenameField.SetPosition( elem.location + m_sheetOffset );
1985 
1986  // If last symbols are ".sChDoC", change them to ".kicad_sch"
1987  if( ( elem.text.Right( GetFileExtension().length() + 1 ).Lower() ) == ( "." + GetFileExtension().Lower() ))
1988  {
1989  elem.text.RemoveLast( GetFileExtension().length() );
1991  }
1992 
1993  filenameField.SetText( elem.text );
1994 
1995  filenameField.SetVisible( !elem.isHidden );
1996 
1999 
2000  SetFieldOrientation( filenameField, elem.orientation );
2001 }
2002 
2003 
2004 void SCH_ALTIUM_PLUGIN::ParseDesignator( const std::map<wxString, wxString>& aProperties )
2005 {
2006  ASCH_DESIGNATOR elem( aProperties );
2007 
2008  const auto& symbol = m_symbols.find( elem.ownerindex );
2009  if( symbol == m_symbols.end() )
2010  {
2011  // TODO: e.g. can depend on Template (RECORD=39
2012  wxLogWarning( wxString::Format( "Designator has non-existent ownerindex %d",
2013  elem.ownerindex ) );
2014  return;
2015  }
2016 
2017  const auto& component = m_components.at( symbol->first );
2018 
2019  SCH_SHEET_PATH sheetpath;
2021 
2022  component->SetRef( &sheetpath, elem.text );
2023 
2024  SCH_FIELD* refField = component->GetField( REFERENCE_FIELD );
2025 
2026  refField->SetPosition( elem.location + m_sheetOffset );
2027  refField->SetVisible( true );
2028 
2031 
2032  SetFieldOrientation( *refField, elem.orientation );
2033 }
2034 
2035 
2036 void SCH_ALTIUM_PLUGIN::ParseBusEntry( const std::map<wxString, wxString>& aProperties )
2037 {
2038  ASCH_BUS_ENTRY elem( aProperties );
2039 
2040  SCH_BUS_WIRE_ENTRY* busWireEntry = new SCH_BUS_WIRE_ENTRY( elem.location + m_sheetOffset );
2041 
2042  wxPoint vector = elem.corner - elem.location;
2043  busWireEntry->SetSize( { vector.x, vector.y } );
2044 
2045  busWireEntry->SetFlags( IS_NEW );
2046  m_currentSheet->GetScreen()->Append( busWireEntry );
2047 }
2048 
2049 
2050 void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map<wxString, wxString>& aProperties )
2051 {
2052  ASCH_PARAMETER elem( aProperties );
2053 
2054  if( elem.ownerindex <= 0 && elem.ownerpartid == ALTIUM_COMPONENT_NONE )
2055  {
2056  // This is some sheet parameter
2057  if( elem.text == "*" )
2058  return; // indicates parameter not set?
2059 
2060  SCH_SHEET_PATH sheetpath;
2062 
2063  if( elem.name == "SheetNumber" )
2064  m_rootSheet->SetPageNumber( sheetpath, elem.text );
2065  else if( elem.name == "Title" )
2066  m_currentTitleBlock->SetTitle( elem.text );
2067  else if( elem.name == "Revision" )
2068  m_currentTitleBlock->SetRevision( elem.text );
2069  else if( elem.name == "Date" )
2070  m_currentTitleBlock->SetDate( elem.text );
2071  else if( elem.name == "CompanyName" )
2072  m_currentTitleBlock->SetCompany( elem.text );
2073  // TODO: parse other parameters
2074  // TODO: handle parameters in labels
2075  }
2076  else
2077  {
2078  const auto& symbol = m_symbols.find( elem.ownerindex );
2079  if( symbol == m_symbols.end() )
2080  {
2081  // TODO: e.g. can depend on Template (RECORD=39
2082  return;
2083  }
2084 
2085  const auto& component = m_components.at( symbol->first );
2086 
2087  // TODO: location not correct?
2088  const wxPoint position = elem.location + m_sheetOffset;
2089 
2090  SCH_FIELD* field = nullptr;
2091  if( elem.name == "Value" )
2092  {
2093  field = component->GetField( VALUE_FIELD );
2094  field->SetPosition( position );
2095  }
2096  else
2097  {
2098  int fieldIdx = component->GetFieldCount();
2099  field = component->AddField( { position, fieldIdx, component, elem.name } );
2100  }
2101 
2102  // TODO: improve text replacement (https://gitlab.com/kicad/code/kicad/-/issues/6256)
2103  if( elem.text == "=Value" && field->GetId() != VALUE_FIELD )
2104  field->SetText( "${VALUE}" );
2105  else
2106  field->SetText( elem.text );
2107 
2108  field->SetVisible( !elem.isHidden );
2110 
2111  switch( elem.orientation )
2112  {
2113  case ASCH_RECORD_ORIENTATION::RIGHTWARDS: field->SetTextAngle( 0 ); break;
2114  case ASCH_RECORD_ORIENTATION::UPWARDS: field->SetTextAngle( 90 ); break;
2115  case ASCH_RECORD_ORIENTATION::LEFTWARDS: field->SetTextAngle( 180 ); break;
2116  case ASCH_RECORD_ORIENTATION::DOWNWARDS: field->SetTextAngle( 270 ); break;
2117  default:
2118  break;
2119  }
2120  }
2121 }
Field Reference of part, i.e. "IC21".
void ParsePort(const ASCH_PORT &aElem)
wxPoint location
power input (GND, VCC for ICs). Must be connected to a power output.
static const wxString & GetSymbolLibTableFileName()
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:51
std::unique_ptr< PROPERTIES > m_properties
void SetModified()
Definition: eda_item.cpp:79
ASCH_RECORD_ORIENTATION orientation
void SetShape(PINSHEETLABEL_SHAPE aShape)
Definition: sch_text.h:237
static int PropertiesReadInt(const std::map< wxString, wxString > &aProperties, const wxString &aKey, int aDefault)
void ParseLabel(const std::map< wxString, wxString > &aProperties)
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib=false)
Replace illegal LIB_ID item name characters with underscores '_'.
Definition: lib_id.cpp:347
void SetLibSymbol(LIB_PART *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
Definition: sch_symbol.cpp:243
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_PLUGIN obje...
void SetLibId(const LIB_ID &aName)
Definition: sch_symbol.cpp:224
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
void ParseBezier(const std::map< wxString, wxString > &aProperties)
void SetPower()
Definition: lib_symbol.cpp:420
COLOR4D & FromCSSRGBA(int aRed, int aGreen, int aBlue, double aAlpha=1.0)
Initialize the color from a RGBA value with 0-255 red/green/blue and 0-1 alpha.
Definition: color4d.cpp:476
void SetEdaTextJustification(EDA_TEXT *text, ASCH_LABEL_JUSTIFICATION justification)
int distanceFromTop
void ParsePowerPort(const std::map< wxString, wxString > &aProperties)
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
void ParseJunction(const std::map< wxString, wxString > &aProperties)
Holds all the data relating to one schematic A schematic may consist of one or more sheets (and one r...
Definition: schematic.h:58
void SetSize(const wxSize &aSize)
Definition: sch_bus_entry.h:64
wxPoint GetPosition() const override
Definition: lib_field.h:180
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
Define a symbol library graphical text item.
Definition: lib_text.h:40
ASCH_PORT_IOTYPE iotype
void GetPoly(std::vector< wxPoint > &aOutput, int aMinSegLen=0)
Convert a Bezier curve to a polygon.
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: lib_pin.h:129
void SetLineWidth(const int aSize)
Definition: sch_line.cpp:271
void ParseParameter(const std::map< wxString, wxString > &aProperties)
size_t GetRemainingBytes() const
void Parse(const CFB::CompoundFileReader &aReader)
SCH_SHEET * Load(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const PROPERTIES *aProperties=nullptr) override
Load information from some input file format that this SCH_PLUGIN implementation knows about,...
void ParseRoundRectangle(const std::map< wxString, wxString > &aProperties)
std::vector< wxPoint > points
void SetItalic(bool isItalic)
Definition: eda_text.h:186
int color
Definition: DXF_plotter.cpp:60
void SetFillMode(FILL_TYPE aFillMode)
Definition: lib_item.h:267
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:155
pin for passive components: must be connected, and can be connected to any pin
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition: schematic.h:130
TRANSFORM InverseTransform() const
Calculate the Inverse mirror/rotation transform.
Definition: transform.cpp:59
const wxString GetName() const override
Returns a brief hard coded name for this SCH_PLUGIN.
void SetVisible(bool aVisible)
Definition: eda_text.h:192
ASCH_LABEL_JUSTIFICATION
void SetFirstRadiusAngle(int aAngle)
Definition: lib_arc.h:105
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
Definition: page_info.cpp:119
ASCH_LABEL_JUSTIFICATION justification
int GetId() const
Definition: sch_field.h:120
int ownerpartdisplaymode
LIB_FIELD & GetValueField()
Return reference to the value field.
Definition: lib_symbol.cpp:977
void ParseBusEntry(const std::map< wxString, wxString > &aProperties)
unknown electrical properties: creates always a warning when connected
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: sch_screen.h:188
void ParseSheet(const std::map< wxString, wxString > &aProperties)
void SetLength(int aLength)
Definition: lib_pin.h:132
void SetPosition(const wxPoint &aPosition) override
Definition: sch_symbol.h:681
ASCH_POWER_PORT_STYLE style
void ParsePolygon(const std::map< wxString, wxString > &aProperties)
void set(SCH_PLUGIN *aPlugin)
Definition: sch_io_mgr.h:498
ASCH_PORT_STYLE style
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:244
Definition: lib_pin.h:50
std::map< int, ASCH_COMPONENT > m_altiumComponents
wxPoint corner
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
const wxPoint GetRelativePosition(const wxPoint &aPosition, const SCH_COMPONENT *aComponent)
A name/value tuple with unique names and optional values.
Definition: properties.h:33
void SetPosition(const wxPoint &aPos) override
Definition: lib_pin.h:259
void SetWidth(int aWidth) override
Definition: lib_polyline.h:103
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:285
virtual const wxString GetProjectPath() const
Return the full path of the project.
std::map< wxString, LIB_PART * > m_powerSymbols
void SetPageNumber(const SCH_SHEET_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
Definition: sch_sheet.cpp:1125
wxPoint TransformCoordinate(const wxPoint &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:42
std::map< int, SCH_SHEET * > m_sheets
COLOR4D GetColorFromInt(int color)
void SetEndPoint(const wxPoint &aPosition)
Definition: sch_line.h:98
void ParseRectangle(const std::map< wxString, wxString > &aProperties)
void ParsePolyline(const std::map< wxString, wxString > &aProperties)
virtual void SetElem(ELEM_T aIndex, _ELEM *aElem)
ASCH_RECORD_ORIENTATION orientation
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
const CFB::COMPOUND_FILE_ENTRY * FindStream(const CFB::CompoundFileReader &aReader, const char *aStreamName)
std::vector< ASCH_PORT > m_altiumPortsCurrentSheet
wxPoint location
ASCH_RECORD_ORIENTATION orientation
void SetLineStyle(const PLOT_DASH_TYPE aStyle)
Definition: sch_line.cpp:239
ASCH_RECORD_ORIENTATION orientation
std::map< wxString, wxString > ReadProperties()
void SetType(ELECTRICAL_PINTYPE aType)
Definition: lib_pin.h:135
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
void SetFileName(wxString aFilename)
Definition: sch_sheet.h:505
int ownerindex
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:297
LIB_FIELD & GetReferenceField()
Return reference to the reference designator field.
Definition: lib_symbol.cpp:985
void SetFlags(STATUS_FLAGS aMask)
Definition: eda_item.h:202
Field Value of part, i.e. "3.3K".
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:121
void ParseLine(const std::map< wxString, wxString > &aProperties)
#define NULL
void SetWidth(int aWidth) override
Definition: lib_rectangle.h:86
void SetFieldOrientation(SCH_FIELD &aField, ASCH_RECORD_ORIENTATION aOrientation)
ASCH_RECORD_ORIENTATION
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
wxFileName getLibFileName()
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:53
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:209
void SetDescription(const wxString &aDescription)
Definition: lib_symbol.h:136
std::unique_ptr< ASCH_SHEET > m_altiumSheet
void ParseSheetEntry(const std::map< wxString, wxString > &aProperties)
void SetEdge(SHEET_SIDE aEdge)
std::vector< wxPoint > points
void SetRadius(int aRadius)
Definition: lib_circle.h:87
Define a library symbol object.
Definition: lib_symbol.h:93
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:294
Definition of file extensions used in Kicad.
void SetVisible(bool aVisible)
Definition: lib_pin.h:148
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
int GetModifyHash() const override
Return the modification hash from the library cache.
wxPoint HelperGeneratePowerPortGraphics(LIB_PART *aKPart, ASCH_POWER_PORT_STYLE aStyle)
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet.h:85
int ownerpartdisplaymode
ASCH_RECORD_ORIENTATION orientation
void SetUnit(int aUnit)
Change the unit number to aUnit.
Definition: sch_symbol.cpp:317
TRANSFORM & GetTransform()
Definition: sch_symbol.h:272
void ParseFileName(const std::map< wxString, wxString > &aProperties)
LIB_ID AltiumToKiCadLibID(wxString aLibName, wxString aLibReference)
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
virtual void Format(OUTPUTFORMATTER *aOutput, int aIndentLevel) const override
Generate the table in s-expression format to aOutput with an indention level of aIndentLevel.
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:499
void AddPoint(const wxPoint &aPoint)
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: sch_screen.h:199
void ParseNoERC(const std::map< wxString, wxString > &aProperties)
wxString name
std::vector< wxPoint > points
void SetSecondRadiusAngle(int aAngle)
Definition: lib_arc.h:108
SCH_SHEET * m_currentSheet
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:219
void SetSize(const wxSize &aSize)
Definition: sch_sheet.h:288
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
wxString designator
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
ASCH_PORT_IOTYPE iotype
wxString componentdescription
const wxString GetLibraryFileExtension() const override
Return the library file extension for the SCH_PLUGIN object.
void SetPosition(const wxPoint &aPosition) override
Definition: sch_sheet.h:206
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
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
void ParseComponent(int aIndex, const std::map< wxString, wxString > &aProperties)
Bezier curves to polygon converter.
Definition: bezier_curves.h:36
SCH_SHEET & Root() const
Definition: schematic.h:116
bool IsTerminalPoint(const wxPoint &aPosition, int aLayer)
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:483
void SetEnd(const wxPoint &aEnd)
Definition: lib_rectangle.h:88
void ParseSheetSymbol(int aIndex, const std::map< wxString, wxString > &aProperties)
void SetName(const wxString &aName)
Definition: lib_pin.h:157
const char * name
Definition: DXF_plotter.cpp:59
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:127
ASCH_SHEET_ENTRY_SIDE side
ASCH_RECORD_ORIENTATION orientation
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:208
double startAngle
ASCH_PIN_SYMBOL_OUTEREDGE symbolOuterEdge
#define _(s)
Definition: 3d_actions.cpp:33
usual pin input: must be connected
void ParseWire(const std::map< wxString, wxString > &aProperties)
void ParseSheetName(const std::map< wxString, wxString > &aProperties)
void SetKeyWords(const wxString &aKeyWords)
Definition: lib_symbol.h:149
const wxString GetFileExtension() const override
Returns the file extension for the SCH_PLUGIN.
void SetRadius(int aRadius)
Definition: lib_arc.h:102
std::map< int, LIB_PART * > m_symbols
const std::string KiCadSchematicFileExtension
Schematic symbol object.
Definition: sch_symbol.h:78
wxPoint GetPosition() const override
Definition: sch_symbol.h:680
void ParseArc(const std::map< wxString, wxString > &aProperties)
Used for text file output.
Definition: richio.h:453
ASCH_POLYLINE_LINESTYLE linestyle
void ParseBus(const std::map< wxString, wxString > &aProperties)
Class for a wire to bus entry.
void SetWidth(int aWidth) override
Definition: lib_circle.h:85
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:314
void SetPosition(const wxPoint &aPosition) override
Definition: lib_item.h:215
ASCH_RECORD_ORIENTATION orientation
wxPoint location
virtual const wxString GetProjectName() const
Return the short name of the project.
input or output (like port for a microprocessor)
const int ALTIUM_COMPONENT_NONE
std::vector< wxPoint > points
void ParseAltiumSch(const wxString &aFileName)
ASCH_POWER_PORT_STYLE
virtual void SetTextAngle(double aAngle)
Definition: eda_text.h:174
int ownerpartdisplaymode
void ParseDesignator(const std::map< wxString, wxString > &aProperties)
void SetFileName(const wxString &aFileName)
Definition: sch_screen.h:190
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
void SetValue(const SCH_SHEET_PATH *sheet, const wxString &aValue)
Definition: sch_symbol.cpp:609
ASCH_PIN_ELECTRICAL electrical
bool CheckHeader(const wxString &aFileName) override
Return true if the first line in aFileName begins with the expected header.
void ParsePin(const std::map< wxString, wxString > &aProperties)
wxPoint center
void SetWidth(int aWidth) override
Definition: lib_bezier.h:87
std::map< int, SCH_COMPONENT * > m_components
SCH_PLUGIN::SCH_PLUGIN_RELEASER m_pi
void SetBold(bool aBold)
Definition: eda_text.h:189
ASCH_PIN_SYMBOL_INNEREDGE symbolInnerEdge
void ParseNetLabel(const std::map< wxString, wxString > &aProperties)
void SetLibId(const LIB_ID &aLibId)
Definition: lib_symbol.h:132
void SetPosition(const wxPoint &aPosition) override
Definition: sch_field.cpp:650
ALTIUM_SCH_RECORD
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
bool HasParsingError()
#define IS_NEW
New item, just created.
Definition: eda_item.h:106
void AddPoint(const wxPoint &aPoint)
Definition: lib_bezier.h:58
bool IsComponentPartVisible(int aOwnerindex, int aOwnerpartdisplaymode) const
std::unique_ptr< TITLE_BLOCK > m_currentTitleBlock
Define a bezier curve graphic body item.
Definition: lib_bezier.h:34
std::vector< wxPoint > points
const std::string KiCadSymbolLibFileExtension
void SetOrientation(int aOrientation)
Compute the new transform matrix based on aOrientation for the symbol which is applied to the current...
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:98
wxString name