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 <[email protected]>
5 * Copyright (C) 2021-2022 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"
28#include "sch_shape.h"
32
33#include <schematic.h>
34
35#include <lib_shape.h>
36#include <lib_id.h>
37#include <lib_item.h>
38#include <lib_pin.h>
39#include <lib_text.h>
40
41#include <sch_bitmap.h>
42#include <sch_bus_entry.h>
43#include <sch_symbol.h>
44#include <sch_junction.h>
45#include <sch_line.h>
46#include <sch_no_connect.h>
47#include <sch_screen.h>
48#include <sch_label.h>
49#include <sch_sheet.h>
50#include <sch_sheet_pin.h>
51#include <sch_textbox.h>
52
53#include <bezier_curves.h>
54#include <compoundfilereader.h>
55#include <string_utils.h>
56#include <sch_edit_frame.h>
57#include <trigo.h>
59#include <wx/mstream.h>
60#include <wx/log.h>
61#include <wx/zstream.h>
62#include <wx/wfstream.h>
63#include <trigo.h>
64
65// Harness port object itself does not contain color information about itself
66// It seems altium is drawing harness ports using these colors
67#define HARNESS_PORT_COLOR_DEFAULT_BACKGROUND COLOR4D( 0.92941176470588238, \
68 0.94901960784313721, \
69 0.98431372549019602, 1.0 )
70
71#define HARNESS_PORT_COLOR_DEFAULT_OUTLINE COLOR4D( 0.56078431372549020, \
72 0.61960784313725492, \
73 0.78823529411764703, 1.0 )
74
75
76static const VECTOR2I GetRelativePosition( const VECTOR2I& aPosition, const SCH_SYMBOL* aSymbol )
77{
79 return t.TransformCoordinate( aPosition - aSymbol->GetPosition() );
80}
81
82
84{
85 int red = color & 0x0000FF;
86 int green = ( color & 0x00FF00 ) >> 8;
87 int blue = ( color & 0xFF0000 ) >> 16;
88
89 return COLOR4D().FromCSSRGBA( red, green, blue, 1.0 );
90}
91
92
94{
95 switch( linestyle )
96 {
101 default: return PLOT_DASH_TYPE::DEFAULT;
102 }
103}
104
105
107{
109 GetColorFromInt( elem.Color ) ) );
110
111 if( !elem.IsSolid )
112 {
114 }
115 else
116 {
118 shape->SetFillColor( GetColorFromInt( elem.AreaColor ) );
119 }
120}
121
122
124{
126
127 if( !elem.IsSolid )
128 {
130 }
131 else if( elem.Color == elem.AreaColor )
132 {
134 }
135 else
136 {
138 }
139}
140
141
143{
144 m_rootSheet = nullptr;
145 m_schematic = nullptr;
148
150}
151
152
154{
155}
156
157
158const wxString SCH_ALTIUM_PLUGIN::GetName() const
159{
160 return "Altium";
161}
162
163
165{
166 return "SchDoc";
167}
168
169
171{
172 return "SchLib";
173}
174
175
177{
178 return 0;
179}
180
181
182bool SCH_ALTIUM_PLUGIN::CheckHeader( const wxString& aFileName )
183{
184 // TODO
185
186 return true;
187}
188
189
191{
192 if( m_libName.IsEmpty() )
193 {
194 // Try to come up with a meaningful name
196
197 if( m_libName.IsEmpty() )
198 {
199 wxFileName fn( m_rootSheet->GetFileName() );
200 m_libName = fn.GetName();
201 }
202
203 if( m_libName.IsEmpty() )
204 m_libName = "noname";
205
206 m_libName += "-altium-import";
208 }
209
210 return m_libName;
211}
212
213
215{
217
218 return fn;
219}
220
221
222SCH_SHEET* SCH_ALTIUM_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchematic,
223 SCH_SHEET* aAppendToMe, const STRING_UTF8_MAP* aProperties )
224{
225 wxCHECK( !aFileName.IsEmpty() && aSchematic, nullptr );
226
227 wxFileName fileName( aFileName );
228 fileName.SetExt( KiCadSchematicFileExtension );
229 m_schematic = aSchematic;
230
231 // Delete on exception, if I own m_rootSheet, according to aAppendToMe
232 std::unique_ptr<SCH_SHEET> deleter( aAppendToMe ? nullptr : m_rootSheet );
233
234 if( aAppendToMe )
235 {
236 wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
237 m_rootSheet = &aSchematic->Root();
238 }
239 else
240 {
241 m_rootSheet = new SCH_SHEET( aSchematic );
242 m_rootSheet->SetFileName( fileName.GetFullPath() );
243
244 aSchematic->SetRoot( m_rootSheet );
245
246 SCH_SHEET_PATH sheetpath;
247 sheetpath.push_back( m_rootSheet );
248
249 // We'll update later if we find a pageNumber record for it.
250 sheetpath.SetPageNumber( "#" );
251 }
252
253 if( !m_rootSheet->GetScreen() )
254 {
255 SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
256 screen->SetFileName( aFileName );
257 m_rootSheet->SetScreen( screen );
258 const_cast<KIID&>( m_rootSheet->m_Uuid ) = screen->GetUuid();
259 }
260
261 SYMBOL_LIB_TABLE* libTable = m_schematic->Prj().SchSymbolLibTable();
262
263 wxCHECK_MSG( libTable, nullptr, "Could not load symbol lib table." );
264
265 m_pi.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
266
269 if( !libTable->HasLibrary( getLibName() ) )
270 {
271 // Create a new empty symbol library.
272 m_pi->CreateSymbolLib( getLibFileName().GetFullPath() );
273 wxString libTableUri = "${KIPRJMOD}/" + getLibFileName().GetFullName();
274
275 // Add the new library to the project symbol library table.
276 libTable->InsertRow( new SYMBOL_LIB_TABLE_ROW( getLibName(), libTableUri,
277 wxString( "KiCad" ) ) );
278
279 // Save project symbol library table.
280 wxFileName fn( m_schematic->Prj().GetProjectPath(),
282
283 // So output formatter goes out of scope and closes the file before reloading.
284 {
285 FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() );
286 libTable->Format( &formatter, 0 );
287 }
288
289 // Reload the symbol library table.
291 m_schematic->Prj().SchSymbolLibTable();
292 }
293
295
296 SCH_SCREEN* rootScreen = m_rootSheet->GetScreen();
297 wxCHECK( rootScreen, nullptr );
298
299 SCH_SHEET_INSTANCE sheetInstance;
300
301 sheetInstance.m_Path = m_sheetPath.Path();
302 sheetInstance.m_PageNumber = wxT( "#" );
303
304 rootScreen->m_sheetInstances.emplace_back( sheetInstance );
305
306 ParseAltiumSch( aFileName );
307
308 m_pi->SaveLibrary( getLibFileName().GetFullPath() );
309
310 SCH_SCREENS allSheets( m_rootSheet );
311 allSheets.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
312 allSheets.ClearEditFlags();
313
314 return m_rootSheet;
315}
316
317
319{
320 return m_sheetPath.LastScreen();
321}
322
323
325{
326 return m_sheetPath.Last();
327}
328
329
330void SCH_ALTIUM_PLUGIN::ParseAltiumSch( const wxString& aFileName )
331{
332 ALTIUM_COMPOUND_FILE altiumSchFile( aFileName );
333
334 // Load path may be different from the project path.
335 wxFileName parentFileName = aFileName;
336
337 try
338 {
339 ParseStorage( altiumSchFile ); // we need this before parsing the FileHeader
340 ParseFileHeader( altiumSchFile );
341
342 // Parse "Additional" because sheet is set up during "FileHeader" parsing.
343 ParseAdditional( altiumSchFile );
344 }
345 catch( const CFB::CFBException& exception )
346 {
347 THROW_IO_ERROR( exception.what() );
348 }
349 catch( const std::exception& exc )
350 {
351 wxLogDebug( wxT( "Unhandled exception in Altium schematic parsers: %s." ), exc.what() );
352 throw;
353 }
354
355 SCH_SCREEN* currentScreen = getCurrentScreen();
356 wxCHECK( currentScreen, /* void */ );
357
358 // Descend the sheet hierarchy.
359 for( SCH_ITEM* item : currentScreen->Items().OfType( SCH_SHEET_T ) )
360 {
361 SCH_SCREEN* loadedScreen = nullptr;
362 SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( item );
363
364 wxCHECK2( sheet, continue );
365
366 // The assumption is that all of the Altium schematic files will be in the same
367 // path as the parent sheet path.
368 wxFileName loadAltiumFileName( parentFileName.GetPath(), sheet->GetFileName() );
369
370 if( loadAltiumFileName.GetFullName().IsEmpty() || !loadAltiumFileName.IsFileReadable() )
371 {
372 wxString msg;
373
374 msg.Printf( _( "The file name for sheet %s is undefined, this is probably an"
375 " Altium signal harness that got converted to a sheet." ),
376 sheet->GetName() );
377 m_reporter->Report( msg );
378 sheet->SetScreen( new SCH_SCREEN( m_schematic ) );
379 continue;
380 }
381
382 m_rootSheet->SearchHierarchy( loadAltiumFileName.GetFullPath(), &loadedScreen );
383
384 if( loadedScreen )
385 {
386 sheet->SetScreen( loadedScreen );
387 // Do not need to load the sub-sheets - this has already been done.
388 }
389 else
390 {
391 sheet->SetScreen( new SCH_SCREEN( m_schematic ) );
392 SCH_SCREEN* screen = sheet->GetScreen();
393 sheet->SetName( loadAltiumFileName.GetName() );
394 wxCHECK2( screen, continue );
395
396 m_sheetPath.push_back( sheet );
397 ParseAltiumSch( loadAltiumFileName.GetFullPath() );
398
399 // Map the loaded Altium file to the project file.
400 wxFileName projectFileName = loadAltiumFileName;
401 projectFileName.SetPath( m_schematic->Prj().GetProjectPath() );
402 projectFileName.SetExt( KiCadSchematicFileExtension );
403 sheet->SetFileName( projectFileName.GetFullName() );
404 screen->SetFileName( projectFileName.GetFullPath() );
405
407 }
408 }
409}
410
411
413{
414 const CFB::COMPOUND_FILE_ENTRY* file = aAltiumSchFile.FindStream( { "Storage" } );
415
416 if( file == nullptr )
417 return;
418
419 ALTIUM_PARSER reader( aAltiumSchFile, file );
420
421 std::map<wxString, wxString> properties = reader.ReadProperties();
422 wxString header = ALTIUM_PARSER::ReadString( properties, "HEADER", "" );
423 int weight = ALTIUM_PARSER::ReadInt( properties, "WEIGHT", 0 );
424
425 if( weight < 0 )
426 THROW_IO_ERROR( "Storage weight is negative!" );
427
428 for( int i = 0; i < weight; i++ )
429 {
430 m_altiumStorage.emplace_back( reader );
431 }
432
433 if( reader.HasParsingError() )
434 THROW_IO_ERROR( "stream was not parsed correctly!" );
435
436 // TODO pointhi: is it possible to have multiple headers in one Storage file? Otherwise
437 // throw IO Error.
438 if( reader.GetRemainingBytes() != 0 )
439 {
440 m_reporter->Report( wxString::Format( _( "Storage file not fully parsed "
441 "(%d bytes remaining)." ),
442 reader.GetRemainingBytes() ),
444 }
445}
446
447
449{
450 const CFB::COMPOUND_FILE_ENTRY* file = aAltiumSchFile.FindStream( { "Additional" } );
451
452 if( file == nullptr )
453 return;
454
455 ALTIUM_PARSER reader( aAltiumSchFile, file );
456
457
458 if( reader.GetRemainingBytes() <= 0 )
459 {
460 THROW_IO_ERROR( "Additional section does not contain any data" );
461 }
462 else
463 {
464 std::map<wxString, wxString> properties = reader.ReadProperties();
465
466 int recordId = ALTIUM_PARSER::ReadInt( properties, "RECORD", 0 );
467 ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
468
469 if( record != ALTIUM_SCH_RECORD::HEADER )
470 THROW_IO_ERROR( "Header expected" );
471 }
472
473 for( int index = 0; reader.GetRemainingBytes() > 0; index++ )
474 {
475 std::map<wxString, wxString> properties = reader.ReadProperties();
476
477 int recordId = ALTIUM_PARSER::ReadInt( properties, "RECORD", 0 );
478 ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
479
480 // see: https://github.com/vadmium/python-altium/blob/master/format.md
481 switch( record )
482 {
484 ParseHarnessConnector( index, properties );
485 break;
486
488 ParseHarnessEntry( properties );
489 break;
490
492 ParseHarnessType( properties );
493 break;
494
496 ParseSignalHarness( properties );
497 break;
498
500 m_reporter->Report( _( "Blanket not currently supported." ), RPT_SEVERITY_ERROR );
501 break;
502
503 default:
504 m_reporter->Report( wxString::Format( _( "Unknown or unexpected record ID %d found "
505 "inside \"Additional\" section." ),
506 recordId ),
508 break;
509 }
510 }
511
512 // Handle harness Ports
514 ParseHarnessPort( port );
515
516 if( reader.HasParsingError() )
517 THROW_IO_ERROR( "stream was not parsed correctly!" );
518
519 if( reader.GetRemainingBytes() != 0 )
520 THROW_IO_ERROR( "stream is not fully parsed" );
521}
522
523
525{
526 const CFB::COMPOUND_FILE_ENTRY* file = aAltiumSchFile.FindStream( { "FileHeader" } );
527
528 if( file == nullptr )
529 THROW_IO_ERROR( "FileHeader not found" );
530
531 ALTIUM_PARSER reader( aAltiumSchFile, file );
532
533 if( reader.GetRemainingBytes() <= 0 )
534 {
535 THROW_IO_ERROR( "FileHeader does not contain any data" );
536 }
537 else
538 {
539 std::map<wxString, wxString> properties = reader.ReadProperties();
540
541 int recordId = ALTIUM_PARSER::ReadInt( properties, "RECORD", 0 );
542 ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
543
544 if( record != ALTIUM_SCH_RECORD::HEADER )
545 THROW_IO_ERROR( "Header expected" );
546 }
547
548 // Prepare some local variables
549 wxCHECK( m_altiumPortsCurrentSheet.empty(), /* void */ );
550 wxCHECK( !m_currentTitleBlock, /* void */ );
551
552 m_currentTitleBlock = std::make_unique<TITLE_BLOCK>();
553
554 // index is required to resolve OWNERINDEX
555 for( int index = 0; reader.GetRemainingBytes() > 0; index++ )
556 {
557 std::map<wxString, wxString> properties = reader.ReadProperties();
558
559 int recordId = ALTIUM_PARSER::ReadInt( properties, "RECORD", 0 );
560 ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
561
562 // see: https://github.com/vadmium/python-altium/blob/master/format.md
563 switch( record )
564 {
566 THROW_IO_ERROR( "Header already parsed" );
567
569 ParseComponent( index, properties );
570 break;
571
573 ParsePin( properties );
574 break;
575
577 m_reporter->Report( _( "Record 'IEEE_SYMBOL' not handled." ),
579 break;
580
582 ParseLabel( properties );
583 break;
584
586 ParseBezier( properties );
587 break;
588
590 ParsePolyline( properties );
591 break;
592
594 ParsePolygon( properties );
595 break;
596
598 ParseEllipse( properties );
599 break;
600
602 m_reporter->Report( _( "Record 'PIECHART' not handled." ),
604 break;
605
607 ParseRoundRectangle( properties );
608 break;
609
612 ParseArc( properties );
613 break;
614
616 ParseLine( properties );
617 break;
618
620 ParseRectangle( properties );
621 break;
622
624 ParseSheetSymbol( index, properties );
625 break;
626
628 ParseSheetEntry( properties );
629 break;
630
632 ParsePowerPort( properties );
633 break;
634
636 // Ports are parsed after the sheet was parsed
637 // This is required because we need all electrical connection points before placing.
638 m_altiumPortsCurrentSheet.emplace_back( properties );
639 break;
640
642 ParseNoERC( properties );
643 break;
644
646 ParseNetLabel( properties );
647 break;
648
650 ParseBus( properties );
651 break;
652
654 ParseWire( properties );
655 break;
656
658 ParseTextFrame( properties );
659 break;
660
662 ParseJunction( properties );
663 break;
664
666 ParseImage( properties );
667 break;
668
670 ParseSheet( properties );
671 break;
672
674 ParseSheetName( properties );
675 break;
676
678 ParseFileName( properties );
679 break;
680
682 ParseDesignator( properties );
683 break;
684
686 ParseBusEntry( properties );
687 break;
688
690 break;
691
693 ParseParameter( properties );
694 break;
695
697 break;
698
700 ParseImplementationList( index, properties );
701 break;
702
704 ParseImplementation( properties );
705 break;
706
708 break;
709
711 break;
712
714 break;
715
717 ParseNote( properties );
718 break;
719
721 m_reporter->Report( _( "Compile mask not currently supported." ), RPT_SEVERITY_ERROR );
722 break;
723
725 break;
726
727 default:
728 m_reporter->Report( wxString::Format( _( "Unknown or unexpected record id %d found "
729 "inside \"FileHeader\" section." ),
730 recordId ),
732 break;
733 }
734
736 }
737
738 if( reader.HasParsingError() )
739 THROW_IO_ERROR( "stream was not parsed correctly!" );
740
741 if( reader.GetRemainingBytes() != 0 )
742 THROW_IO_ERROR( "stream is not fully parsed" );
743
744 // assign LIB_SYMBOL -> COMPONENT
745 for( std::pair<const int, SCH_SYMBOL*>& symbol : m_symbols )
746 {
747 auto libSymbolIt = m_libSymbols.find( symbol.first );
748
749 if( libSymbolIt == m_libSymbols.end() )
750 THROW_IO_ERROR( "every symbol should have a symbol attached" );
751
752 m_pi->SaveSymbol( getLibFileName().GetFullPath(),
753 new LIB_SYMBOL( *( libSymbolIt->second ) ), m_properties.get() );
754
755 symbol.second->SetLibSymbol( libSymbolIt->second );
756 }
757
758 SCH_SCREEN* screen = getCurrentScreen();
759 wxCHECK( screen, /* void */ );
760
761 // Handle title blocks
763 m_currentTitleBlock.reset();
764
765 // Handle Ports
766 for( const ASCH_PORT& port : m_altiumPortsCurrentSheet )
767 ParsePort( port );
768
770 m_altiumComponents.clear();
771 m_symbols.clear();
772 m_libSymbols.clear();
773
774 // Otherwise we cannot save the imported sheet?
775 SCH_SHEET* sheet = getCurrentSheet();
776
777 wxCHECK( sheet, /* void */ );
778
779 sheet->SetModified();
780}
781
782
783bool SCH_ALTIUM_PLUGIN::IsComponentPartVisible( int aOwnerindex, int aOwnerpartdisplaymode ) const
784{
785 const auto& component = m_altiumComponents.find( aOwnerindex );
786
787 if( component == m_altiumComponents.end() )
788 return false;
789
790 return component->second.displaymode == aOwnerpartdisplaymode;
791}
792
793
794const ASCH_STORAGE_FILE* SCH_ALTIUM_PLUGIN::GetFileFromStorage( const wxString& aFilename ) const
795{
796 const ASCH_STORAGE_FILE* nonExactMatch = nullptr;
797
798 for( const ASCH_STORAGE_FILE& file : m_altiumStorage )
799 {
800 if( file.filename.IsSameAs( aFilename ) )
801 return &file;
802
803 if( file.filename.EndsWith( aFilename ) )
804 nonExactMatch = &file;
805 }
806
807 return nonExactMatch;
808}
809
810
812 const std::map<wxString, wxString>& aProperties )
813{
814 SCH_SHEET* currentSheet = m_sheetPath.Last();
815 wxCHECK( currentSheet, /* void */ );
816
817 wxString sheetName = currentSheet->GetName();
818
819 if( sheetName.IsEmpty() )
820 sheetName = wxT( "root" );
821
822 ASCH_SYMBOL altiumSymbol( aProperties );
823
824 if( m_altiumComponents.count( aIndex ) )
825 {
826 const ASCH_SYMBOL& currentSymbol = m_altiumComponents.at( aIndex );
827
828 m_reporter->Report( wxString::Format( _( "Symbol \"%s\" in sheet \"%s\" at index %d "
829 "replaced with symbol \"%s\"." ),
830 currentSymbol.libreference,
831 sheetName,
832 aIndex,
833 altiumSymbol.libreference ),
835 }
836
837 auto pair = m_altiumComponents.insert( { aIndex, altiumSymbol } );
838 const ASCH_SYMBOL& elem = pair.first->second;
839
840 // TODO: this is a hack until we correctly apply all transformations to every element
841 wxString name = wxString::Format( "%s_%d%s_%s",
842 sheetName,
843 elem.orientation,
844 elem.isMirrored ? "_mirrored" : "",
845 elem.libreference );
847
848 LIB_SYMBOL* ksymbol = new LIB_SYMBOL( wxEmptyString );
849 ksymbol->SetName( name );
850 ksymbol->SetDescription( elem.componentdescription );
851 ksymbol->SetLibId( libId );
852 m_libSymbols.insert( { aIndex, ksymbol } );
853
854 // each component has its own symbol for now
855 SCH_SYMBOL* symbol = new SCH_SYMBOL();
856
857 symbol->SetPosition( elem.location + m_sheetOffset );
858
859 // TODO: keep it simple for now, and only set position.
860 // component->SetOrientation( elem.orientation );
861 symbol->SetLibId( libId );
862 symbol->SetUnit( std::max( 0, elem.currentpartid ) );
863
864 SCH_SCREEN* screen = getCurrentScreen();
865 wxCHECK( screen, /* void */ );
866
867 screen->Append( symbol );
868
869 m_symbols.insert( { aIndex, symbol } );
870}
871
872
873void SCH_ALTIUM_PLUGIN::ParsePin( const std::map<wxString, wxString>& aProperties )
874{
875 ASCH_PIN elem( aProperties );
876
877 const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
878
879 if( libSymbolIt == m_libSymbols.end() )
880 {
881 // TODO: e.g. can depend on Template (RECORD=39
882 m_reporter->Report( wxString::Format( wxT( "Pin's owner (%d) not found." ),
883 elem.ownerindex ),
885 return;
886 }
887
889 return;
890
891 SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
892 LIB_PIN* pin = new LIB_PIN( libSymbolIt->second );
893 libSymbolIt->second->AddDrawItem( pin );
894
895 pin->SetUnit( std::max( 0, elem.ownerpartid ) );
896
897 pin->SetName( elem.name );
898 pin->SetNumber( elem.designator );
899 pin->SetLength( elem.pinlength );
900
901 if( !elem.showDesignator )
902 pin->SetNumberTextSize( 0 );
903
904 if( !elem.showPinName )
905 pin->SetNameTextSize( 0 );
906
907 VECTOR2I pinLocation = elem.location; // the location given is not the connection point!
908
909 switch( elem.orientation )
910 {
912 pin->SetOrientation( DrawPinOrient::PIN_LEFT );
913 pinLocation.x += elem.pinlength;
914 break;
915
917 pin->SetOrientation( DrawPinOrient::PIN_DOWN );
918 pinLocation.y -= elem.pinlength;
919 break;
920
922 pin->SetOrientation( DrawPinOrient::PIN_RIGHT );
923 pinLocation.x -= elem.pinlength;
924 break;
925
927 pin->SetOrientation( DrawPinOrient::PIN_UP );
928 pinLocation.y += elem.pinlength;
929 break;
930
931 default:
932 m_reporter->Report( _( "Pin has unexpected orientation." ), RPT_SEVERITY_WARNING );
933 break;
934 }
935
936 // TODO: position can be sometimes off a little bit!
937 pin->SetPosition( GetRelativePosition( pinLocation + m_sheetOffset, symbol ) );
938
939 // TODO: the following fix is even worse for now?
940 // pin->SetPosition( GetRelativePosition( elem.kicadLocation, symbol ) );
941
942 switch( elem.electrical )
943 {
946 break;
947
950 break;
951
954 break;
955
958 break;
959
962 break;
963
966 break;
967
970 break;
971
974 break;
975
977 default:
979 m_reporter->Report( _( "Pin has unexpected electrical type." ), RPT_SEVERITY_WARNING );
980 break;
981 }
982
984 m_reporter->Report( _( "Pin has unexpected outer edge type." ), RPT_SEVERITY_WARNING );
985
987 m_reporter->Report( _( "Pin has unexpected inner edge type." ), RPT_SEVERITY_WARNING );
988
990 {
991 switch( elem.symbolInnerEdge )
992 {
995 break;
996
997 default:
998 pin->SetShape( GRAPHIC_PINSHAPE::INVERTED );
999 break;
1000 }
1001 }
1003 {
1004 switch( elem.symbolInnerEdge )
1005 {
1007 pin->SetShape( GRAPHIC_PINSHAPE::CLOCK_LOW );
1008 break;
1009
1010 default:
1011 pin->SetShape( GRAPHIC_PINSHAPE::INPUT_LOW );
1012 break;
1013 }
1014 }
1016 {
1017 pin->SetShape( GRAPHIC_PINSHAPE::OUTPUT_LOW );
1018 }
1019 else
1020 {
1021 switch( elem.symbolInnerEdge )
1022 {
1024 pin->SetShape( GRAPHIC_PINSHAPE::CLOCK );
1025 break;
1026
1027 default:
1028 pin->SetShape( GRAPHIC_PINSHAPE::LINE ); // nothing to do
1029 break;
1030 }
1031 }
1032}
1033
1034
1036 ASCH_RECORD_ORIENTATION orientation )
1037{
1038 int vjustify, hjustify;
1040
1041 switch( justification )
1042 {
1043 default:
1048 vjustify = GR_TEXT_V_ALIGN_BOTTOM;
1049 break;
1050
1054 vjustify = GR_TEXT_V_ALIGN_CENTER;
1055 break;
1056
1060 vjustify = GR_TEXT_V_ALIGN_TOP;
1061 break;
1062 }
1063
1064 switch( justification )
1065 {
1066 default:
1071 hjustify = GR_TEXT_H_ALIGN_LEFT;
1072 break;
1073
1077 hjustify = GR_TEXT_H_ALIGN_CENTER;
1078 break;
1079
1083 hjustify = GR_TEXT_H_ALIGN_RIGHT;
1084 break;
1085 }
1086
1087 switch( orientation )
1088 {
1091 break;
1092
1094 vjustify *= -1;
1095 hjustify *= -1;
1097 break;
1098
1101 break;
1102
1104 vjustify *= -1;
1105 hjustify *= -1;
1107 break;
1108 }
1109
1110 text->SetVertJustify( static_cast<GR_TEXT_V_ALIGN_T>( vjustify ) );
1111 text->SetHorizJustify( static_cast<GR_TEXT_H_ALIGN_T>( hjustify ) );
1112 text->SetTextAngle( angle );
1113}
1114
1115
1116void SCH_ALTIUM_PLUGIN::ParseLabel( const std::map<wxString, wxString>& aProperties )
1117{
1118 ASCH_LABEL elem( aProperties );
1119
1121 {
1122 std::map<wxString, wxString> variableMap = {
1123 { "APPLICATION_BUILDNUMBER", "KICAD_VERSION" },
1124 { "SHEETNUMBER", "#" },
1125 { "SHEETTOTAL", "##" },
1126 { "TITLE", "TITLE" }, // 1:1 maps are sort of useless, but it makes it
1127 { "REVISION", "REVISION" }, // easier to see that the list is complete
1128 { "DATE", "ISSUE_DATE" },
1129 { "CURRENTDATE", "CURRENT_DATE" },
1130 { "COMPANYNAME", "COMPANY" },
1131 { "DOCUMENTNAME", "FILENAME" },
1132 { "PROJECTNAME", "PROJECTNAME" },
1133 };
1134
1135 wxString kicadText = AltiumSpecialStringsToKiCadVariables( elem.text, variableMap );
1136 SCH_TEXT* textItem = new SCH_TEXT( elem.location + m_sheetOffset, kicadText );
1137
1138 SetTextPositioning( textItem, elem.justification, elem.orientation );
1139
1140 size_t fontId = static_cast<int>( elem.fontId );
1141
1142 if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
1143 {
1144 const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
1145 textItem->SetItalic( font.Italic );
1146 textItem->SetBold( font.Bold );
1147 textItem->SetTextSize( { font.Size / 2, font.Size / 2 } );
1148 }
1149
1150 textItem->SetFlags(IS_NEW );
1151
1152 SCH_SCREEN* screen = getCurrentScreen();
1153 wxCHECK( screen, /* void */ );
1154
1155 screen->Append( textItem );
1156 }
1157 else
1158 {
1159 const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1160
1161 if( libSymbolIt == m_libSymbols.end() )
1162 {
1163 // TODO: e.g. can depend on Template (RECORD=39
1164 m_reporter->Report( wxString::Format( wxT( "Label's owner (%d) not found." ),
1165 elem.ownerindex ),
1167 return;
1168 }
1169
1170 SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1171 LIB_TEXT* textItem = new LIB_TEXT( libSymbolIt->second );
1172 libSymbolIt->second->AddDrawItem( textItem );
1173
1174 textItem->SetUnit( std::max( 0, elem.ownerpartid ) );
1175
1176 textItem->SetPosition( GetRelativePosition( elem.location + m_sheetOffset, symbol ) );
1177 textItem->SetText( elem.text );
1178 SetTextPositioning( textItem, elem.justification, elem.orientation );
1179
1180 size_t fontId = static_cast<int>( elem.fontId );
1181
1182 if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
1183 {
1184 const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
1185 textItem->SetItalic( font.Italic );
1186 textItem->SetBold( font.Bold );
1187 textItem->SetTextSize( { font.Size / 2, font.Size / 2 } );
1188 }
1189 }
1190}
1191
1192
1193void SCH_ALTIUM_PLUGIN::ParseTextFrame( const std::map<wxString, wxString>& aProperties )
1194{
1195 ASCH_TEXT_FRAME elem( aProperties );
1196 AddTextBox( &elem );
1197}
1198
1199
1200void SCH_ALTIUM_PLUGIN::ParseNote( const std::map<wxString, wxString>& aProperties )
1201 {
1202 ASCH_NOTE elem( aProperties );
1203 AddTextBox( static_cast<ASCH_TEXT_FRAME*>( &elem ) );
1204
1205 // TODO: need some sort of property system for storing author....
1206}
1207
1208
1210 {
1211 SCH_TEXTBOX* textBox = new SCH_TEXTBOX();
1212
1213 VECTOR2I sheetTopRight = aElem->TopRight + m_sheetOffset;
1214 VECTOR2I sheetBottomLeft = aElem->BottomLeft + m_sheetOffset;
1215 textBox->SetStart( sheetTopRight );
1216 textBox->SetEnd( sheetBottomLeft );
1217
1218 textBox->SetText( aElem->Text );
1219
1220 textBox->SetFillColor( GetColorFromInt( aElem->AreaColor ) );
1221
1222 if( aElem->IsSolid)
1224 else
1225 textBox->SetFilled( false );
1226
1227 if( aElem->ShowBorder )
1229 GetColorFromInt( aElem->BorderColor ) ) );
1230 else
1232 GetColorFromInt( aElem->BorderColor ) ) );
1233
1234 switch( aElem->Alignment )
1235 {
1236 default:
1239 break;
1242 break;
1245 break;
1246 }
1247
1248 // JEY TODO: word-wrap once KiCad supports wrapped text.
1249
1250 size_t fontId = static_cast<int>( aElem->FontID );
1251
1252 if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
1253 {
1254 const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
1255 textBox->SetItalic( font.Italic );
1256 textBox->SetBold( font.Bold );
1257 textBox->SetTextSize( { font.Size / 2, font.Size / 2 } );
1258 //textBox->SetFont( //how to set font, we have a font mane here: ( font.fontname );
1259 }
1260
1261 textBox->SetFlags( IS_NEW );
1262
1263 SCH_SCREEN* screen = getCurrentScreen();
1264 wxCHECK( screen, /* void */ );
1265
1266 screen->Append( textBox );
1267}
1268
1269
1270void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProperties )
1271{
1272 ASCH_BEZIER elem( aProperties );
1273
1274 if( elem.points.size() < 2 )
1275 {
1276 m_reporter->Report( wxString::Format( _( "Bezier has %d control points. At least 2 are "
1277 "expected." ),
1278 static_cast<int>( elem.points.size() ) ),
1280 return;
1281 }
1282
1283 SCH_SCREEN* screen = getCurrentScreen();
1284 wxCHECK( screen, /* void */ );
1285
1287 {
1288 for( size_t i = 0; i + 1 < elem.points.size(); i += 3 )
1289 {
1290 if( i + 2 == elem.points.size() )
1291 {
1292 // special case: single line
1293 SCH_LINE* line = new SCH_LINE( elem.points.at( i ) + m_sheetOffset,
1295
1296 line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
1298
1299 line->SetFlags( IS_NEW );
1300
1301 screen->Append( line );
1302 }
1303 else
1304 {
1305 // simulate Bezier using line segments
1306 std::vector<VECTOR2I> bezierPoints;
1307 std::vector<VECTOR2I> polyPoints;
1308
1309 for( size_t j = i; j < elem.points.size() && j < i + 4; j++ )
1310 bezierPoints.push_back( elem.points.at( j ) );
1311
1312 BEZIER_POLY converter( bezierPoints );
1313 converter.GetPoly( polyPoints );
1314
1315 for( size_t k = 0; k + 1 < polyPoints.size(); k++ )
1316 {
1317 SCH_LINE* line = new SCH_LINE( polyPoints.at( k ) + m_sheetOffset,
1319
1320 line->SetEndPoint( polyPoints.at( k + 1 ) + m_sheetOffset );
1322
1323 line->SetFlags( IS_NEW );
1324 screen->Append( line );
1325 }
1326 }
1327 }
1328 }
1329 else
1330 {
1331 const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1332
1333 if( libSymbolIt == m_libSymbols.end() )
1334 {
1335 // TODO: e.g. can depend on Template (RECORD=39
1336 m_reporter->Report( wxString::Format( wxT( "Bezier's owner (%d) not found." ),
1337 elem.ownerindex ),
1339 return;
1340 }
1341
1343 return;
1344
1345 SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1346
1347 for( size_t i = 0; i + 1 < elem.points.size(); i += 3 )
1348 {
1349 if( i + 2 == elem.points.size() )
1350 {
1351 // special case: single line
1352 LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
1353 libSymbolIt->second->AddDrawItem( line );
1354
1355 line->SetUnit( std::max( 0, elem.ownerpartid ) );
1356
1357 for( size_t j = i; j < elem.points.size() && j < i + 2; j++ )
1358 {
1359 line->AddPoint( GetRelativePosition( elem.points.at( j ) + m_sheetOffset,
1360 symbol ) );
1361 }
1362
1364 }
1365 else if( i + 3 == elem.points.size() )
1366 {
1367 // TODO: special case of a single line with an extra point?
1368 // I haven't a clue what this is all about, but the sample document we have in
1369 // https://gitlab.com/kicad/code/kicad/-/issues/8974 responds best by treating it
1370 // as another single line special case.
1371 LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
1372 libSymbolIt->second->AddDrawItem( line );
1373
1374 line->SetUnit( std::max( 0, elem.ownerpartid ) );
1375
1376 for( size_t j = i; j < elem.points.size() && j < i + 2; j++ )
1377 {
1378 line->AddPoint( GetRelativePosition( elem.points.at( j ) + m_sheetOffset,
1379 symbol ) );
1380 }
1381
1383 }
1384 else
1385 {
1386 // Bezier always has exactly 4 control points
1387 LIB_SHAPE* bezier = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::BEZIER );
1388 libSymbolIt->second->AddDrawItem( bezier );
1389
1390 bezier->SetUnit( std::max( 0, elem.ownerpartid ) );
1391
1392 for( size_t j = i; j < elem.points.size() && j < i + 4; j++ )
1393 {
1394 VECTOR2I pos =
1395 GetRelativePosition( elem.points.at( j ) + m_sheetOffset, symbol );
1396
1397 switch( j - i )
1398 {
1399 case 0: bezier->SetStart( pos ); break;
1400 case 1: bezier->SetBezierC1( pos ); break;
1401 case 2: bezier->SetBezierC2( pos ); break;
1402 case 3: bezier->SetEnd( pos ); break;
1403 default: break; // Can't get here but silence warnings
1404 }
1405 }
1406
1408 }
1409 }
1410 }
1411}
1412
1413
1414void SCH_ALTIUM_PLUGIN::ParsePolyline( const std::map<wxString, wxString>& aProperties )
1415{
1416 ASCH_POLYLINE elem( aProperties );
1417
1418 SCH_SCREEN* screen = getCurrentScreen();
1419 wxCHECK( screen, /* void */ );
1420
1422 {
1423 SCH_SHAPE* poly = new SCH_SHAPE( SHAPE_T::POLY );
1424
1425 for( VECTOR2I& point : elem.Points )
1426 poly->AddPoint( point + m_sheetOffset );
1427
1429 GetColorFromInt( elem.Color ) ) );
1430 poly->SetFlags( IS_NEW );
1431
1432 screen->Append( poly );
1433 }
1434 else
1435 {
1436 const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex );
1437
1438 if( libSymbolIt == m_libSymbols.end() )
1439 {
1440 // TODO: e.g. can depend on Template (RECORD=39
1441 m_reporter->Report( wxString::Format( wxT( "Polyline's owner (%d) not found." ),
1442 elem.OwnerIndex ),
1444 return;
1445 }
1446
1448 return;
1449
1450 SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1451 LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
1452 libSymbolIt->second->AddDrawItem( line );
1453
1454 line->SetUnit( elem.OwnerPartID );
1455
1456 for( VECTOR2I& point : elem.Points )
1457 line->AddPoint( GetRelativePosition( point + m_sheetOffset, symbol ) );
1458
1460 GetColorFromInt( elem.Color ) ) );
1461 }
1462}
1463
1464
1465void SCH_ALTIUM_PLUGIN::ParsePolygon( const std::map<wxString, wxString>& aProperties )
1466{
1467 ASCH_POLYGON elem( aProperties );
1468
1469 SCH_SCREEN* screen = getCurrentScreen();
1470 wxCHECK( screen, /* void */ );
1471
1473 {
1474 SCH_SHAPE* poly = new SCH_SHAPE( SHAPE_T::POLY );
1475
1476 for( VECTOR2I& point : elem.points )
1477 poly->AddPoint( point + m_sheetOffset );
1478 poly->AddPoint( elem.points.front() + m_sheetOffset );
1479
1480 SetSchShapeFillAndColor( elem, poly );
1481 poly->SetFlags( IS_NEW );
1482
1483 screen->Append( poly );
1484 }
1485 else
1486 {
1487 const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex );
1488
1489 if( libSymbolIt == m_libSymbols.end() )
1490 {
1491 // TODO: e.g. can depend on Template (RECORD=39
1492 m_reporter->Report( wxString::Format( wxT( "Polygon's owner (%d) not found." ),
1493 elem.OwnerIndex ),
1495 return;
1496 }
1497
1499 return;
1500
1501 SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1502 LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
1503 libSymbolIt->second->AddDrawItem( line );
1504
1505 line->SetUnit( elem.OwnerPartID );
1506
1507 for( VECTOR2I& point : elem.points )
1508 line->AddPoint( GetRelativePosition( point + m_sheetOffset, symbol ) );
1509
1510 line->AddPoint( GetRelativePosition( elem.points.front() + m_sheetOffset, symbol ) );
1511 SetLibShapeFillAndColor( elem, line );
1512 }
1513}
1514
1515
1516void SCH_ALTIUM_PLUGIN::ParseRoundRectangle( const std::map<wxString, wxString>& aProperties )
1517{
1518 ASCH_ROUND_RECTANGLE elem( aProperties );
1519
1520 VECTOR2I sheetTopRight = elem.TopRight + m_sheetOffset;
1521 VECTOR2I sheetBottomLeft = elem.BottomLeft + m_sheetOffset;
1522
1523 SCH_SCREEN* screen = getCurrentScreen();
1524 wxCHECK( screen, /* void */ );
1525
1527 {
1528 // TODO: misses rounded edges
1529 SCH_SHAPE* rect = new SCH_SHAPE( SHAPE_T::RECT );
1530
1531 rect->SetPosition( sheetTopRight );
1532 rect->SetEnd( sheetBottomLeft );
1533 SetSchShapeFillAndColor( elem, rect );
1534 rect->SetFlags( IS_NEW );
1535
1536 screen->Append( rect );
1537 }
1538 else
1539 {
1540 const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex );
1541
1542 if( libSymbolIt == m_libSymbols.end() )
1543 {
1544 // TODO: e.g. can depend on Template (RECORD=39
1545 m_reporter->Report( wxString::Format( wxT( "Rounded rectangle's owner (%d) not "
1546 "found." ),
1547 elem.OwnerIndex ),
1549 return;
1550 }
1551
1553 return;
1554
1555 SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1556 // TODO: misses rounded edges
1557 LIB_SHAPE* rect = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::RECT );
1558 libSymbolIt->second->AddDrawItem( rect );
1559
1560 rect->SetUnit( elem.OwnerPartID );
1561
1562 rect->SetPosition( GetRelativePosition( elem.TopRight + m_sheetOffset, symbol ) );
1563 rect->SetEnd( GetRelativePosition( elem.BottomLeft + m_sheetOffset, symbol ) );
1564 SetLibShapeFillAndColor( elem, rect );
1565 }
1566}
1567
1568
1569void SCH_ALTIUM_PLUGIN::ParseArc( const std::map<wxString, wxString>& aProperties )
1570{
1571 // The Arc can be ALTIUM_SCH_RECORD::ELLIPTICAL_ARC or ALTIUM_SCH_RECORD::ARC
1572 // Elliptical arcs are not handled in KiCad. So use an arc instead
1573 // TODO: handle elliptical arc better.
1574
1575 ASCH_ARC elem( aProperties );
1576
1577 SCH_SCREEN* screen = getCurrentScreen();
1578 wxCHECK( screen, /* void */ );
1579
1580 int arc_radius = elem.m_Radius;
1581
1582 // Try to approximate this ellipse by an arc. use the biggest of radius and secondary radius
1583 // One can of course use another recipe
1584 if( elem.m_IsElliptical )
1585 arc_radius = std::max( elem.m_Radius, elem.m_SecondaryRadius );
1586
1588 {
1589 if( elem.m_StartAngle == 0 && ( elem.m_EndAngle == 0 || elem.m_EndAngle == 360 ) )
1590 {
1591 SCH_SHAPE* circle = new SCH_SHAPE( SHAPE_T::CIRCLE );
1592
1593 circle->SetPosition( elem.m_Center + m_sheetOffset );
1594 circle->SetEnd( circle->GetPosition() + VECTOR2I( arc_radius, 0 ) );
1596
1597 screen->Append( circle );
1598 }
1599 else
1600 {
1601 SCH_SHAPE* arc = new SCH_SHAPE( SHAPE_T::ARC );
1602 EDA_ANGLE includedAngle( elem.m_EndAngle - elem.m_StartAngle, DEGREES_T );
1603 EDA_ANGLE startAngle( elem.m_EndAngle, DEGREES_T );
1604 VECTOR2I startOffset( KiROUND( arc_radius * startAngle.Cos() ),
1605 -KiROUND( arc_radius * startAngle.Sin() ) );
1606
1607 arc->SetCenter( elem.m_Center + m_sheetOffset );
1608 arc->SetStart( elem.m_Center + startOffset + m_sheetOffset );
1609 arc->SetArcAngleAndEnd( includedAngle.Normalize(), true );
1610
1612
1613 screen->Append( arc );
1614 }
1615 }
1616 else
1617 {
1618 const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1619
1620 if( libSymbolIt == m_libSymbols.end() )
1621 {
1622 // TODO: e.g. can depend on Template (RECORD=39
1623 m_reporter->Report( wxString::Format( wxT( "Arc's owner (%d) not found." ),
1624 elem.ownerindex ),
1626 return;
1627 }
1628
1630 return;
1631
1632 SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1633
1634 if( elem.m_StartAngle == 0 && ( elem.m_EndAngle == 0 || elem.m_EndAngle == 360 ) )
1635 {
1636 LIB_SHAPE* circle = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::CIRCLE );
1637 libSymbolIt->second->AddDrawItem( circle );
1638
1639 circle->SetUnit( std::max( 0, elem.ownerpartid ) );
1640
1641 circle->SetPosition( GetRelativePosition( elem.m_Center + m_sheetOffset, symbol ) );
1642 circle->SetEnd( circle->GetPosition() + VECTOR2I( arc_radius, 0 ) );
1644 }
1645 else
1646 {
1647 LIB_SHAPE* arc = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::ARC );
1648 libSymbolIt->second->AddDrawItem( arc );
1649 arc->SetUnit( std::max( 0, elem.ownerpartid ) );
1650
1651 arc->SetCenter( GetRelativePosition( elem.m_Center + m_sheetOffset, symbol ) );
1652
1653 VECTOR2I arcStart( arc_radius, 0 );
1654 RotatePoint( arcStart, -EDA_ANGLE( elem.m_StartAngle, DEGREES_T ) );
1655 arcStart += arc->GetCenter();
1656 arc->SetStart( arcStart );
1657
1658 VECTOR2I arcEnd( arc_radius, 0 );
1659 RotatePoint( arcEnd, -EDA_ANGLE( elem.m_EndAngle, DEGREES_T ) );
1660 arcEnd += arc->GetCenter();
1661 arc->SetEnd( arcEnd );
1662
1664 }
1665 }
1666}
1667
1668
1669void SCH_ALTIUM_PLUGIN::ParseEllipse( const std::map<wxString, wxString>& aProperties )
1670{
1671 ASCH_ELLIPSE elem( aProperties );
1672
1673 SCH_SCREEN* screen = getCurrentScreen();
1674 wxCHECK( screen, /* void */ );
1675
1676 // To do: Import true ellipses when KiCad supports them
1677 if( elem.Radius != elem.SecondaryRadius )
1678 {
1679 m_reporter->Report( wxString::Format( _( "Unsupported ellipse was not imported at "
1680 "(X = %d; Y = %d)." ),
1681 ( elem.Center + m_sheetOffset ).x,
1682 ( elem.Center + m_sheetOffset ).y ),
1684 return;
1685 }
1686
1688 {
1689 SCH_SHAPE* circle = new SCH_SHAPE( SHAPE_T::CIRCLE );
1690
1691 circle->SetPosition( elem.Center + m_sheetOffset );
1692 circle->SetEnd( circle->GetPosition() + VECTOR2I( elem.Radius, 0 ) );
1694
1695 circle->SetFillColor( GetColorFromInt( elem.AreaColor ) );
1696
1697 if( elem.IsSolid )
1699 else
1700 circle->SetFilled( false );
1701
1702 screen->Append( circle );
1703 }
1704 else
1705 {
1706 const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex );
1707
1708 if( libSymbolIt == m_libSymbols.end() )
1709 {
1710 // TODO: e.g. can depend on Template (RECORD=39
1711 m_reporter->Report( wxString::Format( wxT( "Ellipse's owner (%d) not found." ),
1712 elem.OwnerIndex ),
1714 return;
1715 }
1716
1717 SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1718
1719 LIB_SHAPE* circle = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::CIRCLE );
1720 libSymbolIt->second->AddDrawItem( circle );
1721
1722 circle->SetUnit( elem.OwnerPartID );
1723
1724 circle->SetPosition( GetRelativePosition( elem.Center + m_sheetOffset, symbol ) );
1725 circle->SetEnd( circle->GetPosition() + VECTOR2I( elem.Radius, 0 ) );
1727
1728 circle->SetFillColor( GetColorFromInt( elem.AreaColor ) );
1729
1730 if( elem.IsSolid )
1732 else
1733 circle->SetFilled( false );
1734 }
1735}
1736
1737
1738void SCH_ALTIUM_PLUGIN::ParseLine( const std::map<wxString, wxString>& aProperties )
1739{
1740 ASCH_LINE elem( aProperties );
1741
1742 SCH_SCREEN* screen = getCurrentScreen();
1743 wxCHECK( screen, /* void */ );
1744
1746 {
1747 // close polygon
1749 line->SetEndPoint( elem.point2 + m_sheetOffset );
1750 line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); // TODO?
1751
1752 line->SetFlags( IS_NEW );
1753 screen->Append( line );
1754 }
1755 else
1756 {
1757 const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1758
1759 if( libSymbolIt == m_libSymbols.end() )
1760 {
1761 // TODO: e.g. can depend on Template (RECORD=39
1762 m_reporter->Report( wxString::Format( wxT( "Line's owner (%d) not found." ),
1763 elem.ownerindex ),
1765 return;
1766 }
1767
1769 return;
1770
1771 SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1772 LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
1773 libSymbolIt->second->AddDrawItem( line );
1774
1775 line->SetUnit( std::max( 0, elem.ownerpartid ) );
1776
1777 line->AddPoint( GetRelativePosition( elem.point1 + m_sheetOffset, symbol ) );
1778 line->AddPoint( GetRelativePosition( elem.point2 + m_sheetOffset, symbol ) );
1779
1781 }
1782}
1783
1784
1785void SCH_ALTIUM_PLUGIN::ParseSignalHarness( const std::map<wxString, wxString>& aProperties )
1786{
1787 ASCH_SIGNAL_HARNESS elem( aProperties );
1788
1789 SCH_SCREEN* screen = getCurrentScreen();
1790 wxCHECK( screen, /* void */ );
1791
1793 {
1794 SCH_SHAPE* poly = new SCH_SHAPE( SHAPE_T::POLY );
1795
1796 for( VECTOR2I& point : elem.Points )
1797 poly->AddPoint( point + m_sheetOffset );
1798
1800 GetColorFromInt( elem.Color ) ) );
1801 poly->SetFlags( IS_NEW );
1802
1803 screen->Append( poly );
1804 }
1805 else
1806 {
1807 // No clue if this situation can ever exist
1808 m_reporter->Report( wxT( "Signal harness, belonging to the part is not currently "
1809 "supported." ), RPT_SEVERITY_DEBUG );
1810 }
1811}
1812
1813
1814void SCH_ALTIUM_PLUGIN::ParseHarnessConnector( int aIndex, const std::map<wxString,
1815 wxString>& aProperties )
1816{
1817 ASCH_HARNESS_CONNECTOR elem( aProperties );
1818
1819 SCH_SCREEN* currentScreen = getCurrentScreen();
1820 wxCHECK( currentScreen, /* void */ );
1821
1823 {
1825 elem.Size );
1826
1827 sheet->SetScreen( new SCH_SCREEN( m_schematic ) );
1829 sheet->SetBorderColor( GetColorFromInt( elem.Color ) );
1830
1831 currentScreen->Append( sheet );
1832
1833 SCH_SHEET_PATH sheetpath = m_sheetPath;
1834 sheetpath.push_back( sheet );
1835
1836 sheetpath.SetPageNumber( "Harness #" );
1837
1839 m_sheets.insert( { m_harnessEntryParent, sheet } );
1840 }
1841 else
1842 {
1843 // I have no clue if this situation can ever exist
1844 m_reporter->Report( wxT( "Harness connector, belonging to the part is not currently "
1845 "supported." ),
1847 }
1848}
1849
1850
1851void SCH_ALTIUM_PLUGIN::ParseHarnessEntry( const std::map<wxString, wxString>& aProperties )
1852{
1853 ASCH_HARNESS_ENTRY elem( aProperties );
1854
1855 const auto& sheetIt = m_sheets.find( m_harnessEntryParent );
1856
1857 if( sheetIt == m_sheets.end() )
1858 {
1859 m_reporter->Report( wxString::Format( wxT( "Harness entry's parent (%d) not found." ),
1862 return;
1863 }
1864
1865 SCH_SHEET_PIN* sheetPin = new SCH_SHEET_PIN( sheetIt->second );
1866 sheetIt->second->AddPin( sheetPin );
1867
1868 sheetPin->SetText( elem.Name );
1870
1871 VECTOR2I pos = sheetIt->second->GetPosition();
1872 VECTOR2I size = sheetIt->second->GetSize();
1873
1874 switch( elem.Side )
1875 {
1876 default:
1878 sheetPin->SetPosition( { pos.x, pos.y + elem.DistanceFromTop } );
1880 sheetPin->SetSide( SHEET_SIDE::LEFT );
1881 break;
1883 sheetPin->SetPosition( { pos.x + size.x, pos.y + elem.DistanceFromTop } );
1885 sheetPin->SetSide( SHEET_SIDE::RIGHT );
1886 break;
1888 sheetPin->SetPosition( { pos.x + elem.DistanceFromTop, pos.y } );
1890 sheetPin->SetSide( SHEET_SIDE::TOP );
1891 break;
1893 sheetPin->SetPosition( { pos.x + elem.DistanceFromTop, pos.y + size.y } );
1895 sheetPin->SetSide( SHEET_SIDE::BOTTOM );
1896 break;
1897 }
1898}
1899
1900
1901void SCH_ALTIUM_PLUGIN::ParseHarnessType( const std::map<wxString, wxString>& aProperties )
1902{
1903 ASCH_HARNESS_TYPE elem( aProperties );
1904
1905 const auto& sheetIt = m_sheets.find( m_harnessEntryParent );
1906
1907 if( sheetIt == m_sheets.end() )
1908 {
1909 m_reporter->Report( wxString::Format( wxT( "Harness type's parent (%d) not found." ),
1912 return;
1913 }
1914
1915 SCH_FIELD& sheetNameField = sheetIt->second->GetFields()[SHEETNAME];
1916
1917 sheetNameField.SetPosition( elem.Location + m_sheetOffset );
1918 sheetNameField.SetText( elem.Text );
1919
1920 // Always set as visible so user is aware about ( !elem.isHidden );
1921 sheetNameField.SetVisible( true );
1924 sheetNameField.SetTextColor( GetColorFromInt( elem.Color ) );
1925
1926 SCH_FIELD& sheetFileName = sheetIt->second->GetFields()[SHEETFILENAME];
1927 sheetFileName.SetText( elem.Text + wxT( "." ) + KiCadSchematicFileExtension );
1928
1929 wxFileName fn( m_schematic->Prj().GetProjectPath(), elem.Text, KiCadSchematicFileExtension );
1930 wxString fullPath = fn.GetFullPath();
1931
1932 fullPath.Replace( wxT( "\\" ), wxT( "/" ) );
1933
1934 SCH_SCREEN* screen = sheetIt->second->GetScreen();
1935
1936 wxCHECK( screen, /* void */ );
1937 screen->SetFileName( fullPath );
1938
1939 m_reporter->Report( wxString::Format( _( "Altium's harness connector (%s) was imported as a "
1940 "hierarchical sheet. Please review the imported "
1941 "schematic." ),
1942 elem.Text ),
1944}
1945
1946
1947void SCH_ALTIUM_PLUGIN::ParseRectangle( const std::map<wxString, wxString>& aProperties )
1948{
1949 ASCH_RECTANGLE elem( aProperties );
1950
1951 VECTOR2I sheetTopRight = elem.TopRight + m_sheetOffset;
1952 VECTOR2I sheetBottomLeft = elem.BottomLeft + m_sheetOffset;
1953
1954 SCH_SCREEN* screen = getCurrentScreen();
1955 wxCHECK( screen, /* void */ );
1956
1958 {
1959 SCH_SHAPE* rect = new SCH_SHAPE( SHAPE_T::RECT );
1960
1961 rect->SetPosition( sheetTopRight );
1962 rect->SetEnd( sheetBottomLeft );
1963 SetSchShapeFillAndColor( elem, rect );
1964 rect->SetFlags( IS_NEW );
1965
1966 screen->Append( rect );
1967 }
1968 else
1969 {
1970 const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex );
1971
1972 if( libSymbolIt == m_libSymbols.end() )
1973 {
1974 // TODO: e.g. can depend on Template (RECORD=39
1975 m_reporter->Report( wxString::Format( wxT( "Rectangle's owner (%d) not found." ),
1976 elem.OwnerIndex ),
1978 return;
1979 }
1980
1982 return;
1983
1984 SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1985 LIB_SHAPE* rect = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::RECT );
1986 libSymbolIt->second->AddDrawItem( rect );
1987
1988 rect->SetUnit( elem.OwnerPartID );
1989
1990 rect->SetPosition( GetRelativePosition( sheetTopRight, symbol ) );
1991 rect->SetEnd( GetRelativePosition( sheetBottomLeft, symbol ) );
1992 SetLibShapeFillAndColor( elem, rect );
1993 }
1994}
1995
1996
1998 const std::map<wxString, wxString>& aProperties )
1999{
2000 ASCH_SHEET_SYMBOL elem( aProperties );
2001
2003 elem.size );
2004
2005 sheet->SetBorderColor( GetColorFromInt( elem.color ) );
2006
2007 if( elem.isSolid )
2009
2010 sheet->SetFlags( IS_NEW );
2011
2012 SCH_SCREEN* currentScreen = getCurrentScreen();
2013 wxCHECK( currentScreen, /* void */ );
2014 currentScreen->Append( sheet );
2015
2016 SCH_SHEET_PATH sheetpath = m_sheetPath;
2017 sheetpath.push_back( sheet );
2018
2019 // We'll update later if we find a pageNumber record for it.
2020 sheetpath.SetPageNumber( "#" );
2021
2022 SCH_SCREEN* rootScreen = m_rootSheet->GetScreen();
2023 wxCHECK( rootScreen, /* void */ );
2024
2025 SCH_SHEET_INSTANCE sheetInstance;
2026
2027 sheetInstance.m_Path = sheetpath.Path();
2028 sheetInstance.m_PageNumber = wxT( "#" );
2029
2030 rootScreen->m_sheetInstances.emplace_back( sheetInstance );
2031 m_sheets.insert( { aIndex, sheet } );
2032}
2033
2034
2035void SCH_ALTIUM_PLUGIN::ParseSheetEntry( const std::map<wxString, wxString>& aProperties )
2036{
2037 ASCH_SHEET_ENTRY elem( aProperties );
2038
2039 const auto& sheetIt = m_sheets.find( elem.ownerindex );
2040
2041 if( sheetIt == m_sheets.end() )
2042 {
2043 m_reporter->Report( wxString::Format( wxT( "Sheet entry's owner (%d) not found." ),
2044 elem.ownerindex ),
2046 return;
2047 }
2048
2049 SCH_SHEET_PIN* sheetPin = new SCH_SHEET_PIN( sheetIt->second );
2050 sheetIt->second->AddPin( sheetPin );
2051
2052 sheetPin->SetText( elem.name );
2054 //sheetPin->SetTextSpinStyle( getSpinStyle( term.OrientAngle, false ) );
2055 //sheetPin->SetPosition( getKiCadPoint( term.Position ) );
2056
2057 VECTOR2I pos = sheetIt->second->GetPosition();
2058 VECTOR2I size = sheetIt->second->GetSize();
2059
2060 switch( elem.side )
2061 {
2062 default:
2064 sheetPin->SetPosition( { pos.x, pos.y + elem.distanceFromTop } );
2066 sheetPin->SetSide( SHEET_SIDE::LEFT );
2067 break;
2068
2070 sheetPin->SetPosition( { pos.x + size.x, pos.y + elem.distanceFromTop } );
2072 sheetPin->SetSide( SHEET_SIDE::RIGHT );
2073 break;
2074
2076 sheetPin->SetPosition( { pos.x + elem.distanceFromTop, pos.y } );
2078 sheetPin->SetSide( SHEET_SIDE::TOP );
2079 break;
2080
2082 sheetPin->SetPosition( { pos.x + elem.distanceFromTop, pos.y + size.y } );
2084 sheetPin->SetSide( SHEET_SIDE::BOTTOM );
2085 break;
2086 }
2087
2088 switch( elem.iotype )
2089 {
2090 default:
2093 break;
2094
2097 break;
2098
2101 break;
2102
2105 break;
2106 }
2107}
2108
2109
2111 REPORTER* aReporter )
2112{
2114 {
2115 LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2116 aKsymbol->AddDrawItem( line1 );
2118 line1->AddPoint( { 0, 0 } );
2119 line1->AddPoint( { 0, schIUScale.MilsToIU( -50 ) } );
2120
2121 if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE )
2122 {
2123 LIB_SHAPE* circle = new LIB_SHAPE( aKsymbol, SHAPE_T::CIRCLE );
2124 aKsymbol->AddDrawItem( circle );
2126 circle->SetPosition( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( -75 ) } );
2127 circle->SetEnd( circle->GetPosition() + VECTOR2I( schIUScale.MilsToIU( 25 ), 0 ) );
2128 }
2129 else
2130 {
2131 LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2132 aKsymbol->AddDrawItem( line2 );
2134 line2->AddPoint( { schIUScale.MilsToIU( -25 ), schIUScale.MilsToIU( -50 ) } );
2135 line2->AddPoint( { schIUScale.MilsToIU( 25 ), schIUScale.MilsToIU( -50 ) } );
2136 line2->AddPoint( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( -100 ) } );
2137 line2->AddPoint( { schIUScale.MilsToIU( -25 ), schIUScale.MilsToIU( -50 ) } );
2138 }
2139
2140 return { 0, schIUScale.MilsToIU( 150 ) };
2141 }
2142 else if( aStyle == ASCH_POWER_PORT_STYLE::WAVE )
2143 {
2144 LIB_SHAPE* line = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2145 aKsymbol->AddDrawItem( line );
2147 line->AddPoint( { 0, 0 } );
2148 line->AddPoint( { 0, schIUScale.MilsToIU( -72 ) } );
2149
2150 LIB_SHAPE* bezier = new LIB_SHAPE( aKsymbol, SHAPE_T::BEZIER );
2151 aKsymbol->AddDrawItem( bezier );
2153 bezier->AddPoint( { schIUScale.MilsToIU( 30 ), schIUScale.MilsToIU( -50 ) } );
2154 bezier->AddPoint( { schIUScale.MilsToIU( 30 ), schIUScale.MilsToIU( -87 ) } );
2155 bezier->AddPoint( { schIUScale.MilsToIU( -30 ), schIUScale.MilsToIU( -63 ) } );
2156 bezier->AddPoint( { schIUScale.MilsToIU( -30 ), schIUScale.MilsToIU( -100 ) } );
2157
2158 return { 0, schIUScale.MilsToIU( 150 ) };
2159 }
2160 else if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND
2162 || aStyle == ASCH_POWER_PORT_STYLE::EARTH
2164 {
2165 LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2166 aKsymbol->AddDrawItem( line1 );
2168 line1->AddPoint( { 0, 0 } );
2169 line1->AddPoint( { 0, schIUScale.MilsToIU( -100 ) } );
2170
2172 {
2173 LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2174 aKsymbol->AddDrawItem( line2 );
2176 line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( -100 ) } );
2177 line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( -100 ) } );
2178
2179 LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2180 aKsymbol->AddDrawItem( line3 );
2182 line3->AddPoint( { schIUScale.MilsToIU( -70 ), schIUScale.MilsToIU( -130 ) } );
2183 line3->AddPoint( { schIUScale.MilsToIU( 70 ), schIUScale.MilsToIU( -130 ) } );
2184
2185 LIB_SHAPE* line4 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2186 aKsymbol->AddDrawItem( line4 );
2188 line4->AddPoint( { schIUScale.MilsToIU( -40 ), schIUScale.MilsToIU( -160 ) } );
2189 line4->AddPoint( { schIUScale.MilsToIU( 40 ), schIUScale.MilsToIU( -160 ) } );
2190
2191 LIB_SHAPE* line5 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2192 aKsymbol->AddDrawItem( line5 );
2194 line5->AddPoint( { schIUScale.MilsToIU( -10 ), schIUScale.MilsToIU( -190 ) } );
2195 line5->AddPoint( { schIUScale.MilsToIU( 10 ), schIUScale.MilsToIU( -190 ) } );
2196 }
2197 else if( aStyle == ASCH_POWER_PORT_STYLE::SIGNAL_GROUND )
2198 {
2199 LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2200 aKsymbol->AddDrawItem( line2 );
2202 line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( -100 ) } );
2203 line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( -100 ) } );
2204 line2->AddPoint( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( -200 ) } );
2205 line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( -100 ) } );
2206 }
2207 else if( aStyle == ASCH_POWER_PORT_STYLE::EARTH )
2208 {
2209 LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2210 aKsymbol->AddDrawItem( line2 );
2212 line2->AddPoint( { schIUScale.MilsToIU( -150 ), schIUScale.MilsToIU( -200 ) } );
2213 line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( -100 ) } );
2214 line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( -100 ) } );
2215 line2->AddPoint( { schIUScale.MilsToIU( 50 ), schIUScale.MilsToIU( -200 ) } );
2216
2217 LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2218 aKsymbol->AddDrawItem( line3 );
2220 line3->AddPoint( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( -100 ) } );
2221 line3->AddPoint( { schIUScale.MilsToIU( -50 ), schIUScale.MilsToIU( -200 ) } );
2222 }
2223 else // ASCH_POWER_PORT_STYLE::GOST_ARROW
2224 {
2225 LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2226 aKsymbol->AddDrawItem( line2 );
2228 line2->AddPoint( { schIUScale.MilsToIU( -25 ), schIUScale.MilsToIU( -50 ) } );
2229 line2->AddPoint( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( -100 ) } );
2230 line2->AddPoint( { schIUScale.MilsToIU( 25 ), schIUScale.MilsToIU( -50 ) } );
2231
2232 return { 0, schIUScale.MilsToIU( 150 ) }; // special case
2233 }
2234
2235 return { 0, schIUScale.MilsToIU( 250 ) };
2236 }
2239 {
2240 LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2241 aKsymbol->AddDrawItem( line1 );
2243 line1->AddPoint( { 0, 0 } );
2244 line1->AddPoint( { 0, schIUScale.MilsToIU( -160 ) } );
2245
2246 LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2247 aKsymbol->AddDrawItem( line2 );
2249 line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( -160 ) } );
2250 line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( -160 ) } );
2251
2252 LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2253 aKsymbol->AddDrawItem( line3 );
2255 line3->AddPoint( { schIUScale.MilsToIU( -60 ), schIUScale.MilsToIU( -200 ) } );
2256 line3->AddPoint( { schIUScale.MilsToIU( 60 ), schIUScale.MilsToIU( -200 ) } );
2257
2258 LIB_SHAPE* line4 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2259 aKsymbol->AddDrawItem( line4 );
2261 line4->AddPoint( { schIUScale.MilsToIU( -20 ), schIUScale.MilsToIU( -240 ) } );
2262 line4->AddPoint( { schIUScale.MilsToIU( 20 ), schIUScale.MilsToIU( -240 ) } );
2263
2265 return { 0, schIUScale.MilsToIU( 300 ) };
2266
2267 LIB_SHAPE* circle = new LIB_SHAPE( aKsymbol, SHAPE_T::CIRCLE );
2268 aKsymbol->AddDrawItem( circle );
2270 circle->SetPosition( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( -160 ) } );
2271 circle->SetEnd( circle->GetPosition() + VECTOR2I( schIUScale.MilsToIU( 120 ), 0 ) );
2272
2273 return { 0, schIUScale.MilsToIU( 350 ) };
2274 }
2275 else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_BAR )
2276 {
2277 LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2278 aKsymbol->AddDrawItem( line1 );
2280 line1->AddPoint( { 0, 0 } );
2281 line1->AddPoint( { 0, schIUScale.MilsToIU( -200 ) } );
2282
2283 LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2284 aKsymbol->AddDrawItem( line2 );
2286 line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( -200 ) } );
2287 line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( -200 ) } );
2288
2289 return { 0, schIUScale.MilsToIU( 250 ) };
2290 }
2291 else
2292 {
2293 if( aStyle != ASCH_POWER_PORT_STYLE::BAR )
2294 {
2295 aReporter->Report( _( "Power Port with unknown style imported as 'Bar' type." ),
2297 }
2298
2299 LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2300 aKsymbol->AddDrawItem( line1 );
2302 line1->AddPoint( { 0, 0 } );
2303 line1->AddPoint( { 0, schIUScale.MilsToIU( -100 ) } );
2304
2305 LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
2306 aKsymbol->AddDrawItem( line2 );
2308 line2->AddPoint( { schIUScale.MilsToIU( -50 ), schIUScale.MilsToIU( -100 ) } );
2309 line2->AddPoint( { schIUScale.MilsToIU( 50 ), schIUScale.MilsToIU( -100 ) } );
2310
2311 return { 0, schIUScale.MilsToIU( 150 ) };
2312 }
2313}
2314
2315
2316void SCH_ALTIUM_PLUGIN::ParsePowerPort( const std::map<wxString, wxString>& aProperties )
2317{
2318 ASCH_POWER_PORT elem( aProperties );
2319 LIB_ID libId = AltiumToKiCadLibID( getLibName(), elem.text );
2320 LIB_SYMBOL* libSymbol = nullptr;
2321
2322 const auto& powerSymbolIt = m_powerSymbols.find( elem.text );
2323
2324 if( powerSymbolIt != m_powerSymbols.end() )
2325 {
2326 libSymbol = powerSymbolIt->second; // cache hit
2327 }
2328 else
2329 {
2330 libSymbol = new LIB_SYMBOL( wxEmptyString );
2331 libSymbol->SetPower();
2332 libSymbol->SetName( elem.text );
2333 libSymbol->GetReferenceField().SetText( "#PWR" );
2334 libSymbol->GetValueField().SetText( elem.text );
2335 libSymbol->GetValueField().SetVisible( true );
2336 libSymbol->SetDescription( wxString::Format( _( "Power symbol creates a global "
2337 "label with name '%s'" ), elem.text ) );
2338 libSymbol->SetKeyWords( "power-flag" );
2339 libSymbol->SetLibId( libId );
2340
2341 // generate graphic
2342 LIB_PIN* pin = new LIB_PIN( libSymbol );
2343 libSymbol->AddDrawItem( pin );
2344
2345 pin->SetName( elem.text );
2346 pin->SetPosition( { 0, 0 } );
2347 pin->SetLength( 0 );
2349
2350 VECTOR2I valueFieldPos =
2352
2353 libSymbol->GetValueField().SetPosition( valueFieldPos );
2354
2355 // this has to be done after parsing the LIB_SYMBOL!
2356 m_pi->SaveSymbol( getLibFileName().GetFullPath(), libSymbol, m_properties.get() );
2357 m_powerSymbols.insert( { elem.text, libSymbol } );
2358 }
2359
2360 SCH_SCREEN* screen = getCurrentScreen();
2361 wxCHECK( screen, /* void */ );
2362
2363 // each symbol has its own powerSymbolIt for now
2364 SCH_SYMBOL* symbol = new SCH_SYMBOL();
2365 symbol->SetRef( &m_sheetPath, "#PWR?" );
2366 symbol->SetValueFieldText( elem.text );
2367 symbol->SetLibId( libId );
2368 symbol->SetLibSymbol( new LIB_SYMBOL( *libSymbol ) );
2369
2370 SCH_FIELD* valueField = symbol->GetField( VALUE_FIELD );
2371 valueField->SetVisible( elem.showNetName );
2372
2373 // TODO: Why do I need to set this a second time?
2374 valueField->SetPosition( libSymbol->GetValueField().GetPosition() );
2375
2376 symbol->SetPosition( elem.location + m_sheetOffset );
2377
2378 switch( elem.orientation )
2379 {
2382 valueField->SetTextAngle( ANGLE_VERTICAL );
2384 break;
2385
2388 valueField->SetTextAngle( ANGLE_HORIZONTAL );
2390 break;
2391
2394 valueField->SetTextAngle( ANGLE_VERTICAL );
2396 break;
2397
2400 valueField->SetTextAngle( ANGLE_HORIZONTAL );
2402 break;
2403
2404 default:
2405 m_reporter->Report( _( "Pin has unexpected orientation." ), RPT_SEVERITY_WARNING );
2406 break;
2407 }
2408
2409 screen->Append( symbol );
2410}
2411
2412
2414{
2415 SCH_TEXTBOX* textBox = new SCH_TEXTBOX();
2416
2417 textBox->SetText( aElem.Name );
2418 textBox->SetTextColor( GetColorFromInt( aElem.TextColor ) );
2419
2420 int height = aElem.Height;
2421 if( height <= 0 )
2422 height = schIUScale.MilsToIU( 100 ); // chose default 50 grid
2423
2424 textBox->SetStartX( ( aElem.Location + m_sheetOffset ).x );
2425 textBox->SetStartY( ( aElem.Location + m_sheetOffset ).y - ( height / 2 ) );
2426 textBox->SetEndX( ( aElem.Location + m_sheetOffset ).x + ( aElem.Width ) );
2427 textBox->SetEndY( ( aElem.Location + m_sheetOffset ).y + ( height / 2 ) );
2428
2431
2434
2435 switch( aElem.Alignment )
2436 {
2437 default:
2440 break;
2441
2444 break;
2445
2448 break;
2449 }
2450
2451 size_t fontId = static_cast<int>( aElem.FontID );
2452
2453 if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
2454 {
2455 const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
2456 textBox->SetItalic( font.Italic );
2457 textBox->SetBold( font.Bold );
2458 textBox->SetTextSize( { font.Size / 2, font.Size / 2 } );
2459 //textBox->SetFont( //how to set font, we have a font mane here: ( font.fontname );
2460 }
2461
2462 textBox->SetFlags( IS_NEW );
2463
2464 SCH_SCREEN* screen = getCurrentScreen();
2465 wxCHECK( screen, /* void */ );
2466
2467 screen->Append( textBox );
2468
2469 m_reporter->Report( wxString::Format( _( "Altium's harness port (%s) was imported as "
2470 "a text box. Please review the imported "
2471 "schematic." ),
2472 aElem.Name ),
2474}
2475
2476
2478{
2479 if( !aElem.HarnessType.IsEmpty() )
2480 {
2481 // Parse harness ports after "Additional" compound section is parsed
2482 m_altiumHarnessPortsCurrentSheet.emplace_back( aElem );
2483 return;
2484 }
2485
2486 VECTOR2I start = aElem.Location + m_sheetOffset;
2487 VECTOR2I end = start;
2488
2489 switch( aElem.Style )
2490 {
2491 default:
2496 end.x += aElem.Width;
2497 break;
2498
2503 end.y -= aElem.Width;
2504 break;
2505 }
2506
2507 // Check which connection points exists in the schematic
2508 SCH_SCREEN* screen = getCurrentScreen();
2509 wxCHECK( screen, /* void */ );
2510
2511 bool startIsWireTerminal = screen->IsTerminalPoint( start, LAYER_WIRE );
2512 bool startIsBusTerminal = screen->IsTerminalPoint( start, LAYER_BUS );
2513
2514 bool endIsWireTerminal = screen->IsTerminalPoint( end, LAYER_WIRE );
2515 bool endIsBusTerminal = screen->IsTerminalPoint( end, LAYER_BUS );
2516
2517 // check if any of the points is a terminal point
2518 // TODO: there seems a problem to detect approximated connections towards component pins?
2519 bool connectionFound = startIsWireTerminal
2520 || startIsBusTerminal
2521 || endIsWireTerminal
2522 || endIsBusTerminal;
2523
2524 if( !connectionFound )
2525 {
2526 m_reporter->Report( wxString::Format( _( "Port %s has no connections." ), aElem.Name ),
2528 }
2529
2530 // Select label position. In case both match, we will add a line later.
2531 VECTOR2I position = ( startIsWireTerminal || startIsBusTerminal ) ? start : end;
2532 SCH_LABEL_BASE* label;
2533
2534 // TODO: detect correct label type depending on sheet settings, etc.
2535 #if 1 // Set to 1 to use SCH_HIERLABEL label, 0 to use SCH_GLOBALLABEL
2536 {
2537 label = new SCH_HIERLABEL( position, aElem.Name );
2538 }
2539 #else
2540 label = new SCH_GLOBALLABEL( position, aElem.Name );
2541 #endif
2542
2543 switch( aElem.IOtype )
2544 {
2545 default:
2548 break;
2549
2552 break;
2553
2556 break;
2557
2560 break;
2561 }
2562
2563 switch( aElem.Style )
2564 {
2565 default:
2570 if( ( startIsWireTerminal || startIsBusTerminal ) )
2572 else
2574 break;
2575
2580 if( ( startIsWireTerminal || startIsBusTerminal ) )
2582 else
2584 break;
2585 }
2586
2587 label->AutoplaceFields( screen, false );
2588
2589 // Default "Sheet References" field should be hidden, at least for now
2590 if( label->GetFields().size() > 0 )
2591 label->GetFields()[0].SetVisible( false );
2592
2593 label->SetFlags( IS_NEW );
2594
2595 screen->Append( label );
2596
2597 // This is a hack, for the case both connection points are valid: add a small wire
2598 if( ( startIsWireTerminal && endIsWireTerminal ) )
2599 {
2600 SCH_LINE* wire = new SCH_LINE( start, SCH_LAYER_ID::LAYER_WIRE );
2601 wire->SetEndPoint( end );
2602 wire->SetLineWidth( schIUScale.MilsToIU( 2 ) );
2603 wire->SetFlags( IS_NEW );
2604 screen->Append( wire );
2605 }
2606 else if( startIsBusTerminal && endIsBusTerminal )
2607 {
2608 SCH_LINE* wire = new SCH_LINE( start, SCH_LAYER_ID::LAYER_BUS );
2609 wire->SetEndPoint( end );
2610 wire->SetLineWidth( schIUScale.MilsToIU( 2 ) );
2611 wire->SetFlags( IS_NEW );
2612 screen->Append( wire );
2613 }
2614}
2615
2616
2617void SCH_ALTIUM_PLUGIN::ParseNoERC( const std::map<wxString, wxString>& aProperties )
2618{
2619 ASCH_NO_ERC elem( aProperties );
2620
2621 SCH_SCREEN* screen = getCurrentScreen();
2622 wxCHECK( screen, /* void */ );
2623
2624 if( elem.isActive )
2625 {
2626 SCH_NO_CONNECT* noConnect = new SCH_NO_CONNECT( elem.location + m_sheetOffset );
2627
2628 noConnect->SetFlags( IS_NEW );
2629 screen->Append( noConnect );
2630 }
2631}
2632
2633
2634void SCH_ALTIUM_PLUGIN::ParseNetLabel( const std::map<wxString, wxString>& aProperties )
2635{
2636 ASCH_NET_LABEL elem( aProperties );
2637
2638 SCH_LABEL* label = new SCH_LABEL( elem.location + m_sheetOffset, elem.text );
2639
2640 SCH_SCREEN* screen = getCurrentScreen();
2641 wxCHECK( screen, /* void */ );
2642
2643 switch( elem.orientation )
2644 {
2647 break;
2648
2651 break;
2652
2655 break;
2656
2659 break;
2660
2661 default:
2662 break;
2663 }
2664
2665 label->SetFlags( IS_NEW );
2666 screen->Append( label );
2667}
2668
2669
2670void SCH_ALTIUM_PLUGIN::ParseBus( const std::map<wxString, wxString>& aProperties )
2671{
2672 ASCH_BUS elem( aProperties );
2673
2674 SCH_SCREEN* screen = getCurrentScreen();
2675 wxCHECK( screen, /* void */ );
2676
2677 for( size_t i = 0; i + 1 < elem.points.size(); i++ )
2678 {
2679 SCH_LINE* bus = new SCH_LINE( elem.points.at( i ) + m_sheetOffset,
2681 bus->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
2682 bus->SetLineWidth( elem.lineWidth );
2683
2684 bus->SetFlags( IS_NEW );
2685 screen->Append( bus );
2686 }
2687}
2688
2689
2690void SCH_ALTIUM_PLUGIN::ParseWire( const std::map<wxString, wxString>& aProperties )
2691{
2692 ASCH_WIRE elem( aProperties );
2693
2694 SCH_SCREEN* screen = getCurrentScreen();
2695 wxCHECK( screen, /* void */ );
2696
2697 for( size_t i = 0; i + 1 < elem.points.size(); i++ )
2698 {
2699 SCH_LINE* wire =
2701 wire->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
2702 wire->SetLineWidth( elem.lineWidth );
2703
2704 wire->SetFlags( IS_NEW );
2705 screen->Append( wire );
2706 }
2707}
2708
2709
2710void SCH_ALTIUM_PLUGIN::ParseJunction( const std::map<wxString, wxString>& aProperties )
2711{
2712 SCH_SCREEN* screen = getCurrentScreen();
2713 wxCHECK( screen, /* void */ );
2714
2715 ASCH_JUNCTION elem( aProperties );
2716
2717 SCH_JUNCTION* junction = new SCH_JUNCTION( elem.location + m_sheetOffset );
2718
2719 junction->SetFlags( IS_NEW );
2720 screen->Append( junction );
2721}
2722
2723
2724void SCH_ALTIUM_PLUGIN::ParseImage( const std::map<wxString, wxString>& aProperties )
2725{
2726 ASCH_IMAGE elem( aProperties );
2727
2728 const auto& component = m_altiumComponents.find( elem.ownerindex );
2729
2730 //Hide the image if it is owned by a component but the part id do not match
2731 if( component != m_altiumComponents.end()
2732 && component->second.currentpartid != elem.ownerpartid )
2733 return;
2734
2735 VECTOR2I center = ( elem.location + elem.corner ) / 2 + m_sheetOffset;
2736 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>( center );
2737
2738 SCH_SCREEN* screen = getCurrentScreen();
2739 wxCHECK( screen, /* void */ );
2740
2741 if( elem.embedimage )
2742 {
2743 const ASCH_STORAGE_FILE* storageFile = GetFileFromStorage( elem.filename );
2744
2745 if( !storageFile )
2746 {
2747 wxString msg = wxString::Format( _( "Embedded file %s not found in storage." ),
2748 elem.filename );
2750 return;
2751 }
2752
2753 wxString storagePath = wxFileName::CreateTempFileName( "kicad_import_" );
2754
2755 // As wxZlibInputStream is not seekable, we need to write a temporary file
2756 wxMemoryInputStream fileStream( storageFile->data.data(), storageFile->data.size() );
2757 wxZlibInputStream zlibInputStream( fileStream );
2758 wxFFileOutputStream outputStream( storagePath );
2759 outputStream.Write( zlibInputStream );
2760 outputStream.Close();
2761
2762 if( !bitmap->ReadImageFile( storagePath ) )
2763 {
2764 m_reporter->Report( wxString::Format( _( "Error reading image %s." ), storagePath ),
2766 return;
2767 }
2768
2769 // Remove temporary file
2770 wxRemoveFile( storagePath );
2771 }
2772 else
2773 {
2774 if( !wxFileExists( elem.filename ) )
2775 {
2776 m_reporter->Report( wxString::Format( _( "File not found %s." ), elem.filename ),
2778 return;
2779 }
2780
2781 if( !bitmap->ReadImageFile( elem.filename ) )
2782 {
2783 m_reporter->Report( wxString::Format( _( "Error reading image %s." ), elem.filename ),
2785 return;
2786 }
2787 }
2788
2789 // we only support one scale, thus we need to select one in case it does not keep aspect ratio
2790 VECTOR2I currentImageSize = bitmap->GetSize();
2791 VECTOR2I expectedImageSize = elem.location - elem.corner;
2792 double scaleX = std::abs( static_cast<double>( expectedImageSize.x ) / currentImageSize.x );
2793 double scaleY = std::abs( static_cast<double>( expectedImageSize.y ) / currentImageSize.y );
2794 bitmap->SetImageScale( std::min( scaleX, scaleY ) );
2795
2796 bitmap->SetFlags( IS_NEW );
2797 screen->Append( bitmap.release() );
2798}
2799
2800
2801void SCH_ALTIUM_PLUGIN::ParseSheet( const std::map<wxString, wxString>& aProperties )
2802{
2803 m_altiumSheet = std::make_unique<ASCH_SHEET>( aProperties );
2804
2805 SCH_SCREEN* screen = getCurrentScreen();
2806 wxCHECK( screen, /* void */ );
2807
2808 PAGE_INFO pageInfo;
2809
2810 bool isPortrait = m_altiumSheet->sheetOrientation == ASCH_SHEET_WORKSPACEORIENTATION::PORTRAIT;
2811
2812 switch( m_altiumSheet->sheetSize )
2813 {
2814 default:
2815 case ASCH_SHEET_SIZE::A4: pageInfo.SetType( "A4", isPortrait ); break;
2816 case ASCH_SHEET_SIZE::A3: pageInfo.SetType( "A3", isPortrait ); break;
2817 case ASCH_SHEET_SIZE::A2: pageInfo.SetType( "A2", isPortrait ); break;
2818 case ASCH_SHEET_SIZE::A1: pageInfo.SetType( "A1", isPortrait ); break;
2819 case ASCH_SHEET_SIZE::A0: pageInfo.SetType( "A0", isPortrait ); break;
2820 case ASCH_SHEET_SIZE::A: pageInfo.SetType( "A", isPortrait ); break;
2821 case ASCH_SHEET_SIZE::B: pageInfo.SetType( "B", isPortrait ); break;
2822 case ASCH_SHEET_SIZE::C: pageInfo.SetType( "C", isPortrait ); break;
2823 case ASCH_SHEET_SIZE::D: pageInfo.SetType( "D", isPortrait ); break;
2824 case ASCH_SHEET_SIZE::E: pageInfo.SetType( "E", isPortrait ); break;
2825 case ASCH_SHEET_SIZE::LETTER: pageInfo.SetType( "USLetter", isPortrait ); break;
2826 case ASCH_SHEET_SIZE::LEGAL: pageInfo.SetType( "USLegal", isPortrait ); break;
2827 case ASCH_SHEET_SIZE::TABLOID: pageInfo.SetType( "A3", isPortrait ); break;
2828 case ASCH_SHEET_SIZE::ORCAD_A: pageInfo.SetType( "A", isPortrait ); break;
2829 case ASCH_SHEET_SIZE::ORCAD_B: pageInfo.SetType( "B", isPortrait ); break;
2830 case ASCH_SHEET_SIZE::ORCAD_C: pageInfo.SetType( "C", isPortrait ); break;
2831 case ASCH_SHEET_SIZE::ORCAD_D: pageInfo.SetType( "D", isPortrait ); break;
2832 case ASCH_SHEET_SIZE::ORCAD_E: pageInfo.SetType( "E", isPortrait ); break;
2833 }
2834
2835 screen->SetPageSettings( pageInfo );
2836
2837 m_sheetOffset = { 0, pageInfo.GetHeightIU( schIUScale.IU_PER_MILS ) };
2838}
2839
2840
2841void SCH_ALTIUM_PLUGIN::ParseSheetName( const std::map<wxString, wxString>& aProperties )
2842{
2843 ASCH_SHEET_NAME elem( aProperties );
2844
2845 const auto& sheetIt = m_sheets.find( elem.ownerindex );
2846
2847 if( sheetIt == m_sheets.end() )
2848 {
2849 m_reporter->Report( wxString::Format( wxT( "Sheetname's owner (%d) not found." ),
2850 elem.ownerindex ),
2852 return;
2853 }
2854
2855 SCH_FIELD& sheetNameField = sheetIt->second->GetFields()[SHEETNAME];
2856
2857 sheetNameField.SetPosition( elem.location + m_sheetOffset );
2858 sheetNameField.SetText( elem.text );
2859 sheetNameField.SetVisible( !elem.isHidden );
2861}
2862
2863
2864void SCH_ALTIUM_PLUGIN::ParseFileName( const std::map<wxString, wxString>& aProperties )
2865{
2866 ASCH_FILE_NAME elem( aProperties );
2867
2868 const auto& sheetIt = m_sheets.find( elem.ownerindex );
2869
2870 if( sheetIt == m_sheets.end() )
2871 {
2872 m_reporter->Report( wxString::Format( wxT( "Filename's owner (%d) not found." ),
2873 elem.ownerindex ),
2875 return;
2876 }
2877
2878 SCH_FIELD& filenameField = sheetIt->second->GetFields()[SHEETFILENAME];
2879
2880 filenameField.SetPosition( elem.location + m_sheetOffset );
2881
2882 // Keep the filename of the Altium file until after the file is actually loaded.
2883 filenameField.SetText( elem.text );
2884 filenameField.SetVisible( !elem.isHidden );
2886}
2887
2888
2889void SCH_ALTIUM_PLUGIN::ParseDesignator( const std::map<wxString, wxString>& aProperties )
2890{
2891 ASCH_DESIGNATOR elem( aProperties );
2892
2893 const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
2894
2895 if( libSymbolIt == m_libSymbols.end() )
2896 {
2897 // TODO: e.g. can depend on Template (RECORD=39
2898 m_reporter->Report( wxString::Format( wxT( "Designator's owner (%d) not found." ),
2899 elem.ownerindex ),
2901 return;
2902 }
2903
2904 SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
2905 SCH_SHEET_PATH sheetpath;
2906
2907 SCH_SCREEN* screen = getCurrentScreen();
2908 wxCHECK( screen, /* void */ );
2909
2910 // Graphics symbols have no reference. '#GRAPHIC' allows them to not have footprint associated.
2911 // Note: not all unnamed imported symbols are necessarily graphics.
2912 bool emptyRef = elem.text.IsEmpty();
2913 symbol->SetRef( &m_sheetPath, emptyRef ? wxString( wxS( "#GRAPHIC" ) ) : elem.text );
2914
2915 // I am not sure value and ref should be invisible just because emptyRef is true
2916 // I have examples with this criteria fully incorrect.
2917 bool visible = !emptyRef;
2918
2919 symbol->GetField( VALUE_FIELD )->SetVisible( visible );
2920 symbol->GetField( REFERENCE_FIELD )->SetVisible( visible );
2921
2922 SCH_FIELD* field = symbol->GetField( REFERENCE_FIELD );
2923 field->SetPosition( elem.location + m_sheetOffset );
2924 SetTextPositioning( field, elem.justification, elem.orientation );
2925}
2926
2927
2928void SCH_ALTIUM_PLUGIN::ParseBusEntry( const std::map<wxString, wxString>& aProperties )
2929{
2930 ASCH_BUS_ENTRY elem( aProperties );
2931
2932 SCH_SCREEN* screen = getCurrentScreen();
2933 wxCHECK( screen, /* void */ );
2934
2935 SCH_BUS_WIRE_ENTRY* busWireEntry = new SCH_BUS_WIRE_ENTRY( elem.location + m_sheetOffset );
2936
2937 VECTOR2I vector = elem.corner - elem.location;
2938 busWireEntry->SetSize( { vector.x, vector.y } );
2939
2940 busWireEntry->SetFlags( IS_NEW );
2941 screen->Append( busWireEntry );
2942}
2943
2944
2945void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map<wxString, wxString>& aProperties )
2946{
2947 ASCH_PARAMETER elem( aProperties );
2948
2949 SCH_SCREEN* screen = getCurrentScreen();
2950 wxCHECK( screen, /* void */ );
2951
2952 // TODO: fill in replacements from variant, sheet and project
2953 std::map<wxString, wxString> variableMap = {
2954 { "COMMENT", "VALUE" },
2955 { "VALUE", "ALTIUM_VALUE" },
2956 };
2957
2958 if( elem.ownerindex <= 0 && elem.ownerpartid == ALTIUM_COMPONENT_NONE )
2959 {
2960 // This is some sheet parameter
2961 if( elem.text == "*" )
2962 return; // indicates parameter not set?
2963
2964 wxString paramName = elem.name.Upper();
2965
2966 if( paramName == "SHEETNUMBER" )
2967 {
2969 }
2970 else if( paramName == "TITLE" )
2971 {
2972 m_currentTitleBlock->SetTitle( elem.text );
2973 }
2974 else if( paramName == "REVISION" )
2975 {
2976 m_currentTitleBlock->SetRevision( elem.text );
2977 }
2978 else if( paramName == "DATE" )
2979 {
2980 m_currentTitleBlock->SetDate( elem.text );
2981 }
2982 else if( paramName == "COMPANYNAME" )
2983 {
2984 m_currentTitleBlock->SetCompany( elem.text );
2985 }
2986 else
2987 {
2988 m_schematic->Prj().GetTextVars()[ paramName ] = elem.text;
2989 }
2990 }
2991 else
2992 {
2993 const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
2994
2995 if( libSymbolIt == m_libSymbols.end() )
2996 {
2997 // TODO: e.g. can depend on Template (RECORD=39
2998 return;
2999 }
3000
3001 SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
3002 SCH_FIELD* field = nullptr;
3003 wxString upperName = elem.name.Upper();
3004
3005 if( upperName == "COMMENT" )
3006 {
3007 field = symbol->GetField( VALUE_FIELD );
3008 }
3009 else
3010 {
3011 int fieldIdx = symbol->GetFieldCount();
3012 wxString fieldName = elem.name.Upper();
3013
3014 if( fieldName.IsEmpty() )
3015 {
3016 int disambiguate = 1;
3017
3018 do
3019 {
3020 fieldName = wxString::Format( "ALTIUM_UNNAMED_%d", disambiguate++ );
3021 } while( !symbol->GetFieldText( fieldName ).IsEmpty() );
3022 }
3023 else if( fieldName == "VALUE" )
3024 {
3025 fieldName = "ALTIUM_VALUE";
3026 }
3027
3028 field = symbol->AddField( SCH_FIELD( VECTOR2I(), fieldIdx, symbol, fieldName ) );
3029 }
3030
3031 wxString kicadText = AltiumSpecialStringsToKiCadVariables( elem.text, variableMap );
3032 field->SetText( kicadText );
3033 field->SetPosition( elem.location + m_sheetOffset );
3034 field->SetVisible( !elem.isHidden );
3035 SetTextPositioning( field, elem.justification, elem.orientation );
3036 }
3037}
3038
3039
3041 const std::map<wxString, wxString>& aProperties )
3042{
3043 ASCH_IMPLEMENTATION_LIST elem( aProperties );
3044
3045 m_altiumImplementationList.emplace( aIndex, elem.ownerindex );
3046}
3047
3048
3049void SCH_ALTIUM_PLUGIN::ParseImplementation( const std::map<wxString, wxString>& aProperties )
3050{
3051 ASCH_IMPLEMENTATION elem( aProperties );
3052
3053 // Only get footprint, currently assigned only
3054 if( ( elem.type == "PCBLIB" ) && ( elem.isCurrent ) )
3055 {
3056 const auto& implementationOwnerIt = m_altiumImplementationList.find( elem.ownerindex );
3057
3058 if( implementationOwnerIt == m_altiumImplementationList.end() )
3059 {
3060 m_reporter->Report( wxString::Format( wxT( "Implementation's owner (%d) not found." ),
3061 elem.ownerindex ),
3063 return;
3064 }
3065
3066 const auto& libSymbolIt = m_libSymbols.find( implementationOwnerIt->second );
3067
3068 if( libSymbolIt == m_libSymbols.end() )
3069 {
3070 m_reporter->Report( wxString::Format( wxT( "Footprint's owner (%d) not found." ),
3071 implementationOwnerIt->second ),
3073 return;
3074 }
3075
3076 LIB_ID fpLibId = AltiumToKiCadLibID( elem.libname, elem.name );
3077 wxArrayString fpFilters;
3078 fpFilters.Add( fpLibId.Format() );
3079
3080 libSymbolIt->second->SetFPFilters( fpFilters ); // TODO: not ideal as we overwrite it
3081
3082 SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
3083
3084 symbol->SetFootprintFieldText( fpLibId.Format() );
3085 }
3086}
int color
Definition: DXF_plotter.cpp:57
const char * name
Definition: DXF_plotter.cpp:56
ALTIUM_SCH_RECORD
ASCH_RECORD_ORIENTATION
const int ALTIUM_COMPONENT_NONE
ASCH_LABEL_JUSTIFICATION
ASCH_POLYLINE_LINESTYLE
ASCH_POWER_PORT_STYLE
LIB_ID AltiumToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
wxString AltiumSpecialStringsToKiCadVariables(const wxString &aString, const std::map< wxString, wxString > &aOverrides)
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
const CFB::COMPOUND_FILE_ENTRY * FindStream(const std::vector< std::string > &aStreamPath) const
static int ReadInt(const std::map< wxString, wxString > &aProps, const wxString &aKey, int aDefault)
size_t GetRemainingBytes() const
bool HasParsingError()
std::map< wxString, wxString > ReadProperties()
static wxString ReadString(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
Bezier curves to polygon converter.
Definition: bezier_curves.h:38
void GetPoly(std::vector< VECTOR2I > &aOutput, int aMinSegLen=0, int aMaxSegCount=32)
Convert a Bezier curve to a polygon.
EDA_ANGLE Normalize()
Definition: eda_angle.h:249
double Sin() const
Definition: eda_angle.h:206
double Cos() const
Definition: eda_angle.h:221
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:139
void SetModified()
Definition: eda_item.cpp:64
const KIID m_Uuid
Definition: eda_item.h:492
void SetStartX(int x)
Definition: eda_shape.h:136
void SetBezierC2(const VECTOR2I &aPt)
Definition: eda_shape.h:178
void SetCenter(const VECTOR2I &aCenter)
Definition: eda_shape.cpp:470
void SetEndY(int y)
Definition: eda_shape.h:155
void SetStartY(int y)
Definition: eda_shape.h:130
void SetFilled(bool aFlag)
Definition: eda_shape.h:95
void SetFillColor(const COLOR4D &aColor)
Definition: eda_shape.h:106
void SetEndX(int x)
Definition: eda_shape.h:161
void SetStart(const VECTOR2I &aStart)
Definition: eda_shape.h:124
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:149
void SetBezierC1(const VECTOR2I &aPt)
Definition: eda_shape.h:175
void SetArcAngleAndEnd(const EDA_ANGLE &aAngle, bool aCheckNegativeAngle=false)
Set the end point from the angle center and start.
Definition: eda_shape.cpp:596
void SetFillMode(FILL_T aFill)
Definition: eda_shape.h:100
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:72
void SetTextColor(const COLOR4D &aColor)
Definition: eda_text.h:204
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:219
void SetBold(bool aBold)
Definition: eda_text.cpp:211
void SetTextSize(const VECTOR2I &aNewSize)
Definition: eda_text.cpp:349
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:165
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:195
void SetItalic(bool aItalic)
Definition: eda_text.cpp:203
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:242
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
Used for text file output.
Definition: richio.h:457
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:102
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:576
Definition: kiid.h:48
VECTOR2I GetPosition() const override
Definition: lib_field.h:160
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
UTF8 Format() const
Definition: lib_id.cpp:117
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
Definition: lib_id.cpp:190
void SetPosition(const VECTOR2I &aPosition) override
Definition: lib_item.h:234
void SetUnit(int aUnit)
Definition: lib_item.h:272
void SetStroke(const STROKE_PARAMS &aStroke)
Definition: lib_shape.h:53
void AddPoint(const VECTOR2I &aPosition)
Definition: lib_shape.cpp:518
void SetPosition(const VECTOR2I &aPosition) override
Definition: lib_shape.h:86
VECTOR2I GetCenter() const
Definition: lib_shape.h:88
VECTOR2I GetPosition() const override
Definition: lib_shape.h:85
Define a library symbol object.
Definition: lib_symbol.h:99
LIB_FIELD & GetReferenceField()
Return reference to the reference designator field.
void SetPower()
Definition: lib_symbol.cpp:554
void SetDescription(const wxString &aDescription)
Definition: lib_symbol.h:149
void SetKeyWords(const wxString &aKeyWords)
Definition: lib_symbol.h:162
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:820
LIB_FIELD & GetValueField()
Return reference to the value field.
void SetLibId(const LIB_ID &aLibId)
Definition: lib_symbol.h:142
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:437
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
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
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
int GetHeightIU(double aIUScale) const
Gets the page height in IU.
Definition: page_info.h:153
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:121
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:126
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:132
virtual void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:294
virtual std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:82
@ ELEM_SYMBOL_LIB_TABLE
Definition: project.h:211
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:71
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
Holds all the data relating to one schematic.
Definition: schematic.h:61
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
Definition: schematic.cpp:109
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition: schematic.h:107
SCH_SHEET & Root() const
Definition: schematic.h:91
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:76
std::unique_ptr< ASCH_SHEET > m_altiumSheet
void ParseImplementationList(int aIndex, const std::map< wxString, wxString > &aProperties)
std::vector< ASCH_PORT > m_altiumHarnessPortsCurrentSheet
void ParseStorage(const ALTIUM_COMPOUND_FILE &aAltiumSchFile)
std::map< int, int > m_altiumImplementationList
void AddTextBox(const ASCH_TEXT_FRAME *aElem)
void ParseSheetEntry(const std::map< wxString, wxString > &aProperties)
const wxString GetName() const override
Return a brief hard coded name for this SCH_PLUGIN.
int GetModifyHash() const override
Return the modification hash from the library cache.
void ParseComponent(int aIndex, const std::map< wxString, wxString > &aProperties)
void ParsePin(const std::map< wxString, wxString > &aProperties)
std::map< wxString, LIB_SYMBOL * > m_powerSymbols
void ParseImplementation(const std::map< wxString, wxString > &aProperties)
wxFileName getLibFileName()
void ParseImage(const std::map< wxString, wxString > &aProperties)
void ParseNetLabel(const std::map< wxString, wxString > &aProperties)
void ParseBezier(const std::map< wxString, wxString > &aProperties)
void ParseBusEntry(const std::map< wxString, wxString > &aProperties)
void ParseSheetName(const std::map< wxString, wxString > &aProperties)
void ParseBus(const std::map< wxString, wxString > &aProperties)
void ParseAdditional(const ALTIUM_COMPOUND_FILE &aAltiumSchFile)
void ParseDesignator(const std::map< wxString, wxString > &aProperties)
void ParseSheetSymbol(int aIndex, const std::map< wxString, wxString > &aProperties)
bool IsComponentPartVisible(int aOwnerindex, int aOwnerpartdisplaymode) const
void ParseAltiumSch(const wxString &aFileName)
void ParsePort(const ASCH_PORT &aElem)
void ParsePowerPort(const std::map< wxString, wxString > &aProperties)
void ParseRoundRectangle(const std::map< wxString, wxString > &aProperties)
std::unique_ptr< STRING_UTF8_MAP > m_properties
void ParseWire(const std::map< wxString, wxString > &aProperties)
SCH_SCREEN * getCurrentScreen()
std::vector< ASCH_STORAGE_FILE > m_altiumStorage
std::map< int, LIB_SYMBOL * > m_libSymbols
void ParseSignalHarness(const std::map< wxString, wxString > &aProperties)
void ParseArc(const std::map< wxString, wxString > &aProperties)
std::unique_ptr< TITLE_BLOCK > m_currentTitleBlock
SCH_SHEET_PATH m_sheetPath
void ParseHarnessType(const std::map< wxString, wxString > &aProperties)
const ASCH_STORAGE_FILE * GetFileFromStorage(const wxString &aFilename) const
const wxString GetFileExtension() const override
Return the file extension for the SCH_PLUGIN.
void ParseRectangle(const std::map< wxString, wxString > &aProperties)
SCH_SHEET * getCurrentSheet()
void ParsePolyline(const std::map< wxString, wxString > &aProperties)
void ParseParameter(const std::map< wxString, wxString > &aProperties)
SCH_PLUGIN::SCH_PLUGIN_RELEASER m_pi
void ParseLabel(const std::map< wxString, wxString > &aProperties)
void ParseHarnessConnector(int aIndex, const std::map< wxString, wxString > &aProperties)
std::vector< ASCH_PORT > m_altiumPortsCurrentSheet
void ParseSheet(const std::map< wxString, wxString > &aProperties)
SCH_SHEET * Load(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const STRING_UTF8_MAP *aProperties=nullptr) override
Load information from some input file format that this SCH_PLUGIN implementation knows about,...
void ParseTextFrame(const std::map< wxString, wxString > &aProperties)
void ParseJunction(const std::map< wxString, wxString > &aProperties)
void ParseFileHeader(const ALTIUM_COMPOUND_FILE &aAltiumSchFile)
void ParseNoERC(const std::map< wxString, wxString > &aProperties)
void ParseLine(const std::map< wxString, wxString > &aProperties)
const wxString GetLibraryFileExtension() const override
Return the library file extension for the SCH_PLUGIN object.
void ParsePolygon(const std::map< wxString, wxString > &aProperties)
std::map< int, ASCH_SYMBOL > m_altiumComponents
void ParseNote(const std::map< wxString, wxString > &aProperties)
bool CheckHeader(const wxString &aFileName) override
Return true if the first line in aFileName begins with the expected header.
std::map< int, SCH_SYMBOL * > m_symbols
void ParseHarnessPort(const ASCH_PORT &aElem)
void ParseFileName(const std::map< wxString, wxString > &aProperties)
void ParseEllipse(const std::map< wxString, wxString > &aProperties)
std::map< int, SCH_SHEET * > m_sheets
void ParseHarnessEntry(const std::map< wxString, wxString > &aProperties)
void SetSize(const VECTOR2I &aSize)
Definition: sch_bus_entry.h:72
Class for a wire to bus entry.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_field.cpp:1048
void SetTextSpinStyle(TEXT_SPIN_STYLE aSpinStyle) override
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_label.cpp:1565
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
void SetShape(LABEL_FLAG_SHAPE aShape) override
Definition: sch_label.h:74
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_label.cpp:376
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:90
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
void SetLineWidth(const int aSize)
Definition: sch_line.cpp:316
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: sch_line.h:178
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:144
void set(SCH_PLUGIN *aPlugin)
Definition: sch_io_mgr.h:562
virtual void SaveSymbol(const wxString &aLibraryPath, const LIB_SYMBOL *aSymbol, const STRING_UTF8_MAP *aProperties=nullptr)
Write aSymbol to an existing library located at aLibraryPath.
Definition: sch_plugin.cpp:94
virtual void SaveLibrary(const wxString &aFileName, const STRING_UTF8_MAP *aProperties=nullptr)
Definition: sch_plugin.cpp:45
virtual void CreateSymbolLib(const wxString &aLibraryPath, const STRING_UTF8_MAP *aProperties=nullptr)
Create a new empty symbol library at aLibraryPath.
Definition: sch_plugin.cpp:110
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:662
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in the full schematic.
void ClearEditFlags()
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
Definition: sch_screen.h:640
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: sch_screen.h:157
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:145
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: sch_screen.h:132
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:109
const KIID & GetUuid() const
Definition: sch_screen.h:526
bool IsTerminalPoint(const VECTOR2I &aPosition, int aLayer) const
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:817
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:110
void SetPosition(const VECTOR2I &aPos) override
Definition: sch_shape.h:78
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: sch_shape.cpp:61
void AddPoint(const VECTOR2I &aPosition)
Definition: sch_shape.cpp:504
VECTOR2I GetPosition() const override
Definition: sch_shape.h:77
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
SCH_SCREEN * LastScreen()
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
void pop_back()
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:66
void SetPosition(const VECTOR2I &aPosition) override
void SetSide(SHEET_SIDE aEdge)
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:115
void SetFileName(const wxString &aFilename)
Definition: sch_sheet.h:308
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:302
wxString GetName() const
Definition: sch_sheet.h:103
bool SearchHierarchy(const wxString &aFilename, SCH_SCREEN **aScreen)
Search the existing hierarchy for an instance of screen loaded from aFileName.
Definition: sch_sheet.cpp:723
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:118
void SetName(const wxString &aName)
Definition: sch_sheet.h:104
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:106
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:162
Schematic symbol object.
Definition: sch_symbol.h:81
void SetLibId(const LIB_ID &aName)
Definition: sch_symbol.cpp:284
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_symbol.h:713
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:486
void SetValueFieldText(const wxString &aValue)
Definition: sch_symbol.cpp:844
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:865
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:716
void SetOrientation(int aOrientation)
Compute the new transform matrix based on aOrientation for the symbol which is applied to the current...
void SetFootprintFieldText(const wxString &aFootprint)
Definition: sch_symbol.cpp:859
VECTOR2I GetPosition() const override
Definition: sch_symbol.h:712
TRANSFORM & GetTransform()
Definition: sch_symbol.h:283
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
Definition: sch_symbol.cpp:916
void SetUnit(int aUnit)
Change the unit number to aUnit.
Definition: sch_symbol.cpp:388
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
Definition: sch_symbol.cpp:303
wxString GetFieldText(const wxString &aFieldName) const
Search for a field named aFieldName and returns text associated with this field.
Definition: sch_symbol.cpp:889
virtual void SetTextSpinStyle(TEXT_SPIN_STYLE aSpinStyle)
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_text.cpp:188
A name/value tuple with unique names and optional values.
Simple container to manage line stroke parameters.
Definition: stroke_params.h:88
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_PLUGIN obje...
static const wxString & GetSymbolLibTableFileName()
virtual void Format(OUTPUTFORMATTER *aOutput, int aIndentLevel) const override
Generate the table in s-expression format to aOutput with an indentation level of aIndentLevel.
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:47
TRANSFORM InverseTransform() const
Calculate the Inverse mirror/rotation transform.
Definition: transform.cpp:61
VECTOR2I TransformCoordinate(const VECTOR2I &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:46
static REPORTER & GetInstance()
Definition: reporter.cpp:177
#define _(s)
static constexpr EDA_ANGLE & ANGLE_HORIZONTAL
Definition: eda_angle.h:425
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE & ANGLE_VERTICAL
Definition: eda_angle.h:426
#define IS_NEW
New item, just created.
@ FILLED_WITH_COLOR
@ FILLED_WITH_BG_BODYCOLOR
@ FILLED_SHAPE
const std::string KiCadSymbolLibFileExtension
const std::string KiCadSchematicFileExtension
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
@ LAYER_WIRE
Definition: layer_ids.h:344
@ LAYER_NOTES
Definition: layer_ids.h:358
@ LAYER_BUS
Definition: layer_ids.h:345
@ PIN_LEFT
Definition: lib_pin.h:46
@ PIN_RIGHT
Definition: lib_pin.h:45
@ PIN_UP
Definition: lib_pin.h:47
@ PIN_DOWN
Definition: lib_pin.h:48
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:418
@ PT_INPUT
usual pin input: must be connected
@ PT_OUTPUT
usual output
@ PT_TRISTATE
tris state bus pin
@ PT_BIDI
input or output (like port for a microprocessor)
@ PT_OPENEMITTER
pin type open emitter
@ PT_OPENCOLLECTOR
pin type open collector
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin
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
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_DEBUG
@ RPT_SEVERITY_INFO
static COLOR4D GetColorFromInt(int color)
#define HARNESS_PORT_COLOR_DEFAULT_OUTLINE
static PLOT_DASH_TYPE GetPlotDashType(const ASCH_POLYLINE_LINESTYLE linestyle)
static void SetLibShapeFillAndColor(const ASCH_SHAPE_INTERFACE &elem, LIB_SHAPE *shape)
VECTOR2I HelperGeneratePowerPortGraphics(LIB_SYMBOL *aKsymbol, ASCH_POWER_PORT_STYLE aStyle, REPORTER *aReporter)
static const VECTOR2I GetRelativePosition(const VECTOR2I &aPosition, const SCH_SYMBOL *aSymbol)
#define HARNESS_PORT_COLOR_DEFAULT_BACKGROUND
static void SetSchShapeFillAndColor(const ASCH_SHAPE_INTERFACE &elem, SCH_SHAPE *shape)
void SetTextPositioning(EDA_TEXT *text, ASCH_LABEL_JUSTIFICATION justification, ASCH_RECORD_ORIENTATION orientation)
@ SYM_ORIENT_270
@ SYM_ORIENT_180
@ SYM_ORIENT_90
@ SYM_ORIENT_0
@ SHEETNAME
Definition: sch_sheet.h:45
@ SHEETFILENAME
Definition: sch_sheet.h:46
@ L_BIDI
Definition: sch_text.h:99
@ L_UNSPECIFIED
Definition: sch_text.h:101
@ L_OUTPUT
Definition: sch_text.h:98
@ L_INPUT
Definition: sch_text.h:97
PLOT_DASH_TYPE
Dashed line types.
Definition: stroke_params.h:48
int ownerpartdisplaymode
double m_StartAngle
VECTOR2I m_Center
double m_EndAngle
std::vector< VECTOR2I > points
VECTOR2I corner
VECTOR2I location
std::vector< VECTOR2I > points
ASCH_LABEL_JUSTIFICATION justification
ASCH_RECORD_ORIENTATION orientation
ASCH_RECORD_ORIENTATION orientation
int DistanceFromTop
ASCH_SHEET_ENTRY_SIDE Side
wxString Name
VECTOR2I location
wxString filename
ASCH_RECORD_ORIENTATION orientation
VECTOR2I location
ASCH_LABEL_JUSTIFICATION justification
VECTOR2I point1
VECTOR2I point2
int ownerpartdisplaymode
ASCH_RECORD_ORIENTATION orientation
ASCH_RECORD_ORIENTATION orientation
ASCH_LABEL_JUSTIFICATION justification
ASCH_PIN_SYMBOL_INNEREDGE symbolInnerEdge
ASCH_PIN_SYMBOL_OUTEREDGE symbolOuterEdge
VECTOR2I location
int ownerpartdisplaymode
wxString name
wxString designator
ASCH_PIN_ELECTRICAL electrical
ASCH_RECORD_ORIENTATION orientation
std::vector< VECTOR2I > points
ASCH_POLYLINE_LINESTYLE LineStyle
std::vector< VECTOR2I > Points
VECTOR2I Location
ASCH_TEXT_FRAME_ALIGNMENT Alignment
ASCH_PORT_IOTYPE IOtype
wxString HarnessType
ASCH_PORT_STYLE Style
ASCH_POWER_PORT_STYLE style
ASCH_RECORD_ORIENTATION orientation
wxString name
int distanceFromTop
ASCH_SHEET_ENTRY_SIDE side
ASCH_PORT_IOTYPE iotype
int ownerindex
ASCH_RECORD_ORIENTATION orientation
std::vector< VECTOR2I > Points
std::vector< char > data
wxString componentdescription
wxString libreference
ASCH_TEXT_FRAME_ALIGNMENT Alignment
std::vector< VECTOR2I > points
const double IU_PER_MILS
Definition: base_units.h:78
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
A simple container for sheet instance information.
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
GR_TEXT_H_ALIGN_T
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
GR_TEXT_V_ALIGN_T
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
@ SCH_SHEET_T
Definition: typeinfo.h:158
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< int > VECTOR2I
Definition: vector2d.h:590
Definition of file extensions used in Kicad.