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  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <memory>
25 
26 #include "altium_parser_sch.h"
30 
31 #include <schematic.h>
32 
33 #include <lib_arc.h>
34 #include <lib_bezier.h>
35 #include <lib_circle.h>
36 #include <lib_id.h>
37 #include <lib_item.h>
38 #include <lib_pin.h>
39 #include <lib_polyline.h>
40 #include <lib_rectangle.h>
41 #include <lib_text.h>
42 
43 #include <bus_alias.h>
44 #include <sch_bitmap.h>
45 #include <sch_bus_entry.h>
46 #include <sch_component.h>
47 #include <sch_junction.h>
48 #include <sch_line.h>
49 #include <sch_no_connect.h>
50 #include <sch_screen.h>
51 #include <sch_sheet.h>
52 #include <sch_text.h>
53 
54 #include <bezier_curves.h>
55 #include <compoundfilereader.h>
56 #include <kicad_string.h>
57 #include <sch_edit_frame.h>
59 #include <wx/textfile.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 SCH_SHEET* SCH_ALTIUM_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchematic,
155  SCH_SHEET* aAppendToMe, const PROPERTIES* aProperties )
156 {
157  wxASSERT( !aFileName || aSchematic != NULL );
158 
159  m_filename = aFileName;
160  m_schematic = aSchematic;
161 
162  // Delete on exception, if I own m_rootSheet, according to aAppendToMe
163  std::unique_ptr<SCH_SHEET> deleter( aAppendToMe ? nullptr : m_rootSheet );
164 
165  if( aAppendToMe )
166  {
167  wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
168  m_rootSheet = &aSchematic->Root();
169  }
170  else
171  {
172  m_rootSheet = new SCH_SHEET( aSchematic );
173  m_rootSheet->SetFileName( aFileName );
174  }
175 
176  if( !m_rootSheet->GetScreen() )
177  {
178  SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
179  screen->SetFileName( aFileName );
180  m_rootSheet->SetScreen( screen );
181  }
182 
183  SYMBOL_LIB_TABLE* libTable = m_schematic->Prj().SchSymbolLibTable();
184 
185  wxCHECK_MSG( libTable, NULL, "Could not load symbol lib table." );
186 
187  m_pi.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
188 
191  if( !libTable->HasLibrary( getLibName() ) )
192  {
193  // Create a new empty symbol library.
194  m_pi->CreateSymbolLib( getLibFileName().GetFullPath() );
195  wxString libTableUri = "${KIPRJMOD}/" + getLibFileName().GetFullName();
196 
197  // Add the new library to the project symbol library table.
198  libTable->InsertRow(
199  new SYMBOL_LIB_TABLE_ROW( getLibName(), libTableUri, wxString( "KiCad" ) ) );
200 
201  // Save project symbol library table.
202  wxFileName fn( m_schematic->Prj().GetProjectPath(),
204 
205  // So output formatter goes out of scope and closes the file before reloading.
206  {
207  FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() );
208  libTable->Format( &formatter, 0 );
209  }
210 
211  // Reload the symbol library table.
213  m_schematic->Prj().SchSymbolLibTable();
214  }
215 
217  ParseAltiumSch( aFileName );
218 
219  m_pi->SaveLibrary( getLibFileName().GetFullPath() );
220 
221  return m_rootSheet;
222 }
223 
224 
225 /*wxString SCH_EAGLE_PLUGIN::fixSymbolName( const wxString& aName )
226 {
227  wxString ret = LIB_ID::FixIllegalChars( aName, LIB_ID::ID_SCH );
228 
229  return ret;
230 }*/
231 
232 void SCH_ALTIUM_PLUGIN::ParseAltiumSch( const wxString& aFileName )
233 {
234  // Open file
235  FILE* fp = wxFopen( aFileName, "rb" );
236  if( fp == nullptr )
237  {
238  wxLogError( wxString::Format( _( "Cannot open file '%s'" ), aFileName ) );
239  return;
240  }
241 
242  fseek( fp, 0, SEEK_END );
243  long len = ftell( fp );
244  if( len < 0 )
245  {
246  fclose( fp );
247  THROW_IO_ERROR( "Reading error, cannot determine length of file" );
248  }
249 
250  std::unique_ptr<unsigned char[]> buffer( new unsigned char[len] );
251  fseek( fp, 0, SEEK_SET );
252 
253  size_t bytesRead = fread( buffer.get(), sizeof( unsigned char ), len, fp );
254  fclose( fp );
255  if( static_cast<size_t>( len ) != bytesRead )
256  {
257  THROW_IO_ERROR( "Reading error" );
258  }
259 
260  try
261  {
262  CFB::CompoundFileReader reader( buffer.get(), bytesRead );
263  Parse( reader );
264  }
265  catch( CFB::CFBException& exception )
266  {
267  THROW_IO_ERROR( exception.what() );
268  }
269 }
270 
271 
272 void SCH_ALTIUM_PLUGIN::Parse( const CFB::CompoundFileReader& aReader )
273 {
274  const CFB::COMPOUND_FILE_ENTRY* file = FindStream( aReader, "FileHeader" );
275  if( file == nullptr )
276  {
277  THROW_IO_ERROR( "FileHeader not found" );
278  }
279 
280  ALTIUM_PARSER reader( aReader, file );
281 
282  if( reader.GetRemainingBytes() <= 0 )
283  {
284  THROW_IO_ERROR( "FileHeader does not contain any data" );
285  }
286  else
287  {
288  std::map<wxString, wxString> properties = reader.ReadProperties();
289 
290  int recordId = ALTIUM_PARSER::PropertiesReadInt( properties, "RECORD", 0 );
291  ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
292 
293  if( record != ALTIUM_SCH_RECORD::HEADER )
294  {
295  THROW_IO_ERROR( "Header expected" );
296  }
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  {
441  THROW_IO_ERROR( "stream was not parsed correctly!" );
442  }
443 
444  if( reader.GetRemainingBytes() != 0 )
445  {
446  THROW_IO_ERROR( "stream is not fully parsed" );
447  }
448 
449  // assign LIB_PART -> COMPONENT
450  for( auto component : m_components )
451  {
452  auto kpart = m_symbols.find( component.first );
453  if( kpart == m_symbols.end() )
454  {
455  THROW_IO_ERROR( "every component should have a symbol attached" );
456  }
457 
458  m_pi->SaveSymbol( getLibFileName().GetFullPath(), new LIB_PART( *( kpart->second ) ),
459  m_properties.get() );
460 
461  component.second->SetLibSymbol( kpart->second );
462  }
463 
464  // Handle title blocks
466  m_currentTitleBlock.reset();
467 
468  // Handle Ports
469  for( const ASCH_PORT& port : m_altiumPortsCurrentSheet )
470  {
471  ParsePort( port );
472  }
474 
475  m_components.clear();
476  m_symbols.clear();
477 
478  // Otherwise we cannot save the imported sheet?
480 }
481 
482 
483 bool SCH_ALTIUM_PLUGIN::IsComponentPartVisible( int aOwnerindex, int aOwnerpartdisplaymode ) const
484 {
485  const auto& component = m_altiumComponents.find( aOwnerindex );
486  if( component == m_altiumComponents.end() )
487  return false;
488 
489  return component->second.displaymode == aOwnerpartdisplaymode;
490 }
491 
492 
494  int aIndex, const std::map<wxString, wxString>& aProperties )
495 {
496  auto pair = m_altiumComponents.insert( { aIndex, ASCH_COMPONENT( aProperties ) } );
497  const ASCH_COMPONENT& elem = pair.first->second;
498 
499  // TODO: this is a hack until we correctly apply all transformations to every element
500  wxString name = wxString::Format(
501  "%d%s_%s", elem.orientation, elem.isMirrored ? "_mirrored" : "", elem.libreference );
503 
504  LIB_PART* kpart = new LIB_PART( wxEmptyString );
505  kpart->SetName( name );
506  kpart->SetDescription( elem.componentdescription );
507  kpart->SetLibId( libId );
508  m_symbols.insert( { aIndex, kpart } );
509 
510  // each component has its own symbol for now
511  SCH_COMPONENT* component = new SCH_COMPONENT();
512 
513  component->SetPosition( elem.location + m_sheetOffset );
514  //component->SetOrientation( elem.orientation ); // TODO: keep it simple for now, and only set position
515  component->SetLibId( libId );
516  //component->SetLibSymbol( kpart ); // this has to be done after parsing the LIB_PART!
517 
518  component->SetUnit( elem.currentpartid );
519 
520  m_currentSheet->GetScreen()->Append( component );
521 
522  m_components.insert( { aIndex, component } );
523 }
524 
525 
526 void SCH_ALTIUM_PLUGIN::ParsePin( const std::map<wxString, wxString>& aProperties )
527 {
528  ASCH_PIN elem( aProperties );
529 
530  const auto& symbol = m_symbols.find( elem.ownerindex );
531  if( symbol == m_symbols.end() )
532  {
533  // TODO: e.g. can depend on Template (RECORD=39
534  wxLogWarning( wxString::Format(
535  "Pin tries to access symbol with ownerindex %d which does not exist",
536  elem.ownerindex ) );
537  return;
538  }
539 
541  return;
542 
543  const auto& component = m_components.at( symbol->first );
544 
545  LIB_PIN* pin = new LIB_PIN( symbol->second );
546  symbol->second->AddDrawItem( pin );
547 
548  pin->SetUnit( elem.ownerpartid );
549 
550  pin->SetName( elem.name );
551  pin->SetNumber( elem.designator );
552  pin->SetLength( elem.pinlength );
553 
554  wxPoint pinLocation = elem.location; // the location given is not the connection point!
555  switch( elem.orientation )
556  {
559  pinLocation.x += elem.pinlength;
560  break;
563  pinLocation.y -= elem.pinlength;
564  break;
567  pinLocation.x -= elem.pinlength;
568  break;
571  pinLocation.y += elem.pinlength;
572  break;
573  default:
574  wxLogWarning( "Pin has unexpected orientation" );
575  break;
576  }
577 
578  // TODO: position can be sometimes off a little bit!
579  pin->SetPosition( GetRelativePosition( pinLocation + m_sheetOffset, component ) );
580  // TODO: the following fix is even worse for now?
581  // pin->SetPosition( GetRelativePosition( elem.kicadLocation, component ) );
582 
583  switch( elem.electrical )
584  {
587  break;
590  break;
593  break;
596  break;
599  break;
602  break;
605  break;
608  break;
610  default:
612  wxLogWarning( "Pin has unexpected electrical type" );
613  break;
614  }
615 
617  wxLogWarning( "Pin has unexpected outer edge type" );
618 
620  wxLogWarning( "Pin has unexpected inner edge type" );
621 
623  {
624  switch( elem.symbolInnerEdge )
625  {
628  break;
629  default:
631  break;
632  }
633  }
635  {
636  switch( elem.symbolInnerEdge )
637  {
640  break;
641  default:
643  break;
644  }
645  }
647  {
649  }
650  else
651  {
652  switch( elem.symbolInnerEdge )
653  {
656  break;
657  default:
658  pin->SetShape( GRAPHIC_PINSHAPE::LINE ); // nothing to do
659  break;
660  }
661  }
662 }
663 
664 
666 {
667  switch( justification )
668  {
669  default:
675  break;
680  break;
685  break;
686  }
687 
688  switch( justification )
689  {
690  default:
696  break;
701  break;
706  break;
707  }
708 }
709 
710 
711 void SCH_ALTIUM_PLUGIN::ParseLabel( const std::map<wxString, wxString>& aProperties )
712 {
713  ASCH_LABEL elem( aProperties );
714 
715  // TODO: text variable support
716  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
717  {
718  SCH_TEXT* text = new SCH_TEXT( elem.location + m_sheetOffset, elem.text );
719  text->SetMirrored( elem.isMirrored );
720 
722 
723  size_t fontId = static_cast<int>( elem.fontId );
724  if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
725  {
726  const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
727  text->SetItalic( font.italic );
728  text->SetBold( font.bold );
729  text->SetTextSize( { font.size / 2, font.size / 2 } );
730  }
731 
732  text->SetFlags( IS_NEW );
733  m_currentSheet->GetScreen()->Append( text );
734  }
735  else
736  {
737  const auto& symbol = m_symbols.find( elem.ownerindex );
738  if( symbol == m_symbols.end() )
739  {
740  // TODO: e.g. can depend on Template (RECORD=39
741  wxLogWarning( wxString::Format(
742  "Label tries to access symbol with ownerindex %d which does not exist",
743  elem.ownerindex ) );
744  return;
745  }
746 
747  const auto& component = m_components.at( symbol->first );
748 
749  LIB_TEXT* text = new LIB_TEXT( symbol->second );
750  symbol->second->AddDrawItem( text );
751 
752  text->SetUnit( elem.ownerpartid );
753 
754  text->SetPosition( GetRelativePosition( elem.location + m_sheetOffset, component ) );
755  text->SetText( elem.text );
756 
758 
759  size_t fontId = static_cast<int>( elem.fontId );
760  if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
761  {
762  const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
763  text->SetItalic( font.italic );
764  text->SetBold( font.bold );
765  text->SetTextSize( { font.size / 2, font.size / 2 } );
766  }
767  }
768 }
769 
770 
771 void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProperties )
772 {
773  ASCH_BEZIER elem( aProperties );
774 
775  if( elem.points.size() < 2 )
776  {
777  wxLogWarning( wxString::Format( "Bezier has %d control points. At least 2 are expected.",
778  static_cast<int>( elem.points.size() ) ) );
779  return;
780  }
781 
782  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
783  {
784  for( size_t i = 0; i + 1 < elem.points.size(); i += 3 )
785  {
786  if( i + 2 == elem.points.size() )
787  {
788  // special case: single line
789  SCH_LINE* line = new SCH_LINE(
791  line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
792  line->SetLineWidth( elem.lineWidth );
794 
795  line->SetFlags( IS_NEW );
796  m_currentSheet->GetScreen()->Append( line );
797  }
798  else
799  {
800  // simulate bezier using line segments
801  std::vector<wxPoint> bezierPoints;
802  std::vector<wxPoint> polyPoints;
803  for( size_t j = i; j < elem.points.size() && j < i + 4; j++ )
804  {
805  bezierPoints.push_back( elem.points.at( j ) + m_sheetOffset );
806  }
807 
808  BEZIER_POLY converter( bezierPoints );
809  converter.GetPoly( polyPoints );
810 
811  for( size_t k = 0; k + 1 < polyPoints.size(); k++ )
812  {
813  SCH_LINE* line = new SCH_LINE(
814  polyPoints.at( k ) + m_sheetOffset, SCH_LAYER_ID::LAYER_NOTES );
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  if( symbol == m_symbols.end() )
828  {
829  // TODO: e.g. can depend on Template (RECORD=39
830  wxLogWarning( wxString::Format(
831  "Bezier tries to access symbol with ownerindex %d which does not exist",
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(
854  GetRelativePosition( elem.points.at( j ) + m_sheetOffset, 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(
870  GetRelativePosition( elem.points.at( j ) + m_sheetOffset, 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:
891  dashType = PLOT_DASH_TYPE::SOLID;
892  break;
894  dashType = PLOT_DASH_TYPE::DASH;
895  break;
897  dashType = PLOT_DASH_TYPE::DOT;
898  break;
900  dashType = PLOT_DASH_TYPE::DASHDOT;
901  break;
902  }
903 
904  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
905  {
906  SCH_LINE* line =
908  line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
909  line->SetLineWidth( elem.lineWidth );
910  line->SetLineStyle( dashType );
911 
912  line->SetFlags( IS_NEW );
913  m_currentSheet->GetScreen()->Append( line );
914  }
915  }
916  else
917  {
918  const auto& symbol = m_symbols.find( elem.ownerindex );
919  if( symbol == m_symbols.end() )
920  {
921  // TODO: e.g. can depend on Template (RECORD=39
922  wxLogWarning( wxString::Format(
923  "Polyline tries to access symbol with ownerindex %d which does not exist",
924  elem.ownerindex ) );
925  return;
926  }
927 
929  return;
930 
931  const auto& component = m_components.at( symbol->first );
932 
933  LIB_POLYLINE* line = new LIB_POLYLINE( symbol->second );
934  symbol->second->AddDrawItem( line );
935 
936  line->SetUnit( elem.ownerpartid );
937 
938  for( wxPoint& point : elem.points )
939  {
940  line->AddPoint( GetRelativePosition( point + m_sheetOffset, component ) );
941  }
942 
943  line->SetWidth( elem.lineWidth );
944  }
945 }
946 
947 
948 void SCH_ALTIUM_PLUGIN::ParsePolygon( const std::map<wxString, wxString>& aProperties )
949 {
950  ASCH_POLYGON elem( aProperties );
951 
952  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
953  {
954  // TODO: we cannot fill this polygon, only draw it for now
955  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
956  {
957  SCH_LINE* line =
959  line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
960  line->SetLineWidth( elem.lineWidth );
962 
963  line->SetFlags( IS_NEW );
964  m_currentSheet->GetScreen()->Append( line );
965  }
966 
967  // close polygon
968  SCH_LINE* line =
970  line->SetEndPoint( elem.points.back() + m_sheetOffset );
971  line->SetLineWidth( elem.lineWidth );
973 
974  line->SetFlags( IS_NEW );
975  m_currentSheet->GetScreen()->Append( line );
976  }
977  else
978  {
979  const auto& symbol = m_symbols.find( elem.ownerindex );
980  if( symbol == m_symbols.end() )
981  {
982  // TODO: e.g. can depend on Template (RECORD=39
983  wxLogWarning( wxString::Format(
984  "Polygon tries to access symbol with ownerindex %d which does not exist",
985  elem.ownerindex ) );
986  return;
987  }
988 
990  return;
991 
992  const auto& component = m_components.at( symbol->first );
993 
994  LIB_POLYLINE* line = new LIB_POLYLINE( symbol->second );
995  symbol->second->AddDrawItem( line );
996 
997  line->SetUnit( elem.ownerpartid );
998 
999  for( wxPoint& point : elem.points )
1000  {
1001  line->AddPoint( GetRelativePosition( point + m_sheetOffset, component ) );
1002  }
1003  line->AddPoint( GetRelativePosition( elem.points.front() + m_sheetOffset, component ) );
1004 
1005  line->SetWidth( elem.lineWidth );
1006 
1007  if( !elem.isSolid )
1009  else if( elem.color == elem.areacolor )
1011  else
1013  }
1014 }
1015 
1016 
1017 void SCH_ALTIUM_PLUGIN::ParseRoundRectangle( const std::map<wxString, wxString>& aProperties )
1018 {
1019  ASCH_ROUND_RECTANGLE elem( aProperties );
1020 
1021  wxPoint sheetTopRight = elem.topRight + m_sheetOffset;
1022  wxPoint sheetBottomLeft = elem.bottomLeft + m_sheetOffset;
1023 
1024  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1025  {
1026  const wxPoint topLeft = { sheetBottomLeft.x, sheetTopRight.y };
1027  const wxPoint bottomRight = { sheetTopRight.x, sheetBottomLeft.y };
1028 
1029  // TODO: we cannot fill this rectangle, only draw it for now
1030  // TODO: misses rounded edges
1031  SCH_LINE* lineTop = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1032  lineTop->SetEndPoint( topLeft );
1033  lineTop->SetLineWidth( elem.lineWidth );
1034  lineTop->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1035  lineTop->SetFlags( IS_NEW );
1036  m_currentSheet->GetScreen()->Append( lineTop );
1037 
1038  SCH_LINE* lineBottom = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1039  lineBottom->SetEndPoint( bottomRight );
1040  lineBottom->SetLineWidth( elem.lineWidth );
1041  lineBottom->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1042  lineBottom->SetFlags( IS_NEW );
1043  m_currentSheet->GetScreen()->Append( lineBottom );
1044 
1045  SCH_LINE* lineRight = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1046  lineRight->SetEndPoint( bottomRight );
1047  lineRight->SetLineWidth( elem.lineWidth );
1048  lineRight->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1049  lineRight->SetFlags( IS_NEW );
1050  m_currentSheet->GetScreen()->Append( lineRight );
1051 
1052  SCH_LINE* lineLeft = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1053  lineLeft->SetEndPoint( topLeft );
1054  lineLeft->SetLineWidth( elem.lineWidth );
1055  lineLeft->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1056  lineLeft->SetFlags( IS_NEW );
1057  m_currentSheet->GetScreen()->Append( lineLeft );
1058  }
1059  else
1060  {
1061  const auto& symbol = m_symbols.find( elem.ownerindex );
1062  if( symbol == m_symbols.end() )
1063  {
1064  // TODO: e.g. can depend on Template (RECORD=39
1065  wxLogWarning( wxString::Format(
1066  "Rounded Rectangle tries to access symbol with ownerindex %d which does not exist",
1067  elem.ownerindex ) );
1068  return;
1069  }
1070 
1072  return;
1073 
1074  const auto& component = m_components.at( symbol->first );
1075 
1076  // TODO: misses rounded edges
1077  LIB_RECTANGLE* rect = new LIB_RECTANGLE( symbol->second );
1078  symbol->second->AddDrawItem( rect );
1079 
1080  rect->SetUnit( elem.ownerpartid );
1081 
1082  rect->SetPosition( GetRelativePosition( elem.topRight + m_sheetOffset, component ) );
1083  rect->SetEnd( GetRelativePosition( elem.bottomLeft + m_sheetOffset, component ) );
1084  rect->SetWidth( elem.lineWidth );
1085 
1086  if( !elem.isSolid )
1088  else if( elem.color == elem.areacolor )
1090  else
1092  }
1093 }
1094 
1095 
1096 void SCH_ALTIUM_PLUGIN::ParseArc( const std::map<wxString, wxString>& aProperties )
1097 {
1098  ASCH_ARC elem( aProperties );
1099 
1100  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1101  {
1102  wxLogError( "Arc drawing is not possible for now on schematic." );
1103  }
1104  else
1105  {
1106  const auto& symbol = m_symbols.find( elem.ownerindex );
1107  if( symbol == m_symbols.end() )
1108  {
1109  // TODO: e.g. can depend on Template (RECORD=39
1110  wxLogWarning( wxString::Format(
1111  "Arc tries to access symbol with ownerindex %d which does not exist",
1112  elem.ownerindex ) );
1113  return;
1114  }
1115 
1117  return;
1118 
1119  const auto& component = m_components.at( symbol->first );
1120 
1121  if( elem.startAngle == 0 && ( elem.endAngle == 0 || elem.endAngle == 360 ) )
1122  {
1123  LIB_CIRCLE* circle = new LIB_CIRCLE( symbol->second );
1124  symbol->second->AddDrawItem( circle );
1125 
1126  circle->SetUnit( elem.ownerpartid );
1127 
1128  circle->SetPosition( GetRelativePosition( elem.center + m_sheetOffset, component ) );
1129  circle->SetRadius( elem.radius );
1130  circle->SetWidth( elem.lineWidth );
1131  }
1132  else
1133  {
1134  LIB_ARC* arc = new LIB_ARC( symbol->second );
1135  symbol->second->AddDrawItem( arc );
1136 
1137  arc->SetUnit( elem.ownerpartid );
1138 
1139  // TODO: correct?
1140  arc->SetPosition( GetRelativePosition( elem.center + m_sheetOffset, component ) );
1141  arc->SetRadius( elem.radius );
1142  arc->SetFirstRadiusAngle( elem.startAngle * 10. );
1143  arc->SetSecondRadiusAngle( elem.endAngle * 10. );
1144  }
1145  }
1146 }
1147 
1148 
1149 void SCH_ALTIUM_PLUGIN::ParseLine( const std::map<wxString, wxString>& aProperties )
1150 {
1151  ASCH_LINE elem( aProperties );
1152 
1153  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1154  {
1155  // close polygon
1157  line->SetEndPoint( elem.point2 + m_sheetOffset );
1158  line->SetLineWidth( elem.lineWidth );
1159  line->SetLineStyle( PLOT_DASH_TYPE::SOLID ); // TODO?
1160 
1161  line->SetFlags( IS_NEW );
1162  m_currentSheet->GetScreen()->Append( line );
1163  }
1164  else
1165  {
1166  const auto& symbol = m_symbols.find( elem.ownerindex );
1167  if( symbol == m_symbols.end() )
1168  {
1169  // TODO: e.g. can depend on Template (RECORD=39
1170  wxLogWarning( wxString::Format(
1171  "Line tries to access symbol with ownerindex %d which does not exist",
1172  elem.ownerindex ) );
1173  return;
1174  }
1175 
1177  return;
1178 
1179  const auto& component = m_components.at( symbol->first );
1180 
1181  LIB_POLYLINE* line = new LIB_POLYLINE( symbol->second );
1182  symbol->second->AddDrawItem( line );
1183 
1184  line->SetUnit( elem.ownerpartid );
1185 
1186  line->AddPoint( GetRelativePosition( elem.point1 + m_sheetOffset, component ) );
1187  line->AddPoint( GetRelativePosition( elem.point2 + m_sheetOffset, component ) );
1188 
1189  line->SetWidth( elem.lineWidth );
1190  }
1191 }
1192 
1193 
1194 void SCH_ALTIUM_PLUGIN::ParseRectangle( const std::map<wxString, wxString>& aProperties )
1195 {
1196  ASCH_RECTANGLE elem( aProperties );
1197 
1198  wxPoint sheetTopRight = elem.topRight + m_sheetOffset;
1199  wxPoint sheetBottomLeft = elem.bottomLeft + m_sheetOffset;
1200 
1201  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1202  {
1203  const wxPoint topLeft = { sheetBottomLeft.x, sheetTopRight.y };
1204  const wxPoint bottomRight = { sheetTopRight.x, sheetBottomLeft.y };
1205 
1206  // TODO: we cannot fill this rectangle, only draw it for now
1207  SCH_LINE* lineTop = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1208  lineTop->SetEndPoint( topLeft );
1209  lineTop->SetLineWidth( elem.lineWidth );
1210  lineTop->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1211  lineTop->SetFlags( IS_NEW );
1212  m_currentSheet->GetScreen()->Append( lineTop );
1213 
1214  SCH_LINE* lineBottom = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1215  lineBottom->SetEndPoint( bottomRight );
1216  lineBottom->SetLineWidth( elem.lineWidth );
1217  lineBottom->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1218  lineBottom->SetFlags( IS_NEW );
1219  m_currentSheet->GetScreen()->Append( lineBottom );
1220 
1221  SCH_LINE* lineRight = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1222  lineRight->SetEndPoint( bottomRight );
1223  lineRight->SetLineWidth( elem.lineWidth );
1224  lineRight->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1225  lineRight->SetFlags( IS_NEW );
1226  m_currentSheet->GetScreen()->Append( lineRight );
1227 
1228  SCH_LINE* lineLeft = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1229  lineLeft->SetEndPoint( topLeft );
1230  lineLeft->SetLineWidth( elem.lineWidth );
1231  lineLeft->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1232  lineLeft->SetFlags( IS_NEW );
1233  m_currentSheet->GetScreen()->Append( lineLeft );
1234  }
1235  else
1236  {
1237  const auto& symbol = m_symbols.find( elem.ownerindex );
1238  if( symbol == m_symbols.end() )
1239  {
1240  // TODO: e.g. can depend on Template (RECORD=39
1241  wxLogWarning( wxString::Format(
1242  "Rectangle tries to access symbol with ownerindex %d which does not exist",
1243  elem.ownerindex ) );
1244  return;
1245  }
1246 
1248  return;
1249 
1250  const auto& component = m_components.at( symbol->first );
1251 
1252  LIB_RECTANGLE* rect = new LIB_RECTANGLE( symbol->second );
1253  symbol->second->AddDrawItem( rect );
1254 
1255  rect->SetUnit( elem.ownerpartid );
1256 
1257  rect->SetPosition( GetRelativePosition( sheetTopRight, component ) );
1258  rect->SetEnd( GetRelativePosition( sheetBottomLeft, component ) );
1259  rect->SetWidth( elem.lineWidth );
1260 
1261  if( !elem.isSolid )
1263  else if( elem.color == elem.areacolor )
1265  else
1267  }
1268 }
1269 
1270 
1272  int aIndex, const std::map<wxString, wxString>& aProperties )
1273 {
1274  ASCH_SHEET_SYMBOL elem( aProperties );
1275 
1276  SCH_SHEET* sheet = new SCH_SHEET( m_currentSheet, elem.location + m_sheetOffset );
1277  SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
1278 
1279  sheet->SetSize( elem.size );
1280 
1281  sheet->SetBorderColor( GetColorFromInt( elem.color ) );
1282  if( elem.isSolid )
1283  sheet->SetBackgroundColor( GetColorFromInt( elem.areacolor ) );
1284 
1285  sheet->SetScreen( screen );
1286 
1287  sheet->SetFlags( IS_NEW );
1288  m_currentSheet->GetScreen()->Append( sheet );
1289 
1290  m_sheets.insert( { aIndex, sheet } );
1291 }
1292 
1293 
1294 void SCH_ALTIUM_PLUGIN::ParseSheetEntry( const std::map<wxString, wxString>& aProperties )
1295 {
1296  ASCH_SHEET_ENTRY elem( aProperties );
1297 
1298  const auto& sheet = m_sheets.find( elem.ownerindex );
1299  if( sheet == m_sheets.end() )
1300  {
1301  wxLogError( wxString::Format(
1302  "Sheet Entry tries to access sheet with ownerindex %d which does not exist",
1303  elem.ownerindex ) );
1304  return;
1305  }
1306 
1307  SCH_SHEET_PIN* sheetPin = new SCH_SHEET_PIN( sheet->second );
1308  sheet->second->AddPin( sheetPin );
1309 
1310  sheetPin->SetText( elem.name );
1312  //sheetPin->SetLabelSpinStyle( getSpinStyle( term.OrientAngle, false ) );
1313  //sheetPin->SetPosition( getKiCadPoint( term.Position ) );
1314 
1315  wxPoint pos = sheet->second->GetPosition();
1316  wxSize size = sheet->second->GetSize();
1317 
1318  switch( elem.side )
1319  {
1320  default:
1322  sheetPin->SetPosition( { pos.x, pos.y + elem.distanceFromTop } );
1324  sheetPin->SetEdge( SHEET_SIDE::SHEET_LEFT_SIDE );
1325  break;
1327  sheetPin->SetPosition( { pos.x + size.x, pos.y + elem.distanceFromTop } );
1330  break;
1332  sheetPin->SetPosition( { pos.x + elem.distanceFromTop, pos.y } );
1334  sheetPin->SetEdge( SHEET_SIDE::SHEET_TOP_SIDE );
1335  break;
1337  sheetPin->SetPosition( { pos.x + elem.distanceFromTop, pos.y + size.y } );
1340  break;
1341  }
1342 
1343  switch( elem.iotype )
1344  {
1345  default:
1348  break;
1351  break;
1354  break;
1357  break;
1358  }
1359 }
1360 
1361 
1363 {
1364  if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE || aStyle == ASCH_POWER_PORT_STYLE::ARROW )
1365  {
1366  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart );
1367  aKPart->AddDrawItem( line1 );
1368  line1->SetWidth( Mils2iu( 10 ) );
1369  line1->AddPoint( { 0, 0 } );
1370  line1->AddPoint( { 0, Mils2iu( -50 ) } );
1371 
1372  if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE )
1373  {
1374  LIB_CIRCLE* circle = new LIB_CIRCLE( aKPart );
1375  aKPart->AddDrawItem( circle );
1376  circle->SetWidth( Mils2iu( 5 ) );
1377  circle->SetRadius( Mils2iu( 25 ) );
1378  circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -75 ) } );
1379  }
1380  else
1381  {
1382  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1383  aKPart->AddDrawItem( line2 );
1384  line2->SetWidth( Mils2iu( 10 ) );
1385  line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
1386  line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } );
1387  line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
1388  line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
1389  }
1390 
1391  return { 0, Mils2iu( 150 ) };
1392  }
1393  else if( aStyle == ASCH_POWER_PORT_STYLE::WAVE )
1394  {
1395  LIB_POLYLINE* line = new LIB_POLYLINE( aKPart );
1396  aKPart->AddDrawItem( line );
1397  line->SetWidth( Mils2iu( 10 ) );
1398  line->AddPoint( { 0, 0 } );
1399  line->AddPoint( { 0, Mils2iu( -72 ) } );
1400 
1401  LIB_BEZIER* bezier = new LIB_BEZIER( aKPart );
1402  aKPart->AddDrawItem( bezier );
1403  bezier->SetWidth( Mils2iu( 5 ) );
1404  bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -50 ) } );
1405  bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -87 ) } );
1406  bezier->AddPoint( { Mils2iu( -30 ), Mils2iu( -63 ) } );
1407  bezier->AddPoint( { Mils2iu( -30 ), Mils2iu( -100 ) } );
1408 
1409  return { 0, Mils2iu( 150 ) };
1410  }
1411  else if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND
1413  || aStyle == ASCH_POWER_PORT_STYLE::EARTH
1414  || aStyle == ASCH_POWER_PORT_STYLE::GOST_ARROW )
1415  {
1416  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart );
1417  aKPart->AddDrawItem( line1 );
1418  line1->SetWidth( Mils2iu( 10 ) );
1419  line1->AddPoint( { 0, 0 } );
1420  line1->AddPoint( { 0, Mils2iu( -100 ) } );
1421 
1422  if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND )
1423  {
1424  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1425  aKPart->AddDrawItem( line2 );
1426  line2->SetWidth( Mils2iu( 10 ) );
1427  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1428  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
1429 
1430  LIB_POLYLINE* line3 = new LIB_POLYLINE( aKPart );
1431  aKPart->AddDrawItem( line3 );
1432  line3->SetWidth( Mils2iu( 10 ) );
1433  line3->AddPoint( { Mils2iu( -70 ), Mils2iu( -130 ) } );
1434  line3->AddPoint( { Mils2iu( 70 ), Mils2iu( -130 ) } );
1435 
1436  LIB_POLYLINE* line4 = new LIB_POLYLINE( aKPart );
1437  aKPart->AddDrawItem( line4 );
1438  line4->SetWidth( Mils2iu( 10 ) );
1439  line4->AddPoint( { Mils2iu( -40 ), Mils2iu( -160 ) } );
1440  line4->AddPoint( { Mils2iu( 40 ), Mils2iu( -160 ) } );
1441 
1442  LIB_POLYLINE* line5 = new LIB_POLYLINE( aKPart );
1443  aKPart->AddDrawItem( line5 );
1444  line5->SetWidth( Mils2iu( 10 ) );
1445  line5->AddPoint( { Mils2iu( -10 ), Mils2iu( -190 ) } );
1446  line5->AddPoint( { Mils2iu( 10 ), Mils2iu( -190 ) } );
1447  }
1448  else if( aStyle == ASCH_POWER_PORT_STYLE::SIGNAL_GROUND )
1449  {
1450  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1451  aKPart->AddDrawItem( line2 );
1452  line2->SetWidth( Mils2iu( 10 ) );
1453  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1454  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
1455  line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -200 ) } );
1456  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1457  }
1458  else if( aStyle == ASCH_POWER_PORT_STYLE::EARTH )
1459  {
1460  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1461  aKPart->AddDrawItem( line2 );
1462  line2->SetWidth( Mils2iu( 10 ) );
1463  line2->AddPoint( { Mils2iu( -150 ), Mils2iu( -200 ) } );
1464  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1465  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
1466  line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -200 ) } );
1467 
1468  LIB_POLYLINE* line3 = new LIB_POLYLINE( aKPart );
1469  aKPart->AddDrawItem( line3 );
1470  line3->SetWidth( Mils2iu( 10 ) );
1471  line3->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
1472  line3->AddPoint( { Mils2iu( -50 ), Mils2iu( -200 ) } );
1473  }
1474  else // ASCH_POWER_PORT_STYLE::GOST_ARROW
1475  {
1476  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1477  aKPart->AddDrawItem( line2 );
1478  line2->SetWidth( Mils2iu( 10 ) );
1479  line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
1480  line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
1481  line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } );
1482 
1483  return { 0, Mils2iu( 150 ) }; // special case
1484  }
1485 
1486  return { 0, Mils2iu( 250 ) };
1487  }
1488  else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_POWER_GROUND
1489  || aStyle == ASCH_POWER_PORT_STYLE::GOST_EARTH )
1490  {
1491  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart );
1492  aKPart->AddDrawItem( line1 );
1493  line1->SetWidth( Mils2iu( 10 ) );
1494  line1->AddPoint( { 0, 0 } );
1495  line1->AddPoint( { 0, Mils2iu( -160 ) } );
1496 
1497  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1498  aKPart->AddDrawItem( line2 );
1499  line2->SetWidth( Mils2iu( 10 ) );
1500  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -160 ) } );
1501  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -160 ) } );
1502 
1503  LIB_POLYLINE* line3 = new LIB_POLYLINE( aKPart );
1504  aKPart->AddDrawItem( line3 );
1505  line3->SetWidth( Mils2iu( 10 ) );
1506  line3->AddPoint( { Mils2iu( -60 ), Mils2iu( -200 ) } );
1507  line3->AddPoint( { Mils2iu( 60 ), Mils2iu( -200 ) } );
1508 
1509  LIB_POLYLINE* line4 = new LIB_POLYLINE( aKPart );
1510  aKPart->AddDrawItem( line4 );
1511  line4->SetWidth( Mils2iu( 10 ) );
1512  line4->AddPoint( { Mils2iu( -20 ), Mils2iu( -240 ) } );
1513  line4->AddPoint( { Mils2iu( 20 ), Mils2iu( -240 ) } );
1514 
1516  return { 0, Mils2iu( 300 ) };
1517 
1518  LIB_CIRCLE* circle = new LIB_CIRCLE( aKPart );
1519  aKPart->AddDrawItem( circle );
1520  circle->SetWidth( Mils2iu( 10 ) );
1521  circle->SetRadius( Mils2iu( 120 ) );
1522  circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -160 ) } );
1523 
1524  return { 0, Mils2iu( 350 ) };
1525  }
1526  else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_BAR )
1527  {
1528  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart );
1529  aKPart->AddDrawItem( line1 );
1530  line1->SetWidth( Mils2iu( 10 ) );
1531  line1->AddPoint( { 0, 0 } );
1532  line1->AddPoint( { 0, Mils2iu( -200 ) } );
1533 
1534  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1535  aKPart->AddDrawItem( line2 );
1536  line2->SetWidth( Mils2iu( 10 ) );
1537  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -200 ) } );
1538  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -200 ) } );
1539 
1540  return { 0, Mils2iu( 250 ) };
1541  }
1542  else
1543  {
1544  if( aStyle != ASCH_POWER_PORT_STYLE::BAR )
1545  wxLogWarning( "Power Port has unknown style, use bar instead. " );
1546 
1547  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart );
1548  aKPart->AddDrawItem( line1 );
1549  line1->SetWidth( Mils2iu( 10 ) );
1550  line1->AddPoint( { 0, 0 } );
1551  line1->AddPoint( { 0, Mils2iu( -100 ) } );
1552 
1553  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart );
1554  aKPart->AddDrawItem( line2 );
1555  line2->SetWidth( Mils2iu( 10 ) );
1556  line2->AddPoint( { Mils2iu( -50 ), Mils2iu( -100 ) } );
1557  line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -100 ) } );
1558 
1559  return { 0, Mils2iu( 150 ) };
1560  }
1561 }
1562 
1563 
1564 void SCH_ALTIUM_PLUGIN::ParsePowerPort( const std::map<wxString, wxString>& aProperties )
1565 {
1566  ASCH_POWER_PORT elem( aProperties );
1567 
1569 
1570  LIB_PART* kpart = nullptr;
1571 
1572  const auto& symbol = m_powerSymbols.find( elem.text );
1573  if( symbol != m_powerSymbols.end() )
1574  {
1575  kpart = symbol->second; // cache hit
1576  }
1577  else
1578  {
1579  kpart = new LIB_PART( wxEmptyString );
1580  kpart->SetPower();
1581  kpart->SetName( elem.text );
1582  kpart->GetReferenceField().SetText( "#PWR" );
1583  kpart->GetValueField().SetText( elem.text );
1584  kpart->GetValueField().SetVisible( true ); // TODO: why does this not work?
1586  "Power symbol creates a global label with name \"%s\"", elem.text ) );
1587  kpart->SetKeyWords( "power-flag" );
1588  kpart->SetLibId( libId );
1589 
1590  // generate graphic
1591  LIB_PIN* pin = new LIB_PIN( kpart );
1592  kpart->AddDrawItem( pin );
1593 
1594  pin->SetName( elem.text );
1595  pin->SetPosition( { 0, 0 } );
1596  pin->SetLength( 0 );
1597 
1598  // marks the pin as a global label
1600  pin->SetVisible( false );
1601 
1602  wxPoint valueFieldPos = HelperGeneratePowerPortGraphics( kpart, elem.style );
1603 
1604  kpart->GetValueField().SetPosition( valueFieldPos );
1605 
1606  // this has to be done after parsing the LIB_PART!
1607  m_pi->SaveSymbol( getLibFileName().GetFullPath(), kpart, m_properties.get() );
1608  m_powerSymbols.insert( { elem.text, kpart } );
1609  }
1610 
1611  SCH_SHEET_PATH sheetpath;
1613 
1614  // each component has its own symbol for now
1615  SCH_COMPONENT* component = new SCH_COMPONENT();
1616  component->SetRef( &sheetpath, "#PWR?" );
1617  component->SetValue( elem.text );
1618  component->SetLibId( libId );
1619  component->SetLibSymbol( new LIB_PART( *kpart ) );
1620 
1621  SCH_FIELD* valueField = component->GetField( VALUE );
1622 
1623  // TODO: Why do I need to set those a second time?
1624  valueField->SetVisible( true );
1625  valueField->SetPosition( kpart->GetValueField().GetPosition() );
1626 
1627  component->SetPosition( elem.location + m_sheetOffset );
1628 
1629  switch( elem.orientation )
1630  {
1633  valueField->SetTextAngle( -900. );
1635  break;
1638  valueField->SetTextAngle( -1800. );
1640  break;
1643  valueField->SetTextAngle( -2700. );
1645  break;
1648  valueField->SetTextAngle( 0. );
1650  break;
1651  default:
1652  wxLogWarning( "Pin has unexpected orientation" );
1653  break;
1654  }
1655 
1656  m_currentSheet->GetScreen()->Append( component );
1657 }
1658 
1659 
1661 {
1662  // Get both connection points where we could connect to
1663  wxPoint start = aElem.location + m_sheetOffset;
1664  wxPoint end = start;
1665 
1666  switch( aElem.style )
1667  {
1668  default:
1670  case ASCH_PORT_STYLE::LEFT:
1673  end.x += aElem.width;
1674  break;
1676  case ASCH_PORT_STYLE::TOP:
1679  end.y -= aElem.width;
1680  break;
1681  }
1682 
1683  // Check which connection points exists in the schematic
1684  SCH_SCREEN* screen = m_currentSheet->GetScreen();
1685 
1686  bool startIsWireTerminal = screen->IsTerminalPoint( start, LAYER_WIRE );
1687  bool startIsBusTerminal = screen->IsTerminalPoint( start, LAYER_BUS );
1688 
1689  bool endIsWireTerminal = screen->IsTerminalPoint( end, LAYER_WIRE );
1690  bool endIsBusTerminal = screen->IsTerminalPoint( end, LAYER_BUS );
1691 
1692  // check if any of the points is a terminal point
1693  // TODO: there seems a problem to detect approximated connections towards component pins?
1694  bool connectionFound =
1695  startIsWireTerminal || startIsBusTerminal || endIsWireTerminal || endIsBusTerminal;
1696  if( !connectionFound )
1697  wxLogError( wxString::Format(
1698  "There is a Port for \"%s\", but no connections towards it?", aElem.name ) );
1699 
1700  // Select label position. In case both match, we will add a line later.
1701  wxPoint position = ( startIsWireTerminal || startIsBusTerminal ) ? start : end;
1702 
1703  SCH_TEXT* const label = new SCH_GLOBALLABEL( position, aElem.name );
1704  // TODO: detect correct label type depending on sheet settings, etc.
1705  // label = new SCH_HIERLABEL( elem.location + m_sheetOffset, elem.name );
1706 
1707  switch( aElem.iotype )
1708  {
1709  default:
1712  break;
1715  break;
1718  break;
1721  break;
1722  }
1723 
1724  switch( aElem.style )
1725  {
1726  default:
1728  case ASCH_PORT_STYLE::LEFT:
1731  if( ( startIsWireTerminal || startIsBusTerminal ) )
1733  else
1735  break;
1737  case ASCH_PORT_STYLE::TOP:
1740  if( ( startIsWireTerminal || startIsBusTerminal ) )
1742  else
1744  break;
1745  }
1746 
1747  label->SetFlags( IS_NEW );
1748  m_currentSheet->GetScreen()->Append( label );
1749 
1750  // This is a hack, for the case both connection points are valid: add a small wire
1751  if( ( startIsWireTerminal && endIsWireTerminal ) || !connectionFound )
1752  {
1753  SCH_LINE* wire = new SCH_LINE( start, SCH_LAYER_ID::LAYER_WIRE );
1754  wire->SetEndPoint( end );
1755  wire->SetLineWidth( Mils2iu( 2 ) );
1756  wire->SetFlags( IS_NEW );
1757  m_currentSheet->GetScreen()->Append( wire );
1758  }
1759  else if( startIsBusTerminal && endIsBusTerminal )
1760  {
1761  SCH_LINE* wire = new SCH_LINE( start, SCH_LAYER_ID::LAYER_BUS );
1762  wire->SetEndPoint( end );
1763  wire->SetLineWidth( Mils2iu( 2 ) );
1764  wire->SetFlags( IS_NEW );
1765  m_currentSheet->GetScreen()->Append( wire );
1766  }
1767 }
1768 
1769 
1770 void SCH_ALTIUM_PLUGIN::ParseNoERC( const std::map<wxString, wxString>& aProperties )
1771 {
1772  ASCH_NO_ERC elem( aProperties );
1773 
1774  if( elem.isActive )
1775  {
1776  SCH_NO_CONNECT* noConnect = new SCH_NO_CONNECT( elem.location + m_sheetOffset );
1777 
1778  noConnect->SetFlags( IS_NEW );
1779  m_currentSheet->GetScreen()->Append( noConnect );
1780  }
1781 }
1782 
1783 
1784 void SCH_ALTIUM_PLUGIN::ParseNetLabel( const std::map<wxString, wxString>& aProperties )
1785 {
1786  ASCH_NET_LABEL elem( aProperties );
1787 
1788  SCH_LABEL* label = new SCH_LABEL( elem.location + m_sheetOffset, elem.text );
1789 
1790  switch( elem.orientation )
1791  {
1794  break;
1797  break;
1800  break;
1803  break;
1804  default:
1805  break;
1806  }
1807 
1808  label->SetFlags( IS_NEW );
1809  m_currentSheet->GetScreen()->Append( label );
1810 }
1811 
1812 
1813 void SCH_ALTIUM_PLUGIN::ParseBus( const std::map<wxString, wxString>& aProperties )
1814 {
1815  ASCH_BUS elem( aProperties );
1816 
1817  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
1818  {
1819  SCH_LINE* bus =
1820  new SCH_LINE( elem.points.at( i ) + m_sheetOffset, SCH_LAYER_ID::LAYER_BUS );
1821  bus->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
1822  bus->SetLineWidth( elem.lineWidth );
1823 
1824  bus->SetFlags( IS_NEW );
1825  m_currentSheet->GetScreen()->Append( bus );
1826  }
1827 }
1828 
1829 
1830 void SCH_ALTIUM_PLUGIN::ParseWire( const std::map<wxString, wxString>& aProperties )
1831 {
1832  ASCH_WIRE elem( aProperties );
1833 
1834  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
1835  {
1836  SCH_LINE* wire =
1837  new SCH_LINE( elem.points.at( i ) + m_sheetOffset, SCH_LAYER_ID::LAYER_WIRE );
1838  wire->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
1839  wire->SetLineWidth( elem.lineWidth );
1840 
1841  wire->SetFlags( IS_NEW );
1842  m_currentSheet->GetScreen()->Append( wire );
1843  }
1844 }
1845 
1846 
1847 void SCH_ALTIUM_PLUGIN::ParseJunction( const std::map<wxString, wxString>& aProperties )
1848 {
1849  ASCH_JUNCTION elem( aProperties );
1850 
1851  SCH_JUNCTION* junction = new SCH_JUNCTION( elem.location + m_sheetOffset );
1852 
1853  junction->SetFlags( IS_NEW );
1854  m_currentSheet->GetScreen()->Append( junction );
1855 }
1856 
1857 
1858 void SCH_ALTIUM_PLUGIN::ParseSheet( const std::map<wxString, wxString>& aProperties )
1859 {
1860  m_altiumSheet = std::make_unique<ASCH_SHEET>( aProperties );
1861 
1862  PAGE_INFO pageInfo;
1863 
1864  bool isPortrait = m_altiumSheet->sheetOrientation == ASCH_SHEET_WORKSPACEORIENTATION::PORTRAIT;
1865  switch( m_altiumSheet->sheetSize )
1866  {
1867  default:
1868  case ASCH_SHEET_SIZE::A4:
1869  pageInfo.SetType( "A4", isPortrait );
1870  break;
1871  case ASCH_SHEET_SIZE::A3:
1872  pageInfo.SetType( "A3", isPortrait );
1873  break;
1874  case ASCH_SHEET_SIZE::A2:
1875  pageInfo.SetType( "A2", isPortrait );
1876  break;
1877  case ASCH_SHEET_SIZE::A1:
1878  pageInfo.SetType( "A1", isPortrait );
1879  break;
1880  case ASCH_SHEET_SIZE::A0:
1881  pageInfo.SetType( "A0", isPortrait );
1882  break;
1883  case ASCH_SHEET_SIZE::A:
1884  pageInfo.SetType( "A", isPortrait );
1885  break;
1886  case ASCH_SHEET_SIZE::B:
1887  pageInfo.SetType( "B", isPortrait );
1888  break;
1889  case ASCH_SHEET_SIZE::C:
1890  pageInfo.SetType( "C", isPortrait );
1891  break;
1892  case ASCH_SHEET_SIZE::D:
1893  pageInfo.SetType( "D", isPortrait );
1894  break;
1895  case ASCH_SHEET_SIZE::E:
1896  pageInfo.SetType( "E", isPortrait );
1897  break;
1899  pageInfo.SetType( "USLetter", isPortrait );
1900  break;
1902  pageInfo.SetType( "USLegal", isPortrait );
1903  break;
1905  pageInfo.SetType( "A3", isPortrait ); // TODO: use User
1906  break;
1908  pageInfo.SetType( "A", isPortrait );
1909  break;
1911  pageInfo.SetType( "B", isPortrait );
1912  break;
1914  pageInfo.SetType( "C", isPortrait );
1915  break;
1917  pageInfo.SetType( "D", isPortrait );
1918  break;
1920  pageInfo.SetType( "E", isPortrait );
1921  break;
1922  }
1923 
1924  m_currentSheet->GetScreen()->SetPageSettings( pageInfo );
1925 
1926  m_sheetOffset = { 0, pageInfo.GetHeightIU() };
1927 }
1928 
1929 
1931 {
1932  switch( aOrientation )
1933  {
1934  default:
1936  aField.SetTextAngle( 0 );
1937  break;
1939  aField.SetTextAngle( 900 );
1940  break;
1942  aField.SetTextAngle( 1800 );
1943  break;
1945  aField.SetTextAngle( 2700 );
1946  break;
1947  }
1948 }
1949 
1950 
1951 void SCH_ALTIUM_PLUGIN::ParseSheetName( const std::map<wxString, wxString>& aProperties )
1952 {
1953  ASCH_SHEET_NAME elem( aProperties );
1954 
1955  const auto& sheet = m_sheets.find( elem.ownerindex );
1956  if( sheet == m_sheets.end() )
1957  {
1958  wxLogError( wxString::Format(
1959  "Sheet Name tries to access sheet with ownerindex %d which does not exist",
1960  elem.ownerindex ) );
1961  return;
1962  }
1963 
1964  SCH_FIELD& sheetNameField = sheet->second->GetFields()[SHEETNAME];
1965 
1966  sheetNameField.SetPosition( elem.location + m_sheetOffset );
1967  sheetNameField.SetText( elem.text );
1968  sheetNameField.SetVisible( !elem.isHidden );
1969 
1972 
1973  SetFieldOrientation( sheetNameField, elem.orientation );
1974 }
1975 
1976 
1977 void SCH_ALTIUM_PLUGIN::ParseFileName( const std::map<wxString, wxString>& aProperties )
1978 {
1979  ASCH_FILE_NAME elem( aProperties );
1980 
1981  const auto& sheet = m_sheets.find( elem.ownerindex );
1982  if( sheet == m_sheets.end() )
1983  {
1984  wxLogError( wxString::Format(
1985  "File Name tries to access sheet with ownerindex %d which does not exist",
1986  elem.ownerindex ) );
1987  return;
1988  }
1989 
1990  SCH_FIELD& filenameField = sheet->second->GetFields()[SHEETFILENAME];
1991 
1992  filenameField.SetPosition( elem.location + m_sheetOffset );
1993  filenameField.SetText( elem.text ); // TODO: use kicad_sch
1994  filenameField.SetVisible( !elem.isHidden );
1995 
1998 
1999  SetFieldOrientation( filenameField, elem.orientation );
2000 }
2001 
2002 
2003 void SCH_ALTIUM_PLUGIN::ParseDesignator( const std::map<wxString, wxString>& aProperties )
2004 {
2005  ASCH_DESIGNATOR elem( aProperties );
2006 
2007  const auto& symbol = m_symbols.find( elem.ownerindex );
2008  if( symbol == m_symbols.end() )
2009  {
2010  // TODO: e.g. can depend on Template (RECORD=39
2011  wxLogWarning( wxString::Format(
2012  "Designator tries to access symbol with ownerindex %d which does not exist",
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 );
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  int fieldIdx = component->GetFieldCount() + 1;
2088 
2089  // TODO: location not correct?
2090  SCH_FIELD field( elem.location + m_sheetOffset, fieldIdx, component, elem.name );
2091  field.SetText( elem.text );
2092  field.SetVisible( !elem.isHidden );
2093  field.SetMirrored( elem.isMirrored );
2095 
2096  switch( elem.orientation )
2097  {
2099  field.SetTextAngle( 0 );
2100  break;
2102  field.SetTextAngle( 90 );
2103  break;
2105  field.SetTextAngle( 180 );
2106  break;
2108  field.SetTextAngle( 270 );
2109  break;
2110  default:
2111  break;
2112  }
2113 
2114  component->AddField( field );
2115  }
2116 }
void SetMirrored(bool isMirrored)
Definition: eda_text.h:194
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:52
std::unique_ptr< PROPERTIES > m_properties
Library plugin properties.
void SetModified()
Definition: eda_item.cpp:79
ASCH_RECORD_ORIENTATION orientation
void SetShape(PINSHEETLABEL_SHAPE aShape)
Definition: sch_text.h:240
static int PropertiesReadInt(const std::map< wxString, wxString > &aProperties, const wxString &aKey, int aDefault)
void ParseLabel(const std::map< wxString, wxString > &aProperties)
void SetLibSymbol(LIB_PART *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_PLUGIN obje...
void SetLibId(const LIB_ID &aName)
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()
COLOR4D & FromCSSRGBA(int aRed, int aGreen, int aBlue, double aAlpha=1.0)
Initializes 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)
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:44
void SetSize(const wxSize &aSize)
Definition: sch_bus_entry.h:72
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)
Converts Bezier curve to a polygon.
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: lib_pin.h:129
void SetLineWidth(const int aSize)
Definition: sch_line.cpp:269
void ParseParameter(const std::map< wxString, wxString > &aProperties)
size_t GetRemainingBytes() const
void Parse(const CFB::CompoundFileReader &aReader)
void ParseRoundRectangle(const std::map< wxString, wxString > &aProperties)
std::vector< wxPoint > points
void SetItalic(bool isItalic)
Definition: eda_text.h:185
int color
Definition: DXF_plotter.cpp:60
void SetFillMode(FILL_TYPE aFillMode)
Definition: lib_item.h:301
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:150
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:110
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:191
ASCH_LABEL_JUSTIFICATION
void SetFirstRadiusAngle(int aAngle)
Definition: lib_arc.h:105
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Function SetType sets the name of the page type and also the sizes and margins commonly associated wi...
Definition: page_info.cpp:119
ASCH_LABEL_JUSTIFICATION justification
int ownerpartdisplaymode
LIB_FIELD & GetValueField()
Return reference to the value field.
wxString m_libName
Library name to save symbols.
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:182
void ParseSheet(const std::map< wxString, wxString > &aProperties)
void SetLength(int aLength)
Definition: lib_pin.h:132
void SetPosition(const wxPoint &aPosition) override
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)
PROPERTIES is a name/value tuple with unique names and optional values.
Definition: properties.h:34
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:284
VTBL_ENTRY const wxString GetProjectPath() const
Function GetProjectPath returns the full path of the project.
Definition: project.cpp:121
std::map< wxString, LIB_PART * > m_powerSymbols
Field Reference of part, i.e. "IC21".
void SetPageNumber(const SCH_SHEET_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
Definition: sch_sheet.cpp:1081
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)
VTBL_ENTRY void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:257
ASCH_RECORD_ORIENTATION orientation
void AddDrawItem(LIB_ITEM *aItem)
Add a new draw aItem to the draw object list.
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
wxPoint m_sheetOffset
Will be assigned at the end of parsing a sheet.
ASCH_RECORD_ORIENTATION orientation
void SetLineStyle(const PLOT_DASH_TYPE aStyle)
Definition: sch_line.cpp:237
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:504
int ownerindex
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:296
LIB_FIELD & GetReferenceField()
Return reference to the reference designator field.
void SetFlags(STATUS_FLAGS aMask)
Definition: eda_item.h:221
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:120
SCHEMATIC * m_schematic
Passed to Load(), the schematic object being loaded.
void ParseLine(const std::map< wxString, wxString > &aProperties)
#define NULL
void SetWidth(int aWidth) override
Definition: lib_rectangle.h:84
void SetFieldOrientation(SCH_FIELD &aField, ASCH_RECORD_ORIENTATION aOrientation)
ASCH_RECORD_ORIENTATION
wxFileName getLibFileName()
PAGE_INFO describes the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
TRANSFORM & GetTransform() const
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:209
void SetDescription(const wxString &aDescription)
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.
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:293
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:1068
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.
void ParseFileName(const std::map< wxString, wxString > &aProperties)
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:498
void AddPoint(const wxPoint &aPoint)
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: sch_screen.h:193
void ParseNoERC(const std::map< wxString, wxString > &aProperties)
wxString name
SCH_SHEET * m_rootSheet
The root sheet of the schematic being loaded..
std::vector< wxPoint > points
void SetSecondRadiusAngle(int aAngle)
Definition: lib_arc.h:108
SCH_SHEET * m_currentSheet
The current sheet of the schematic being loaded..
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:287
PLOT_DASH_TYPE
Dashed line types.
Definition: plotter.h:104
wxString designator
SCH_FIELD * GetField(int aFieldNdx)
Returns a field in this symbol.
Field Value of part, i.e. "3.3K".
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.
void SetUnit(int aUnit)
Definition: lib_item.h:295
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:666
LIB_ID AltiumToKiCadLibID(LIB_ID::LIB_ID_TYPE aType, wxString aLibName, wxString aLibReference)
void ParseComponent(int aIndex, const std::map< wxString, wxString > &aProperties)
Bezier curves to polygon converter.
Definition: bezier_curves.h:35
SCH_SHEET & Root() const
Definition: schematic.h:96
bool IsTerminalPoint(const wxPoint &aPosition, int aLayer)
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:481
void SetEnd(const wxPoint &aEnd)
Definition: lib_rectangle.h:86
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 Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:201
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:129
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)
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
Schematic symbol object.
Definition: sch_component.h:79
PROJECT & Prj() const
Return a reference to the project this schematic is part of.
Definition: schematic.h:79
wxPoint GetPosition() const override
void ParseArc(const std::map< wxString, wxString > &aProperties)
SCH_SHEET * Load(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=NULL, const PROPERTIES *aProperties=NULL) override
Load information from some input file format that this SCH_PLUGIN implementation knows about,...
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, LIB_ID_TYPE aType, bool aLib=false)
Replace illegal LIB_ID item name characters with underscores '_'.
Definition: lib_id.cpp:352
FILE_OUTPUTFORMATTER may be used for text file output.
Definition: richio.h:493
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)
void SetPosition(const wxPoint &aPosition) override
Definition: lib_item.h:249
ASCH_RECORD_ORIENTATION orientation
wxPoint location
VTBL_ENTRY const wxString GetProjectName() const
Function GetProjectName returns the short name of the project.
Definition: project.cpp:127
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:173
int ownerpartdisplaymode
void ParseDesignator(const std::map< wxString, wxString > &aProperties)
void SetFileName(const wxString &aFileName)
Definition: sch_screen.h:184
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:232
void SetValue(const SCH_SHEET_PATH *sheet, const wxString &aValue)
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
Plugin to create the KiCad symbol library.
void SetBold(bool aBold)
Definition: eda_text.h:188
ASCH_PIN_SYMBOL_INNEREDGE symbolInnerEdge
void ParseNetLabel(const std::map< wxString, wxString > &aProperties)
void SetLibId(const LIB_ID &aLibId)
void SetPosition(const wxPoint &aPosition) override
Definition: sch_field.cpp:580
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...
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:100
wxString name