29#include <wx/filename.h>
31#include <wx/tokenzr.h>
32#include <wx/wfstream.h>
33#include <wx/txtstrm.h>
34#include <wx/mstream.h>
35#include <wx/xml/xml.h>
90 bbox.
Merge( item->GetBoundingBox() );
99 return aPinName.BeforeFirst(
'@' );
112 wxCHECK( currentSheet,
nullptr );
157 for(
const std::unique_ptr<ELAYER>& elayer : aLayers )
176 switch ( elayer->number)
206 int roti = int( eagleDegrees );
216 wxASSERT_MSG(
false, wxString::Format( wxT(
"Unhandled orientation (%d degrees)" ),
225 bool aMirror,
bool aSpin,
int aAbsDegress )
227 int align = aEagleAlignment;
229 if( aRelDegress == 90 )
233 else if( aRelDegress == 180 )
237 else if( aRelDegress == 270 )
243 if( aMirror ==
true )
245 if( aAbsDegress == 90 || aAbsDegress == 270 )
256 else if( aAbsDegress == 0 || aAbsDegress == 180 )
350 const std::map<std::string, UTF8>* aProperties )
352 wxASSERT( !aFileName || aSchematic !=
nullptr );
372 wxXmlNode* currentNode = xmlDocument.GetRoot();
378 unique_ptr<SCH_SHEET> deleter( aAppendToMe ?
nullptr :
m_rootSheet );
385 wxCHECK_MSG( aSchematic->
IsValid(),
nullptr,
386 wxT(
"Can't append to a schematic with no root!" ) );
397 if( sheetPath.Last() == aAppendToMe )
408 m_rootSheet->SetFileName( newFilename.GetFullPath() );
427 wxCHECK_MSG(
table,
nullptr,
"Could not load symbol lib table." );
429 m_pi.reset( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
437 wxString libTableUri = wxT(
"${KIPRJMOD}/" ) +
getLibFileName().GetFullName();
442 row.
SetURI( libTableUri );
450 m_eagleDoc = std::make_unique<EAGLE_DOC>( currentNode,
this );
469 const wxString& aLibraryPath,
470 const std::map<std::string, UTF8>* aProperties )
481 for(
const auto& [symName, libSymbol] : it->second.KiCadSymbols )
482 aSymbolNameList.push_back( symName );
488 const wxString& aLibraryPath,
489 const std::map<std::string, UTF8>* aProperties )
500 for(
const auto& [symName, libSymbol] : it->second.KiCadSymbols )
501 aSymbolList.push_back( libSymbol.get() );
507 const std::map<std::string, UTF8>* aProperties )
518 auto it2 = it->second.KiCadSymbols.find( aAliasName );
520 if( it2 != it->second.KiCadSymbols.end() )
521 return it2->second.get();
530 wxFileName fn( aLibraryPath );
532 if( fn.IsFileReadable() && fn.GetModificationTime().IsValid() )
533 return fn.GetModificationTime().GetValue().GetValue();
564 std::unique_ptr<EAGLE_DOC> doc = std::make_unique<EAGLE_DOC>( xmlDocument.GetRoot(),
this );
568 m_version = ( doc->version.IsEmpty() ) ? wxString( wxS(
"0.0" ) ) : doc->version;
580 wxXmlDocument xmlDocument;
581 wxFFileInputStream stream(
m_filename.GetFullPath() );
586 wxString::Format(
_(
"Unable to read file '%s'." ),
m_filename.GetFullPath() ) );
590 wxTextInputStream
text( stream );
591 wxString line =
text.ReadLine();
593 if( !line.StartsWith( wxT(
"<?xml" ) ) && !line.StartsWith( wxT(
"<!--" ) )
594 && !line.StartsWith( wxT(
"<eagle " ) ) )
596 THROW_IO_ERROR( wxString::Format(
_(
"'%s' is an Eagle binary-format file; "
597 "only Eagle XML-format files can be imported." ),
601#if wxCHECK_VERSION( 3, 3, 0 )
604 if( !xmlDocument.Load( stream, wxXMLDOC_NONE, &err ) )
606 if( err.message == wxS(
"no element found" ) )
610 wxMemoryOutputStream memOutput;
613 header <<
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
614 header <<
"<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n";
616 wxScopedCharBuffer headerBuf = header.utf8_str();
617 memOutput.Write( headerBuf.data(), headerBuf.length() );
619 wxFFileInputStream stream2(
m_filename.GetFullPath() );
620 memOutput.Write( stream2 );
622 wxMemoryInputStream memInput( memOutput );
624 if( !xmlDocument.Load( memInput, wxXMLDOC_NONE, &err ) )
631 THROW_IO_ERROR( wxString::Format(
_(
"Unable to read file '%s'.\n'%s' at line %d, column %d, offset %d" ),
632 m_filename.GetFullPath(), err.message, err.line, err.column,
637 if( !xmlDocument.Load( stream ) )
641 wxMemoryOutputStream memOutput;
644 header <<
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
645 header <<
"<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n";
647 wxScopedCharBuffer headerBuf = header.utf8_str();
648 memOutput.Write( headerBuf.data(), headerBuf.length() );
650 wxFFileInputStream stream2(
m_filename.GetFullPath() );
651 memOutput.Write( stream2 );
653 wxMemoryInputStream memInput( memOutput );
655 if( !xmlDocument.Load( memInput ) )
668 wxCHECK( aDrawing, );
672 if( aDrawing->library )
680 if( aDrawing->schematic )
687 for(
const std::unique_ptr<ESHEET>& esheet : aSchematic.
sheets )
689 for(
const std::unique_ptr<ENET>& enet : esheet->nets )
691 wxString netName = enet->netname;
700 for(
const auto& [modname, emodule] : aSchematic.
modules )
702 for(
const std::unique_ptr<ESHEET>& esheet : emodule->sheets )
704 for(
const std::unique_ptr<ENET>& enet : esheet->nets )
706 wxString netName = enet->netname;
721 if( aSchematic.
sheets.empty() )
725 for(
const auto& [
name, epart] : aSchematic.
parts )
728 for(
const auto& [modName, emodule] : aSchematic.
modules )
730 for(
const auto& [partName, epart] : emodule->parts )
736 for(
const auto& [libName, elibrary] : aSchematic.
libraries )
739 elib->
name = elibrary->GetName();
753 for(
const std::unique_ptr<ESHEET>& esheet : aSchematic.
sheets )
757 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>(
m_rootSheet );
759 sheet->SetScreen( screen );
762 wxCHECK2( sheet && screen,
continue );
764 wxString pageNo = wxString::Format( wxT(
"%d" ),
m_sheetIndex );
774 wxCHECK2( currentScreen,
continue );
790 int maxY = sheetBbox.
GetY();
797 const SCH_SYMBOL* origSymbol = cmp.second.cmp;
799 for(
auto& unitEntry : cmp.second.units )
801 if( unitEntry.second ==
false )
805 int unit = unitEntry.first;
809 symbol->SetUnitSelection( &sheetpath, unit );
810 symbol->SetUnit( unit );
811 symbol->SetOrientation( 0 );
812 symbol->AddHierarchicalReference( sheetpath.
Path(), reference, unit );
815 BOX2I cmpBbox = symbol->GetBoundingBox();
816 int posY = newCmpPosition.
y + cmpBbox.
GetHeight();
817 symbol->SetPosition(
VECTOR2I( newCmpPosition.
x, posY ) );
819 maxY = std::max( maxY, posY );
821 if( newCmpPosition.
x >= pageSizeIU.
x )
826 m_rootSheet->GetScreen()->Append( symbol.release() );
839 wxCHECK( sheet && screen, );
843 std::string filename;
850 if( aSheet->description )
851 sheet->
SetName( aSheet->description.value().text );
856 replace( filename.begin(), filename.end(),
' ',
'_' );
858 fn.SetName( filename );
864 for(
const auto& [
name, moduleinst] : aSheet->moduleinsts )
871 for(
const std::unique_ptr<EPOLYGON>& epoly : aSheet->plain->polygons )
874 for(
const std::unique_ptr<EWIRE>& ewire : aSheet->plain->wires )
880 for(
const std::unique_ptr<ETEXT>& etext : aSheet->plain->texts )
883 for(
const std::unique_ptr<ECIRCLE>& ecircle : aSheet->plain->circles )
886 for(
const std::unique_ptr<ERECT>& erectangle : aSheet->plain->rectangles )
889 for(
const std::unique_ptr<EFRAME>& eframe : aSheet->plain->frames )
891 std::vector<SCH_ITEM*> frameItems;
902 for(
const std::unique_ptr<EINSTANCE>& einstance : aSheet->instances )
910 for(
const std::unique_ptr<EBUS>& ebus : aSheet->busses )
919 for(
const std::unique_ptr<ENET>& enet : aSheet->nets )
922 wxString netName = enet->netname;
923 wxString netClass = wxString::Format( wxS(
"%i" ), enet->netcode );
942 if( pageSizeIU.
x < targetSheetSize.
x )
945 if( pageSizeIU.
y < targetSheetSize.
y )
952 VECTOR2I sheetcentre( pageSizeIU.
x / 2, pageSizeIU.
y / 2 );
956 VECTOR2I translation = sheetcentre - itemsCentre;
957 translation.
x = translation.
x - translation.
x %
schIUScale.MilsToIU( 100 );
958 translation.
y = translation.
y - translation.
y %
schIUScale.MilsToIU( 100 );
970 std::vector<SCH_ITEM*> allItems;
972 std::copy( screen->
Items().
begin(), screen->
Items().
end(), std::back_inserter( allItems ) );
976 item->SetPosition( item->GetPosition() + translation );
994 wxCHECK( currentSheet &¤tScreen, );
1000 auto it =
m_eagleDoc->drawing->schematic->modules.find( aModuleInstance->moduleinst );
1003 if( it ==
m_eagleDoc->drawing->schematic->modules.end() )
1005 THROW_IO_ERROR( wxString::Format(
_(
"No module instance '%s' found in schematic "
1007 aModuleInstance->name,
m_filename.GetFullPath() ) );
1011 fn.SetName( aModuleInstance->moduleinst );
1015 VECTOR2I size( it->second->dx.ToSchUnits(), it->second->dy.ToSchUnits() );
1017 int halfX =
KiROUND( size.
x / 2.0 );
1018 int halfY =
KiROUND( size.
y / 2.0 );
1019 int portExtWireLength =
schIUScale.mmToIU( 5.08 );
1020 VECTOR2I pos( aModuleInstance->x.ToSchUnits() - halfX,
1021 -aModuleInstance->y.ToSchUnits() - halfY );
1023 std::unique_ptr<SCH_SHEET> newSheet = std::make_unique<SCH_SHEET>( currentSheet, pos, size );
1031 if( schFile->GetFileName() == fn.GetFullPath() )
1033 newScreen = schFile;
1038 bool isNewSchFile = ( newScreen == nullptr );
1046 wxCHECK( newSheet && newScreen, );
1048 newSheet->SetScreen( newScreen );
1049 newSheet->SetFileName( fn.GetFullName() );
1050 newSheet->SetName( aModuleInstance->name );
1052 for(
const auto& [portName, port] : it->second->ports )
1055 int pinOffset = port->coord.ToSchUnits();
1058 if( port->side ==
"left" )
1062 pinPos.
y = pos.
y + halfY - pinOffset;
1063 portExtWireEndpoint = pinPos;
1064 portExtWireEndpoint.
x -= portExtWireLength;
1066 else if( port->side ==
"right" )
1069 pinPos.
x = pos.
x + size.
x;
1070 pinPos.
y = pos.
y + halfY - pinOffset;
1071 portExtWireEndpoint = pinPos;
1072 portExtWireEndpoint.
x += portExtWireLength;
1074 else if( port->side ==
"top" )
1077 pinPos.
x = pos.
x + halfX + pinOffset;
1079 portExtWireEndpoint = pinPos;
1080 portExtWireEndpoint.
y -= portExtWireLength;
1082 else if( port->side ==
"bottom" )
1085 pinPos.
x = pos.
x + halfX + pinOffset;
1086 pinPos.
y = pos.
y + size.
y;
1087 portExtWireEndpoint = pinPos;
1088 portExtWireEndpoint.
y += portExtWireLength;
1093 currentScreen->
Append( portExtWire );
1097 if( port->direction )
1099 if( *port->direction ==
"in" )
1101 else if( *port->direction ==
"out" )
1103 else if( *port->direction ==
"io" )
1105 else if( *port->direction ==
"hiz" )
1120 newSheet->AddPin( sheetPin );
1123 wxString pageNo = wxString::Format( wxT(
"%d" ),
m_sheetIndex );
1125 newSheet->SetParent( currentSheet );
1128 currentScreen->
Append( newSheet.release() );
1130 m_modules.push_back( it->second.get() );
1136 for(
const std::unique_ptr<ESHEET>& esheet : it->second->sheets )
1146 wxCHECK2( emoduleInst,
continue );
1148 refPrefix += emoduleInst->name + wxS(
":" );
1159 wxCHECK2( symbol && !symbol->
GetInstances().empty(),
continue );
1162 wxString newReference = refPrefix + inst.
m_Reference.AfterLast(
':' );
1176 std::vector<SCH_ITEM*>& aItems )
1178 int xMin = aFrame->x1.ToSchUnits();
1179 int xMax = aFrame->x2.ToSchUnits();
1180 int yMin = -aFrame->y1.ToSchUnits();
1181 int yMax = -aFrame->y2.ToSchUnits();
1184 std::swap( xMin, xMax );
1187 std::swap( yMin, yMax );
1195 aItems.push_back( lines );
1197 if( !( aFrame->border_left ==
false ) )
1204 aItems.push_back( lines );
1207 int height = yMax - yMin;
1210 int legendPosX = xMin +
schIUScale.MilsToIU( 75 );
1211 double rowSpacing = height / double( aFrame->rows );
1212 double legendPosY = yMin + ( rowSpacing / 2 );
1214 for( i = 1; i < aFrame->rows; i++ )
1216 int newY =
KiROUND( yMin + ( rowSpacing * (
double) i ) );
1220 aItems.push_back( lines );
1223 char legendChar =
'A';
1225 for( i = 0; i < aFrame->rows; i++ )
1231 legendText->
SetText( wxString( legendChar ) );
1234 aItems.push_back( legendText );
1236 legendPosY += rowSpacing;
1240 if( !( aFrame->border_right ==
false ) )
1247 aItems.push_back( lines );
1250 int height = yMax - yMin;
1253 int legendPosX = xMax -
schIUScale.MilsToIU( 75 );
1254 double rowSpacing = height / double( aFrame->rows );
1255 double legendPosY = yMin + ( rowSpacing / 2 );
1257 for( i = 1; i < aFrame->rows; i++ )
1259 int newY =
KiROUND( yMin + ( rowSpacing * (
double) i ) );
1263 aItems.push_back( lines );
1266 char legendChar =
'A';
1268 for( i = 0; i < aFrame->rows; i++ )
1274 legendText->
SetText( wxString( legendChar ) );
1277 aItems.push_back( legendText );
1279 legendPosY += rowSpacing;
1283 if( !( aFrame->border_top ==
false ) )
1290 aItems.push_back( lines );
1293 int width = xMax - xMin;
1296 int legendPosY = yMin +
schIUScale.MilsToIU( 75 );
1297 double columnSpacing = width / double( aFrame->columns );
1298 double legendPosX = xMin + ( columnSpacing / 2 );
1300 for( i = 1; i < aFrame->columns; i++ )
1302 int newX =
KiROUND( xMin + ( columnSpacing * (
double) i ) );
1306 aItems.push_back( lines );
1309 char legendChar =
'1';
1311 for( i = 0; i < aFrame->columns; i++ )
1317 legendText->
SetText( wxString( legendChar ) );
1320 aItems.push_back( legendText );
1322 legendPosX += columnSpacing;
1326 if( !( aFrame->border_bottom ==
false ) )
1333 aItems.push_back( lines );
1336 int width = xMax - xMin;
1339 int legendPosY = yMax -
schIUScale.MilsToIU( 75 );
1340 double columnSpacing = width / double( aFrame->columns );
1341 double legendPosX = xMin + ( columnSpacing / 2 );
1343 for( i = 1; i < aFrame->columns; i++ )
1345 int newX =
KiROUND( xMin + ( columnSpacing * (
double) i ) );
1349 aItems.push_back( lines );
1352 char legendChar =
'1';
1354 for( i = 0; i < aFrame->columns; i++ )
1360 legendText->
SetText( wxString( legendChar ) );
1363 aItems.push_back( legendText );
1365 legendPosX += columnSpacing;
1372 const wxString& netName,
1373 const wxString& aNetClass )
1380 size_t segmentCount = aSegments.size();
1382 for(
const std::unique_ptr<ESEGMENT>& esegment : aSegments )
1384 bool labelled =
false;
1385 bool firstWireFound =
false;
1391 for(
const std::unique_ptr<EWIRE>& ewire : esegment->wires )
1400 if( !firstWireFound )
1402 firstWire = thisWire;
1403 firstWireFound =
true;
1409 if( !desc.labels.empty() && desc.labels.front()->GetText() == netName )
1412 for(
const SEG& seg : desc.segs )
1421 segDesc.
segs.push_back( thisWire );
1425 for(
const std::unique_ptr<EJUNCTION>& ejunction : esegment->junctions )
1428 for(
const std::unique_ptr<ELABEL>& elabel : esegment->labels )
1433 wxASSERT( segDesc.
labels.empty()
1436 segDesc.
labels.push_back( label );
1440 for(
const std::unique_ptr<EPINREF>& epinref : esegment->pinRefs )
1442 wxString part = epinref->part;
1443 wxString
pin = epinref->pin;
1445 auto powerPort =
m_powerPorts.find( wxT(
"#" ) + part );
1457 if( !labelled && firstWireFound )
1459 std::unique_ptr<SCH_LABEL_BASE> label;
1464 else if( segmentCount > 1 )
1469 label->SetPosition( firstWire.
A );
1474 if( firstWire.
B.
x > firstWire.
A.
x )
1479 screen->
Append( label.release() );
1488 std::unique_ptr<SCH_SHAPE> poly = std::make_unique<SCH_SHAPE>(
SHAPE_T::POLY );
1492 for(
const std::unique_ptr<EVERTEX>& evertex : aPolygon->vertices )
1494 pt =
VECTOR2I( evertex->x.ToSchUnits(), -evertex->y.ToSchUnits() );
1500 poly->GetPolyShape().Append( arc, -1, -1,
ARC_ACCURACY );
1504 poly->AddPoint( pt );
1508 prev_curve = evertex->curve;
1511 poly->SetLayer(
kiCadLayer( aPolygon->layer ) );
1515 return poly.release();
1523 start.
x = aWire->x1.ToSchUnits();
1524 start.
y = -aWire->y1.ToSchUnits();
1525 end.x = aWire->x2.ToSchUnits();
1526 end.y = -aWire->y2.ToSchUnits();
1529 endpoints =
SEG( start,
end );
1533 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>(
SHAPE_T::ARC );
1536 arc->SetCenter(
center );
1537 arc->SetStart( start );
1544 return arc.release();
1548 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>();
1550 line->SetStartPoint( start );
1551 line->SetEndPoint(
end );
1552 line->SetLayer(
kiCadLayer( aWire->layer ) );
1555 return line.release();
1563 VECTOR2I center( aCircle->x.ToSchUnits(), -aCircle->y.ToSchUnits() );
1576 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>(
SHAPE_T::RECTANGLE );
1578 rectangle->SetLayer(
kiCadLayer( aRectangle->layer ) );
1579 rectangle->SetPosition(
VECTOR2I( aRectangle->x1.ToSchUnits(), -aRectangle->y1.ToSchUnits() ) );
1580 rectangle->SetEnd(
VECTOR2I( aRectangle->x2.ToSchUnits(), -aRectangle->y2.ToSchUnits() ) );
1582 if( aRectangle->rot )
1584 VECTOR2I pos( rectangle->GetPosition() );
1591 rectangle->SetPosition( pos );
1592 rectangle->SetEnd(
end );
1598 return rectangle.release();
1604 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
1606 VECTOR2I pos( aJunction->x.ToSchUnits(), -aJunction->y.ToSchUnits() );
1608 junction->SetPosition( pos );
1610 return junction.release();
1615 const wxString& aNetName )
1617 VECTOR2I elabelpos( aLabel->x.ToSchUnits(), -aLabel->y.ToSchUnits() );
1622 std::unique_ptr<SCH_LABEL_BASE> label;
1624 VECTOR2I textSize =
KiROUND( aLabel->size.ToSchUnits() * 0.7, aLabel->size.ToSchUnits() * 0.7 );
1630 label = std::make_unique<SCH_HIERLABEL>();
1633 const auto it =
m_modules.back()->ports.find( aNetName );
1637 if( it->second->direction )
1639 wxString direction = *it->second->direction;
1641 if( direction ==
"in" )
1643 else if( direction ==
"out" )
1645 else if( direction ==
"io" )
1647 else if( direction ==
"hiz" )
1655 label->SetLabelShape( type );
1660 label = std::make_unique<SCH_LABEL>();
1666 label = std::make_unique<SCH_GLOBALLABEL>();
1671 label = std::make_unique<SCH_LABEL>();
1675 label->SetPosition( elabelpos );
1676 label->SetTextSize( textSize );
1681 for(
int i = 0; i <
KiROUND( aLabel->rot->degrees / 90.0 ) %4; ++i )
1682 label->Rotate90(
false );
1684 if( aLabel->rot->mirror )
1685 label->MirrorSpinStyle(
false );
1688 return label.release();
1692std::pair<VECTOR2I, const SEG*>
1694 const std::vector<SEG>& aLines )
const
1697 const SEG* nearestLine =
nullptr;
1699 double d, mindistance = std::numeric_limits<double>::max();
1702 for(
const SEG& line : aLines )
1707 if( d < mindistance )
1710 nearestPoint = testpoint;
1711 nearestLine = &line;
1714 testpoint = line.Center();
1717 if( d < mindistance )
1720 nearestPoint = testpoint;
1721 nearestLine = &line;
1727 if( d < mindistance )
1730 nearestPoint = testpoint;
1731 nearestLine = &line;
1735 return std::make_pair( nearestPoint, nearestLine );
1740 const std::map<wxString, std::unique_ptr<EPART>>& aParts )
1742 wxCHECK( aInstance, );
1748 const auto partIt = aParts.find( aInstance->part );
1750 if( partIt == aParts.end() )
1752 Report( wxString::Format(
_(
"Error parsing Eagle file. Could not find '%s' "
1753 "instance but it is referenced in the schematic." ),
1760 const std::unique_ptr<EPART>& epart = partIt->second;
1762 wxString libName = epart->library;
1765 if( epart->libraryUrn )
1766 libName += wxS(
"_" ) + epart->libraryUrn->assetId;
1768 wxString gatename = epart->deviceset + wxS(
"_" ) + epart->device + wxS(
"_" ) +
1770 wxString symbolname = wxString( epart->deviceset + epart->device );
1771 symbolname.Replace( wxT(
"*" ), wxEmptyString );
1779 wxString altSymbolName = libName + wxT(
"_" ) + symbolname;
1782 wxString libIdSymbolName = altSymbolName;
1788 Report( wxString::Format( wxS(
"Eagle library '%s' not found while looking up symbol for "
1789 "deviceset '%s', device '%s', and gate '%s." ),
1790 libName, epart->deviceset, epart->device, aInstance->gate ) );
1794 const auto gateIt = libIt->second.GateToUnitMap.find( gatename );
1796 if( gateIt == libIt->second.GateToUnitMap.end() )
1798 Report( wxString::Format( wxS(
"Symbol not found for deviceset '%s', device '%s', and "
1799 "gate '%s in library '%s'." ),
1800 epart->deviceset, epart->device, aInstance->gate, libName ) );
1804 int unit = gateIt->second;
1809 auto p = elib->
package.find( kisymbolname );
1811 if( p != elib->
package.end() )
1812 package = p->second;
1815 std::map<std::string, UTF8> properties;
1822 part =
m_pi->LoadSymbol(
getLibFileName().GetFullPath(), kisymbolname, &properties );
1823 libIdSymbolName = kisymbolname;
1828 Report( wxString::Format(
_(
"Could not find '%s' in the imported library." ),
1835 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
1836 symbol->SetLibId( libId );
1837 symbol->SetUnit( unit );
1838 symbol->SetPosition(
VECTOR2I( aInstance->x.ToSchUnits(), -aInstance->y.ToSchUnits() ) );
1841 if( !package.IsEmpty() )
1843 wxString footprint =
m_schematic->Project().GetProjectName() + wxT(
":" ) + package;
1847 if( aInstance->rot )
1851 if( aInstance->rot->mirror )
1852 symbol->MirrorHorizontally( aInstance->x.ToSchUnits() );
1855 std::vector<SCH_FIELD*> partFields;
1858 for(
const SCH_FIELD* partField : partFields )
1862 if( partField->IsMandatory() )
1863 symbolField = symbol->GetField( partField->GetId() );
1865 symbolField = symbol->GetField( partField->GetName() );
1867 wxCHECK2( symbolField,
continue );
1870 symbolField->
SetTextPos( symbol->GetPosition() + partField->GetTextPos() );
1875 wxString reference = package.IsEmpty() ?
'#' + aInstance->part : aInstance->part;
1878 if( reference.find_last_not_of( wxT(
"0123456789" ) ) == ( reference.Length()-1 ) )
1879 reference.Append( wxT(
"0" ) );
1884 if( reference.find_first_not_of( wxT(
"0123456789" ) ) != 0 )
1885 reference.Prepend( wxT(
"UNK" ) );
1889 if( aInstance->part.find_first_not_of( wxT(
"#" ) ) != 0 )
1890 reference.Prepend( wxT(
"UNK" ) );
1893 referenceField->
SetText( reference );
1896 bool userValue =
m_userValue.at( libIdSymbolName );
1904 if( epart->value && !epart->value.CGet().IsEmpty() )
1906 valueField->
SetText( *epart->value );
1910 valueField->
SetText( kisymbolname );
1916 for(
const auto& [ attrName, attr ] : epart->attributes )
1922 if( !symbol->GetFields().empty() )
1923 newField.
SetTextPos( symbol->GetFields().back().GetPosition() );
1926 newField.
SetText( *attr->value );
1930 symbol->AddField( newField );
1933 for(
const auto& [variantName, variant] : epart->variants )
1936 field->
SetName( wxT(
"VARIANT_" ) + variant->name );
1938 if( variant->value )
1939 field->
SetText( *variant->value );
1944 bool valueAttributeFound =
false;
1945 bool nameAttributeFound =
false;
1948 for(
auto& [
name, eattr] : aInstance->attributes )
1952 if( eattr->name.Lower() == wxT(
"name" ) )
1955 nameAttributeFound =
true;
1957 else if( eattr->name.Lower() == wxT(
"value" ) )
1960 valueAttributeFound =
true;
1964 field = symbol->GetField( eattr->name );
1974 int absdegrees = eattr->rot ? eattr->rot->degrees : 0;
1975 bool mirror = eattr->rot ? eattr->rot->mirror :
false;
1977 if( aInstance->rot && aInstance->rot->mirror )
1980 bool spin = eattr->rot ? eattr->rot->spin :
false;
1985 int rotation = aInstance->rot ? aInstance->rot->degrees : 0;
1986 int reldegrees = ( absdegrees - rotation + 360.0 );
1994 if( aInstance->smashed && aInstance->smashed.Get() )
1996 symbol->GetField(
FIELD_T::VALUE )->SetVisible( valueAttributeFound );
2008 wxCHECK2( emoduleInst,
continue );
2010 refPrefix += emoduleInst->name + wxS(
":" );
2013 symbol->AddHierarchicalReference(
m_sheetPath.Path(), refPrefix + reference, unit );
2019 wxCHECK( libSymbol, );
2021 symbol->SetLibSymbol(
new LIB_SYMBOL( *libSymbol ) );
2023 for(
const SCH_PIN*
pin : symbol->GetLibPins() )
2029 symbol->ClearFlags();
2031 screen->
Append( symbol.release() );
2037 wxCHECK( aLibrary && aEagleLibrary,
nullptr );
2043 wxString prefix = edeviceset->prefix ? edeviceset->prefix.Get() : wxString( wxT(
"" ) );
2044 wxString deviceSetDescr;
2046 if( edeviceset->description )
2050 for(
const std::unique_ptr<EDEVICE>& edevice : edeviceset->devices )
2053 wxString symbolName = edeviceset->name + edevice->name;
2054 symbolName.Replace( wxT(
"*" ), wxEmptyString );
2055 wxASSERT( !symbolName.IsEmpty() );
2058 if( edevice->package )
2059 aEagleLibrary->
package[symbolName] = edevice->package.Get();
2062 std::unique_ptr<LIB_SYMBOL> libSymbol = std::make_unique<LIB_SYMBOL>( symbolName );
2065 int gate_count =
static_cast<int>( edeviceset->gates.size() );
2066 libSymbol->SetUnitCount( gate_count,
true );
2067 libSymbol->LockUnits(
true );
2071 if( prefix.length() == 0 )
2079 reference->
SetText( edevice->package ? prefix :
'#' + prefix );
2082 libSymbol->GetValueField().SetVisible(
true );
2085 bool ispower =
false;
2087 for(
const auto& [gateName, egate] : edeviceset->gates )
2089 const auto it = aLibrary->
symbols.find( egate->symbol );
2091 if( it == aLibrary->
symbols.end() )
2093 Report( wxString::Format( wxS(
"Eagle symbol '%s' not found in library '%s'." ),
2094 egate->symbol, aLibrary->
GetName() ) );
2098 wxString gateMapName = edeviceset->name + wxS(
"_" ) + edevice->name +
2099 wxS(
"_" ) + egate->name;
2101 ispower =
loadSymbol( it->second, libSymbol, edevice, gateindex, egate->name );
2106 libSymbol->SetUnitCount( gate_count,
true );
2108 if( gate_count == 1 && ispower )
2109 libSymbol->SetGlobalPower();
2112 if( edevice->package )
2119 libName =
m_schematic->Project().GetProjectName();
2126 wxString packageString = libName + wxT(
":" ) + aEagleLibrary->
package[symbolName];
2128 libSymbol->GetFootprintField().SetText( packageString );
2131 wxString libName = libSymbol->GetName();
2132 libSymbol->SetName( libName );
2133 libSymbol->SetDescription( deviceSetDescr );
2143 libName = aEagleLibrary->
name + wxT(
"_" ) + libName;
2145 libSymbol->SetName( libName );
2149 std::map<std::string, UTF8> properties;
2163 aEagleLibrary->
KiCadSymbols[ libName ] = std::move( libSymbol );
2167 m_userValue.emplace( std::make_pair( libName, edeviceset->uservalue ==
true ) );
2171 return aEagleLibrary;
2176 std::unique_ptr<LIB_SYMBOL>& aSymbol,
2177 const std::unique_ptr<EDEVICE>& aDevice,
int aGateNumber,
2178 const wxString& aGateName )
2180 wxCHECK( aEsymbol && aSymbol && aDevice,
false );
2182 std::vector<SCH_ITEM*> items;
2184 bool showRefDes =
false;
2185 bool showValue =
false;
2186 bool ispower =
false;
2189 for(
const std::unique_ptr<ECIRCLE>& ecircle : aEsymbol->circles )
2192 for(
const std::unique_ptr<EPIN>& epin : aEsymbol->pins )
2194 std::unique_ptr<SCH_PIN>
pin(
loadPin( aSymbol, epin, aGateNumber ) );
2199 if( epin->direction )
2203 if( epin->direction->Lower() == pinDir.first )
2205 pin->SetType( pinDir.second );
2207 if( pinDir.first == wxT(
"sup" ) )
2216 if( aDevice->connects.size() != 0 )
2218 for(
const std::unique_ptr<ECONNECT>& connect : aDevice->connects )
2220 if( connect->gate == aGateName &&
pin->GetName() == connect->pin )
2222 wxArrayString pads = wxSplit( wxString( connect->pad ),
' ' );
2224 pin->SetUnit( aGateNumber );
2227 if( pads.GetCount() > 1 )
2229 pin->SetNumberTextSize( 0 );
2232 for(
unsigned i = 0; i < pads.GetCount(); i++ )
2236 wxString padname( pads[i] );
2238 aSymbol->AddDrawItem( apin );
2247 pin->SetUnit( aGateNumber );
2248 pin->SetNumber( wxString::Format( wxT(
"%i" ), pincount ) );
2249 aSymbol->AddDrawItem(
pin.release() );
2253 for(
const std::unique_ptr<EPOLYGON>& epolygon : aEsymbol->polygons )
2256 for(
const std::unique_ptr<ERECT>& erectangle : aEsymbol->rectangles )
2259 for(
const std::unique_ptr<ETEXT>& etext : aEsymbol->texts )
2261 std::unique_ptr<SCH_TEXT> libtext(
loadSymbolText( aSymbol, etext, aGateNumber ) );
2263 if( libtext->GetText() == wxT(
"${REFERENCE}" ) )
2269 showRefDes = etext->text == wxT(
">NAME" );
2271 else if( libtext->GetText() == wxT(
"${VALUE}" ) )
2277 showValue = etext->text == wxT(
">VALUE" );
2281 aSymbol->AddDrawItem( libtext.release() );
2285 for(
const std::unique_ptr<EWIRE>& ewire : aEsymbol->wires )
2286 aSymbol->AddDrawItem(
loadSymbolWire( aSymbol, ewire, aGateNumber ) );
2288 for(
const std::unique_ptr<EFRAME>& eframe : aEsymbol->frames )
2290 std::vector<SCH_ITEM*> frameItems;
2296 item->SetParent( aSymbol.get() );
2297 item->SetUnit( aGateNumber );
2298 aSymbol->AddDrawItem( item );
2302 aSymbol->GetReferenceField().SetVisible( showRefDes );
2303 aSymbol->GetValueField().SetVisible( showValue );
2305 return pincount == 1 ? ispower :
false;
2310 const std::unique_ptr<ECIRCLE>& aCircle,
2313 wxCHECK( aSymbol && aCircle,
nullptr );
2317 VECTOR2I center( aCircle->x.ToSchUnits(), -aCircle->y.ToSchUnits() );
2319 circle->SetParent( aSymbol.get() );
2323 circle->SetUnit( aGateNumber );
2330 const std::unique_ptr<ERECT>& aRectangle,
2333 wxCHECK( aSymbol && aRectangle,
nullptr );
2338 rectangle->
SetPosition(
VECTOR2I( aRectangle->x1.ToSchUnits(), -aRectangle->y1.ToSchUnits() ) );
2339 rectangle->
SetEnd(
VECTOR2I( aRectangle->x2.ToSchUnits(), -aRectangle->y2.ToSchUnits() ) );
2341 if( aRectangle->rot )
2354 rectangle->
SetUnit( aGateNumber );
2364 const std::unique_ptr<EWIRE>& aWire,
int aGateNumber )
2366 wxCHECK( aSymbol && aWire,
nullptr );
2370 begin.
x = aWire->x1.ToSchUnits();
2371 begin.
y = -aWire->y1.ToSchUnits();
2372 end.x = aWire->x2.ToSchUnits();
2373 end.y = -aWire->y2.ToSchUnits();
2392 ( aWire->width.ToSchUnits() /
radius );
2393 begin =
center + centerStartVector;
2427 const std::unique_ptr<EPOLYGON>& aPolygon,
2430 wxCHECK( aSymbol && aPolygon,
nullptr );
2438 for(
const std::unique_ptr<EVERTEX>& evertex : aPolygon->vertices )
2440 pt =
VECTOR2I( evertex->x.ToSchUnits(), evertex->y.ToSchUnits() );
2454 prev_curve = evertex->curve;
2466 const std::unique_ptr<EPIN>& aPin,
int aGateNumber )
2468 wxCHECK( aSymbol && aPin,
nullptr );
2470 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>( aSymbol.get() );
2471 pin->SetPosition(
VECTOR2I( aPin->x.ToSchUnits(), -aPin->y.ToSchUnits() ) );
2472 pin->SetName( aPin->name );
2473 pin->SetUnit( aGateNumber );
2475 int roti = aPin->rot ? aPin->rot->degrees : 0;
2483 default: wxFAIL_MSG( wxString::Format( wxT(
"Unhandled orientation (%d degrees)." ), roti ) );
2490 wxString length = aPin->length.Get();
2492 if( length == wxT(
"short" ) )
2494 else if( length == wxT(
"middle" ) )
2496 else if( length == wxT(
"long" ) )
2498 else if( length == wxT(
"point" ) )
2509 wxString visible = aPin->visible.Get();
2511 if( visible == wxT(
"off" ) )
2513 pin->SetNameTextSize( 0 );
2514 pin->SetNumberTextSize( 0 );
2516 else if( visible == wxT(
"pad" ) )
2518 pin->SetNameTextSize( 0 );
2520 else if( visible == wxT(
"pin" ) )
2522 pin->SetNumberTextSize( 0 );
2532 if( aPin->function )
2534 wxString function = aPin->function.Get();
2536 if( function == wxT(
"dot" ) )
2538 else if( function == wxT(
"clk" ) )
2540 else if( function == wxT(
"dotclk" ) )
2544 return pin.release();
2549 const std::unique_ptr<ETEXT>& aText,
int aGateNumber )
2551 wxCHECK( aSymbol && aText,
nullptr );
2553 std::unique_ptr<SCH_TEXT> libtext = std::make_unique<SCH_TEXT>();
2555 libtext->SetParent( aSymbol.get() );
2556 libtext->SetUnit( aGateNumber );
2557 libtext->SetPosition(
VECTOR2I( aText->x.ToSchUnits(), -aText->y.ToSchUnits() ) );
2559 const wxString& eagleText = aText->text;
2560 wxString adjustedText;
2561 wxStringTokenizer tokenizer( eagleText,
"\r\n" );
2564 while( tokenizer.HasMoreTokens() )
2566 wxString tmp =
interpretText( tokenizer.GetNextToken().Trim(
true ).Trim(
false ) );
2568 if( tokenizer.HasMoreTokens() )
2571 adjustedText += tmp;
2574 libtext->SetText( adjustedText.IsEmpty() ? wxString( wxS(
"~" ) ) : adjustedText );
2578 return libtext.release();
2584 wxCHECK( aText,
nullptr );
2586 std::unique_ptr<SCH_TEXT> schtext = std::make_unique<SCH_TEXT>();
2588 const wxString& eagleText = aText->text;
2589 wxString adjustedText;
2590 wxStringTokenizer tokenizer( eagleText,
"\r\n" );
2593 while( tokenizer.HasMoreTokens() )
2595 wxString tmp =
interpretText( tokenizer.GetNextToken().Trim(
true ).Trim(
false ) );
2597 if( tokenizer.HasMoreTokens() )
2600 adjustedText += tmp;
2603 schtext->SetText( adjustedText.IsEmpty() ? wxString( wxS(
"\" \"" ) )
2606 schtext->SetPosition(
VECTOR2I( aText->x.ToSchUnits(), -aText->y.ToSchUnits() ) );
2608 schtext->SetItalic(
false );
2610 return schtext.release();
2615 const std::unique_ptr<ETEXT>& aAttributes )
const
2617 wxCHECK( aText && aAttributes, );
2622 if( aAttributes->ratio && aAttributes->ratio.CGet() > 12 )
2626 int degrees = aAttributes->rot ? aAttributes->rot->degrees : 0;
2627 bool mirror = aAttributes->rot ? aAttributes->rot->mirror :
false;
2628 bool spin = aAttributes->rot ? aAttributes->rot->spin :
false;
2636 wxCHECK( aField && aText, );
2660 auto onIntersection =
2669 for(
SCH_TEXT* label : segDesc.labels )
2672 const SEG* segAttached = segDesc.LabelAttached( label );
2674 if( segAttached && !onIntersection( labelPos ) )
2688 VECTOR2I wireDirection( segAttached->
B - segAttached->
A );
2690 const VECTOR2I origPos( labelPos );
2693 bool checkPositive =
true, checkNegative =
true,
move =
false;
2697 while( ( !
move || onIntersection( labelPos ) ) && ( checkPositive || checkNegative ) )
2702 if( trial % 2 == 1 )
2704 labelPos =
VECTOR2I( origPos + wireDirection * trial / 2 );
2705 move = checkPositive = segAttached->
Contains( labelPos );
2709 labelPos =
VECTOR2I( origPos - wireDirection * trial / 2 );
2710 move = checkNegative = segAttached->
Contains( labelPos );
2746 wxFileInputStream input( aFileName );
2751 wxTextInputStream
text( input );
2753 for(
int i = 0; i < 8; i++ )
2758 if(
text.ReadLine().Contains( wxS(
"<eagle" ) ) )
2776 if( !item->IsType( { SCH_LABEL_LOCATE_ANY_T } ) )
2780 item->SetPosition( aNewEndPoint );
2793 std::vector<SCH_LINE*> buses;
2794 std::vector<SCH_LINE*> wires;
2805 buses.push_back( line );
2806 else if( line->
IsWire() )
2807 wires.push_back( line );
2812 VECTOR2I wireStart = wire->GetStartPoint();
2813 VECTOR2I wireEnd = wire->GetEndPoint();
2817 VECTOR2I busStart = bus->GetStartPoint();
2818 VECTOR2I busEnd = bus->GetEndPoint();
2821 [](
int signX,
int signY ) ->
VECTOR2I
2833 if( wireStart.
y == wireEnd.
y && busStart.
x == busEnd.
x )
2837 if( testBusHit( wireStart ) )
2841 if( wireEnd.
x < busStart.
x )
2848 VECTOR2I p = wireStart + entrySize( -1, 0 );
2850 if( testBusHit( wireStart + entrySize( 0, -1 ) ) )
2859 screen->
Append( busEntry );
2861 wire->SetStartPoint( p );
2863 else if( testBusHit( wireStart + entrySize( 0, 1 ) ) )
2872 screen->
Append( busEntry );
2874 wire->SetStartPoint( p );
2889 VECTOR2I p = wireStart + entrySize( 1, 0 );
2891 if( testBusHit( wireStart + entrySize( 0, -1 ) ) )
2900 screen->
Append( busEntry );
2902 wire->SetStartPoint( p );
2904 else if( testBusHit( wireStart + entrySize( 0, 1 ) ) )
2913 screen->
Append( busEntry );
2915 wire->SetStartPoint( p );
2926 else if( testBusHit( wireEnd ) )
2930 if( wireStart.
x < busStart.
x )
2937 VECTOR2I p = wireEnd + entrySize( -1, 0 );
2939 if( testBusHit( wireEnd + entrySize( 0, -1 ) ) )
2948 screen->
Append( busEntry );
2950 wire->SetEndPoint( p );
2952 else if( testBusHit( wireEnd + entrySize( 0, -1 ) ) )
2961 screen->
Append( busEntry );
2962 moveLabels( wire, wireEnd + entrySize( -1, 0 ) );
2963 wire->SetEndPoint( wireEnd + entrySize( -1, 0 ) );
2978 VECTOR2I p = wireEnd + entrySize( 1, 0 );
2980 if( testBusHit( wireEnd + entrySize( 0, -1 ) ) )
2989 screen->
Append( busEntry );
2991 wire->SetEndPoint( p );
2993 else if( testBusHit( wireEnd + entrySize( 0, 1 ) ) )
3002 screen->
Append( busEntry );
3004 wire->SetEndPoint( p );
3016 else if( wireStart.
x == wireEnd.
x && busStart.
y == busEnd.
y )
3020 if( testBusHit( wireStart ) )
3024 if( wireEnd.
y < busStart.
y )
3032 VECTOR2I p = wireStart + entrySize( 0, -1 );
3034 if( testBusHit( wireStart + entrySize( -1, 0 ) ) )
3044 screen->
Append( busEntry );
3046 wire->SetStartPoint( p );
3048 else if( testBusHit( wireStart + entrySize( 1, 0 ) ) )
3058 screen->
Append( busEntry );
3060 wire->SetStartPoint( p );
3076 VECTOR2I p = wireStart + entrySize( 0, 1 );
3078 if( testBusHit( wireStart + entrySize( -1, 0 ) ) )
3088 screen->
Append( busEntry );
3090 wire->SetStartPoint( p );
3092 else if( testBusHit( wireStart + entrySize( 1, 0 ) ) )
3102 screen->
Append( busEntry );
3104 wire->SetStartPoint( p );
3115 else if( testBusHit( wireEnd ) )
3119 if( wireStart.
y < busStart.
y )
3127 VECTOR2I p = wireEnd + entrySize( 0, -1 );
3129 if( testBusHit( wireEnd + entrySize( -1, 0 ) ) )
3139 screen->
Append( busEntry );
3141 wire->SetEndPoint( p );
3143 else if( testBusHit( wireEnd + entrySize( 1, 0 ) ) )
3153 screen->
Append( busEntry );
3155 wire->SetEndPoint( p );
3171 VECTOR2I p = wireEnd + entrySize( 0, 1 );
3173 if( testBusHit( wireEnd + entrySize( -1, 0 ) ) )
3183 screen->
Append( busEntry );
3185 wire->SetEndPoint( p );
3187 else if( testBusHit( wireEnd + entrySize( 1, 0 ) ) )
3197 screen->
Append( busEntry );
3199 wire->SetEndPoint( p );
3215 if( testBusHit( wireStart ) )
3217 VECTOR2I wirevector = wireStart - wireEnd;
3219 if( wirevector.
x > 0 )
3221 if( wirevector.
y > 0 )
3223 VECTOR2I p = wireStart + entrySize( -1, -1 );
3226 screen->
Append( busEntry );
3229 wire->SetStartPoint( p );
3233 VECTOR2I p = wireStart + entrySize( -1, 1 );
3236 screen->
Append( busEntry );
3239 wire->SetStartPoint( p );
3244 if( wirevector.
y > 0 )
3246 VECTOR2I p = wireStart + entrySize( 1, -1 );
3249 screen->
Append( busEntry );
3252 wire->SetStartPoint( p );
3256 VECTOR2I p = wireStart + entrySize( 1, 1 );
3259 screen->
Append( busEntry );
3262 wire->SetStartPoint( p );
3268 else if( testBusHit( wireEnd ) )
3270 VECTOR2I wirevector = wireStart - wireEnd;
3272 if( wirevector.
x > 0 )
3274 if( wirevector.
y > 0 )
3276 VECTOR2I p = wireEnd + entrySize( 1, 1 );
3279 screen->
Append( busEntry );
3282 wire->SetEndPoint( p );
3286 VECTOR2I p = wireEnd + entrySize( 1, -1 );
3289 screen->
Append( busEntry );
3292 wire->SetEndPoint( p );
3297 if( wirevector.
y > 0 )
3299 VECTOR2I p = wireEnd + entrySize( -1, 1 );
3302 screen->
Append( busEntry );
3305 wire->SetEndPoint( p );
3309 VECTOR2I p = wireEnd + entrySize( -1, -1 );
3312 screen->
Append( busEntry );
3315 wire->SetEndPoint( p );
3329 wxCHECK( aLabel,
nullptr );
3335 if( seg.Contains( labelPos ) )
3347 wxCHECK( aSymbol && aPin,
false );
3355 const auto& items = pointIt->second;
3357 wxCHECK( items.find( aPin ) != items.end(),
false );
3359 return items.size() > 1;
3373 int unit = aSymbol->
GetUnit();
3376 std::set<int> missingUnits;
3383 bool pinInUnit = !unit ||
pin->GetUnit() == unit;
3397 switch(
pin->GetOrientation() )
3414 aScreen->
Append( netLabel );
3417 else if( aUpdateSet )
3422 wxASSERT(
pin->GetUnit() );
3423 missingUnits.insert(
pin->GetUnit() );
3436 entry.
cmp = aSymbol;
3437 entry.
units.emplace( unit,
false );
3442 cmpIt->second.units[unit] =
false;
3445 if( !missingUnits.empty() )
3448 entry.
cmp = aSymbol;
3451 for(
int i : missingUnits )
3453 if( entry.
units.find( i ) != entry.
units.end() )
3454 entry.
units.emplace( i,
true );
3466 wxString ret = wxT(
"{" );
3468 wxStringTokenizer tokenizer( aEagleName,
"," );
3470 while( tokenizer.HasMoreTokens() )
3472 wxString member = tokenizer.GetNextToken();
3479 if( member.Freq(
'!' ) % 2 > 0 )
3480 member << wxT(
"!" );
3482 ret << member << wxS(
" " );
3497 std::unique_ptr<EPART>& epart =
m_eagleDoc->drawing->schematic->parts[aInstance->part];
3499 if( !epart || epart->deviceset.IsEmpty() )
3502 std::unique_ptr<ELIBRARY>& elibrary =
m_eagleDoc->drawing->schematic->libraries[epart->library];
3507 std::unique_ptr<EDEVICE_SET>& edeviceset = elibrary->devicesets[epart->deviceset];
3512 std::unique_ptr<EGATE>& egate = edeviceset->gates[aInstance->gate];
3517 std::unique_ptr<ESYMBOL>& esymbol = elibrary->symbols[egate->symbol];
3520 return esymbol.get();
3527 const wxString& aEagleFieldName,
3530 wxCHECK( aField && !aEagleFieldName.
IsEmpty(), );
3536 for(
const std::unique_ptr<ETEXT>&
text : esymbol->
texts )
3538 if(
text->text == aEagleFieldName )
3541 VECTOR2I pos(
text->x.ToSchUnits() + aInstance->x.ToSchUnits(),
3542 -
text->y.ToSchUnits() - aInstance->y.ToSchUnits() );
3544 bool mirror =
text->rot ?
text->rot->mirror :
false;
3546 if( aInstance->rot && aInstance->rot->mirror )
3550 pos.
y = -aInstance->y.ToSchUnits() +
text->y.ToSchUnits();
constexpr EDA_IU_SCALE schIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
constexpr coord_type GetY() const
constexpr size_type GetWidth() const
constexpr Vec Centre() const
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
constexpr size_type GetHeight() const
constexpr coord_type GetLeft() const
constexpr const SizeVec & GetSize() const
constexpr coord_type GetBottom() const
void SetFlags(EDA_ITEM_FLAGS aMask)
virtual void SetParent(EDA_ITEM *aParent)
void SetCenter(const VECTOR2I &aCenter)
SHAPE_POLY_SET & GetPolyShape()
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
void SetStart(const VECTOR2I &aStart)
void SetEnd(const VECTOR2I &aEnd)
void SetArcAngleAndEnd(const EDA_ANGLE &aAngle, bool aCheckNegativeAngle=false)
Set the end point from the angle center and start.
void SetFillMode(FILL_T aFill)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
const EDA_ANGLE & GetTextAngle() const
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
virtual const wxString & GetText() const
Return the string associated with the text object.
void SetTextPos(const VECTOR2I &aPoint)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
GR_TEXT_H_ALIGN_T GetHorizJustify() const
virtual void SetVisible(bool aVisible)
void SetBold(bool aBold)
Set the text to be bold - this will also update the font if needed.
GR_TEXT_V_ALIGN_T GetVertJustify() const
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
VECTOR2I GetTextSize() const
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
EE_TYPE Overlapping(const BOX2I &aRect) const
iterator end()
Return a read/write iterator that points to one past the last element in the EE_RTREE.
iterator begin()
Return a read/write iterator that points to the first.
EE_TYPE OfType(KICAD_T aType) const
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
REPORTER * m_reporter
Reporter to log errors/warnings to, may be nullptr.
PROGRESS_REPORTER * m_progressReporter
Progress reporter to track the progress of the operation, may be nullptr.
virtual bool CanReadLibrary(const wxString &aFileName) const
Checks if this IO object can read the specified library file/directory.
virtual void Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
std::optional< LIBRARY_TABLE * > ProjectTable() const
Retrieves the project library table for this adapter type, or nullopt if one doesn't exist.
void SetNickname(const wxString &aNickname)
void SetType(const wxString &aType)
void SetURI(const wxString &aUri)
A logical library item identifier and consists of various portions much like a URI.
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
Define a library symbol object.
void GetFields(std::vector< SCH_FIELD * > &aList, bool aVisibleOnly=false) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
std::vector< SCH_PIN * > GetPins() const override
bool IsGlobalPower() const override
int GetUnitCount() const override
static bool ParseBusVector(const wxString &aBus, wxString *aName, std::vector< wxString > *aMemberList)
Parse a bus vector (e.g.
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetHeightMils(double aHeightInMils)
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
void SetWidthMils(double aWidthInMils)
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
Holds all the data relating to one schematic.
PROJECT & Project() const
Return a reference to the project this schematic is part of.
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Class for a wire to bus entry.
void ImportValues(const SCH_FIELD &aSource)
Copy parameters from a SCH_FIELD source.
bool IsEmpty()
Return true if both the name and value of the field are empty.
void SetPosition(const VECTOR2I &aPosition) override
void SetName(const wxString &aName)
void SetText(const wxString &aText) override
void SetSpinStyle(SPIN_STYLE aSpinStyle) override
std::unique_ptr< EAGLE_DOC > m_eagleDoc
SCH_ITEM * loadWire(const std::unique_ptr< EWIRE > &aWire, SEG &endpoints)
void loadTextAttributes(EDA_TEXT *aText, const std::unique_ptr< ETEXT > &aAttributes) const
void loadModuleInstance(const std::unique_ptr< EMODULEINST > &aModuleInstance)
SCH_TEXT * loadLabel(const std::unique_ptr< ELABEL > &aLabel, const wxString &aNetName)
void ensureLoadedLibrary(const wxString &aLibraryPath)
void loadSchematic(const ESCHEMATIC &aSchematic)
SCH_TEXT * loadPlainText(const std::unique_ptr< ETEXT > &aSchText)
void loadSheet(const std::unique_ptr< ESHEET > &aSheet)
void loadLayerDefs(const std::vector< std::unique_ptr< ELAYER > > &aLayers)
const ESYMBOL * getEagleSymbol(const std::unique_ptr< EINSTANCE > &aInstance)
EAGLE_LIBRARY * loadLibrary(const ELIBRARY *aLibrary, EAGLE_LIBRARY *aEagleLib)
wxXmlDocument loadXmlDocument(const wxString &aFileName)
wxString translateEagleBusName(const wxString &aEagleName) const
Translate an Eagle-style bus name into one that is KiCad-compatible.
void loadFieldAttributes(SCH_FIELD *aField, const SCH_TEXT *aText) const
Move net labels that are detached from any wire to the nearest wire.
std::map< wxString, wxString > m_powerPorts
map from symbol reference to global label equivalent
SCH_SHEET_PATH m_sheetPath
The current sheet path of the schematic being loaded.
wxString m_libName
Library name to save symbols.
SCH_TEXT * loadSymbolText(std::unique_ptr< LIB_SYMBOL > &aSymbol, const std::unique_ptr< ETEXT > &aText, int aGateNumber)
std::pair< VECTOR2I, const SEG * > findNearestLinePoint(const VECTOR2I &aPoint, const std::vector< SEG > &aLines) const
std::map< wxString, long long > m_timestamps
void loadInstance(const std::unique_ptr< EINSTANCE > &aInstance, const std::map< wxString, std::unique_ptr< EPART > > &aParts)
LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aAliasName, const std::map< std::string, UTF8 > *aProperties) override
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
std::unordered_map< wxString, bool > m_userValue
deviceset/@uservalue for device.
int GetModifyHash() const override
Return the modification hash from the library cache.
std::map< wxString, int > m_netCounts
std::map< wxString, EAGLE_LIBRARY > m_eagleLibs
bool loadSymbol(const std::unique_ptr< ESYMBOL > &aEsymbol, std::unique_ptr< LIB_SYMBOL > &aSymbol, const std::unique_ptr< EDEVICE > &aDevice, int aGateNumber, const wxString &aGateName)
SCH_SHEET * getCurrentSheet()
void loadDrawing(const std::unique_ptr< EDRAWING > &aDrawing)
void EnumerateSymbolLib(wxArrayString &aSymbolNameList, const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties) override
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
SCH_SHAPE * loadSymbolPolyLine(std::unique_ptr< LIB_SYMBOL > &aSymbol, const std::unique_ptr< EPOLYGON > &aPolygon, int aGateNumber)
std::vector< VECTOR2I > m_wireIntersections
Wires and labels of a single connection (segment in Eagle nomenclature)
std::map< VECTOR2I, std::set< const EDA_ITEM * > > m_connPoints
The fully parsed Eagle schematic file.
void loadSegments(const std::vector< std::unique_ptr< ESEGMENT > > &aSegments, const wxString &aNetName, const wxString &aNetClass)
bool checkConnections(const SCH_SYMBOL *aSymbol, const SCH_PIN *aPin) const
IO_RELEASER< SCH_IO > m_pi
PI to create KiCad symbol library.
SCH_SHAPE * loadRectangle(const std::unique_ptr< ERECT > &aRect)
void addBusEntries()
This function finds best way to place a bus entry symbol for when an Eagle wire segment ends on an Ea...
bool CanReadSchematicFile(const wxString &aFileName) const override
Checks if this SCH_IO can read the specified schematic file.
void addImplicitConnections(SCH_SYMBOL *aSymbol, SCH_SCREEN *aScreen, bool aUpdateSet)
Create net labels to emulate implicit connections in Eagle.
std::map< int, SCH_LAYER_ID > m_layerMap
SCH_LAYER_ID kiCadLayer(int aEagleLayer)
Return the matching layer or return LAYER_NOTES.
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
SCH_PIN * loadPin(std::unique_ptr< LIB_SYMBOL > &aSymbol, const std::unique_ptr< EPIN > &aPin, int aGateNumber)
SCH_SHAPE * loadCircle(const std::unique_ptr< ECIRCLE > &aCircle)
wxFileName getLibFileName()
Checks if there are other wires or pins at the position of the tested pin.
SCH_SHAPE * loadSymbolRectangle(std::unique_ptr< LIB_SYMBOL > &aSymbol, const std::unique_ptr< ERECT > &aRectangle, int aGateNumber)
SCH_JUNCTION * loadJunction(const std::unique_ptr< EJUNCTION > &aJunction)
wxString m_version
Eagle file version.
void getEagleSymbolFieldAttributes(const std::unique_ptr< EINSTANCE > &aInstance, const wxString &aEagleFieldName, SCH_FIELD *aField)
std::map< wxString, const EPART * > m_partlist
void moveLabels(SCH_LINE *aWire, const VECTOR2I &aNewEndPoint)
Move any labels on the wire to the new end point of the wire.
bool checkHeader(const wxString &aFileName) const
SCHEMATIC * m_schematic
Passed to Load(), the schematic object being loaded.
void countNets(const ESCHEMATIC &aSchematic)
SCH_SHEET * m_rootSheet
The root sheet of the schematic being loaded.
SCH_SHAPE * loadPolyLine(const std::unique_ptr< EPOLYGON > &aPolygon)
SCH_SHAPE * loadSymbolCircle(std::unique_ptr< LIB_SYMBOL > &aSymbol, const std::unique_ptr< ECIRCLE > &aCircle, int aGateNumber)
SCH_SCREEN * getCurrentScreen()
bool CanReadLibrary(const wxString &aFileName) const override
Checks if this IO object can read the specified library file/directory.
std::map< wxString, EAGLE_MISSING_CMP > m_missingCmps
void loadFrame(const std::unique_ptr< EFRAME > &aFrame, std::vector< SCH_ITEM * > &aItems)
std::vector< SEG_DESC > m_segments
Nets as defined in the <nets> sections of an Eagle schematic file.
std::vector< EMODULE * > m_modules
The current module stack being loaded.
std::vector< EMODULEINST * > m_moduleInstances
SCH_ITEM * loadSymbolWire(std::unique_ptr< LIB_SYMBOL > &aSymbol, const std::unique_ptr< EWIRE > &aWire, int aGateNumber)
long long getLibraryTimestamp(const wxString &aLibraryPath) const
static const char * PropBuffering
The property used internally by the plugin to enable cache buffering which prevents the library file ...
virtual bool CanReadSchematicFile(const wxString &aFileName) const
Checks if this SCH_IO can read the specified schematic file.
SCH_IO(const wxString &aName)
Base class for any item which can be embedded within the SCHEMATIC container class,...
SCH_ITEM * Duplicate(bool addToParentGroup, SCH_COMMIT *aCommit=nullptr, bool doClone=false) const
Routine to create a new copy of given item.
virtual void SetUnit(int aUnit)
void SetShape(LABEL_FLAG_SHAPE aShape)
void SetPosition(const VECTOR2I &aPosition) override
Segment description base class to describe items which have 2 end points (track, wire,...
bool IsWire() const
Return true if the line is a wire.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
VECTOR2I GetEndPoint() const
VECTOR2I GetStartPoint() const
bool IsBus() const
Return true if the line is a bus.
void SetEndPoint(const VECTOR2I &aPosition)
void SetNumber(const wxString &aNumber)
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in the full schematic.
const PAGE_INFO & GetPageSettings() const
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void SetPageSettings(const PAGE_INFO &aPageSettings)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
void SetPosition(const VECTOR2I &aPos) override
void SetStroke(const STROKE_PARAMS &aStroke) override
VECTOR2I GetCenter() const
void AddPoint(const VECTOR2I &aPosition)
VECTOR2I GetPosition() const override
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
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.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
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.
void SetFileName(const wxString &aFilename)
void SetName(const wxString &aName)
SCH_SCREEN * GetScreen() const
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
VECTOR2I GetPinPhysicalPosition(const SCH_PIN *Pin) const
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
VECTOR2I GetPosition() const override
void SetPosition(const VECTOR2I &aPosition) override
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
bool Contains(const SEG &aSeg) const
SHAPE_ARC & ConstructFromStartEndAngle(const VECTOR2I &aStart, const VECTOR2I &aEnd, const EDA_ANGLE &aAngle, double aWidth=0)
Construct this arc from the given start, end and angle.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
Simple container to manage line stroke parameters.
An interface to the global shared library manager that is schematic-specific and linked to one projec...
std::optional< LIB_STATUS > LoadOne(LIB_DATA *aLib) override
Loads or reloads the given library, if it exists.
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
static REPORTER & GetInstance()
static void SetReporter(REPORTER *aReporter)
Set the reporter to use for reporting font substitution warnings.
#define DEFAULT_SCH_ENTRY_SIZE
The default text size in mils. (can be changed in preference menu)
wxString escapeName(const wxString &aNetName)
Translates Eagle special characters to their counterparts in KiCad.
wxString interpretText(const wxString &aText)
Interprets special characters in Eagle text and converts them to KiCAD notation.
size_t GetNodeCount(const wxXmlNode *aNode)
Fetch the number of XML nodes within aNode.
VECTOR2I ConvertArcCenter(const VECTOR2I &aStart, const VECTOR2I &aEnd, double aAngle)
Convert an Eagle curve end to a KiCad center for S_ARC.
wxString convertDescription(wxString aDescr)
Converts Eagle's HTML description into KiCad description format.
OPTIONAL_XML_ATTRIBUTE< double > opt_double
static constexpr EDA_ANGLE ANGLE_VERTICAL
#define IGNORE_PARENT_GROUP
#define IS_NEW
New item, just created.
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
@ FILLED_SHAPE
Fill with object color.
@ ERCE_BUS_ENTRY_NEEDED
Importer failed to auto-place a bus entry.
static const std::string KiCadSchematicFileExtension
static const std::string KiCadSymbolLibFileExtension
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
SCH_LAYER_ID
Eeschema drawing layers.
@ PT_INPUT
usual pin input: must be connected
@ PT_NC
not connected (must be left open)
@ PT_TRISTATE
tri state bus pin
@ PT_BIDI
input or output (like port for a microprocessor)
@ PT_OPENCOLLECTOR
pin type open collector
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin.
@ PIN_UP
The pin extends upwards from the connection point: Probably on the bottom side of the symbol.
@ PIN_RIGHT
The pin extends rightwards from the connection point.
@ PIN_LEFT
The pin extends leftwards from the connection point: Probably on the right side of the symbol.
@ PIN_DOWN
The pin extends downwards from the connection: Probably on the top side of the symbol.
static wxString extractNetName(const wxString &aPinName)
static const std::map< wxString, ELECTRICAL_PINTYPE > pinDirectionsMap
Map of EAGLE pin type values to KiCad pin type values.
static SYMBOL_ORIENTATION_T kiCadComponentRotation(float eagleDegrees)
static void eagleToKicadAlignment(EDA_TEXT *aText, int aEagleAlignment, int aRelDegress, bool aMirror, bool aSpin, int aAbsDegress)
static BOX2I getSheetBbox(SCH_SHEET *aSheet)
Extract the net name part from a pin name (e.g. return 'GND' for pin named 'GND@2')
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
SHEET_SIDE
Define the edge of the sheet that the sheet pin is positioned.
std::optional< VECTOR2I > OPT_VECTOR2I
wxString UnescapeString(const wxString &aSource)
bool ReplaceIllegalFileNameChars(std::string &aName, int aReplaceChar)
Checks aName for illegal file name characters.
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
wxString UnescapeHTML(const wxString &aString)
Return a new wxString unescaped from HTML format.
std::map< wxString, std::unique_ptr< LIB_SYMBOL > > KiCadSymbols
std::unordered_map< wxString, wxString > package
std::unordered_map< wxString, int > GateToUnitMap
Map Eagle gate unit number (which are strings) to KiCad library symbol unit number.
std::map< wxString, std::unique_ptr< EDEVICE_SET > > devicesets
wxString GetName() const
Fetch the fully unique library name.
std::map< wxString, std::unique_ptr< ESYMBOL > > symbols
std::map< wxString, std::unique_ptr< EMODULE > > modules
std::vector< std::unique_ptr< ESHEET > > sheets
std::map< wxString, std::unique_ptr< EPART > > parts
std::map< wxString, std::unique_ptr< ELIBRARY > > libraries
std::vector< std::unique_ptr< ETEXT > > texts
Map references to missing symbol units data.
std::map< int, bool > units
Segments representing wires for intersection checking.
std::vector< SCH_TEXT * > labels
const SEG * LabelAttached(const SCH_TEXT *aLabel) const
< Test if a particular label is attached to any of the stored segments
A simple container for schematic symbol instance information.
SYMBOL_ORIENTATION_T
enum used in RotationMiroir()
@ USER
The field ID hasn't been set yet; field is invalid.
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
bool TestSegmentHit(const VECTOR2I &aRefPoint, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aDist)
Test if aRefPoint is with aDistance on the line defined by aStart and aEnd.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
VECTOR2< int32_t > VECTOR2I
Definition of file extensions used in Kicad.