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>
91 bbox.
Merge( item->GetBoundingBox() );
100 return aPinName.BeforeFirst(
'@' );
113 wxCHECK( currentSheet,
nullptr );
158 for(
const std::unique_ptr<ELAYER>& elayer : aLayers )
177 switch ( elayer->number)
207 int roti = int( eagleDegrees );
217 wxASSERT_MSG(
false, wxString::Format( wxT(
"Unhandled orientation (%d degrees)" ),
226 bool aMirror,
bool aSpin,
int aAbsDegress )
228 int align = aEagleAlignment;
230 if( aRelDegress == 90 )
234 else if( aRelDegress == 180 )
238 else if( aRelDegress == 270 )
244 if( aMirror ==
true )
246 if( aAbsDegress == 90 || aAbsDegress == 270 )
257 else if( aAbsDegress == 0 || aAbsDegress == 180 )
351 const std::map<std::string, UTF8>* aProperties )
353 wxASSERT( !aFileName || aSchematic !=
nullptr );
373 wxXmlNode* currentNode = xmlDocument.GetRoot();
379 unique_ptr<SCH_SHEET> deleter( aAppendToMe ?
nullptr :
m_rootSheet );
386 wxCHECK_MSG( aSchematic->
IsValid(),
nullptr,
387 wxT(
"Can't append to a schematic with no root!" ) );
398 if( sheetPath.Last() == aAppendToMe )
409 m_rootSheet->SetFileName( newFilename.GetFullPath() );
428 wxCHECK_MSG(
table,
nullptr,
"Could not load symbol lib table." );
430 m_pi.reset( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
438 wxString libTableUri = wxT(
"${KIPRJMOD}/" ) +
getLibFileName().GetFullName();
443 row.
SetURI( libTableUri );
451 m_eagleDoc = std::make_unique<EAGLE_DOC>( currentNode,
this );
462 std::vector<SCH_SHEET*> topLevelSheets;
466 if( sheet && !sheet->IsVirtualRootSheet() )
467 topLevelSheets.push_back( sheet );
470 if( !topLevelSheets.empty() )
486 const wxString& aLibraryPath,
487 const std::map<std::string, UTF8>* aProperties )
498 for(
const auto& [symName, libSymbol] : it->second.KiCadSymbols )
499 aSymbolNameList.push_back( symName );
505 const wxString& aLibraryPath,
506 const std::map<std::string, UTF8>* aProperties )
517 for(
const auto& [symName, libSymbol] : it->second.KiCadSymbols )
518 aSymbolList.push_back( libSymbol.get() );
524 const std::map<std::string, UTF8>* aProperties )
535 auto it2 = it->second.KiCadSymbols.find( aAliasName );
537 if( it2 != it->second.KiCadSymbols.end() )
538 return it2->second.get();
547 wxFileName fn( aLibraryPath );
549 if( fn.IsFileReadable() && fn.GetModificationTime().IsValid() )
550 return fn.GetModificationTime().GetValue().GetValue();
581 std::unique_ptr<EAGLE_DOC> doc = std::make_unique<EAGLE_DOC>( xmlDocument.GetRoot(),
this );
585 m_version = ( doc->version.IsEmpty() ) ? wxString( wxS(
"0.0" ) ) : doc->version;
597 wxXmlDocument xmlDocument;
598 wxFFileInputStream stream(
m_filename.GetFullPath() );
603 wxString::Format(
_(
"Unable to read file '%s'." ),
m_filename.GetFullPath() ) );
607 wxTextInputStream
text( stream );
608 wxString line =
text.ReadLine();
610 if( !line.StartsWith( wxT(
"<?xml" ) ) && !line.StartsWith( wxT(
"<!--" ) )
611 && !line.StartsWith( wxT(
"<eagle " ) ) )
613 THROW_IO_ERROR( wxString::Format(
_(
"'%s' is an Eagle binary-format file; "
614 "only Eagle XML-format files can be imported." ),
618#if wxCHECK_VERSION( 3, 3, 0 )
621 if( !xmlDocument.Load( stream, wxXMLDOC_NONE, &err ) )
623 if( err.message == wxS(
"no element found" ) )
627 wxMemoryOutputStream memOutput;
630 header <<
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
631 header <<
"<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n";
633 wxScopedCharBuffer headerBuf = header.utf8_str();
634 memOutput.Write( headerBuf.data(), headerBuf.length() );
636 wxFFileInputStream stream2(
m_filename.GetFullPath() );
637 memOutput.Write( stream2 );
639 wxMemoryInputStream memInput( memOutput );
641 if( !xmlDocument.Load( memInput, wxXMLDOC_NONE, &err ) )
648 THROW_IO_ERROR( wxString::Format(
_(
"Unable to read file '%s'.\n'%s' at line %d, column %d, offset %d" ),
649 m_filename.GetFullPath(), err.message, err.line, err.column,
654 if( !xmlDocument.Load( stream ) )
658 wxMemoryOutputStream memOutput;
661 header <<
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
662 header <<
"<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n";
664 wxScopedCharBuffer headerBuf = header.utf8_str();
665 memOutput.Write( headerBuf.data(), headerBuf.length() );
667 wxFFileInputStream stream2(
m_filename.GetFullPath() );
668 memOutput.Write( stream2 );
670 wxMemoryInputStream memInput( memOutput );
672 if( !xmlDocument.Load( memInput ) )
685 wxCHECK( aDrawing, );
689 if( aDrawing->library )
697 if( aDrawing->schematic )
704 for(
const std::unique_ptr<ESHEET>& esheet : aSchematic.
sheets )
706 for(
const std::unique_ptr<ENET>& enet : esheet->nets )
708 wxString netName = enet->netname;
717 for(
const auto& [modname, emodule] : aSchematic.
modules )
719 for(
const std::unique_ptr<ESHEET>& esheet : emodule->sheets )
721 for(
const std::unique_ptr<ENET>& enet : esheet->nets )
723 wxString netName = enet->netname;
738 if( aSchematic.
sheets.empty() )
742 for(
const auto& [
name, epart] : aSchematic.
parts )
745 for(
const auto& [modName, emodule] : aSchematic.
modules )
747 for(
const auto& [partName, epart] : emodule->parts )
753 for(
const auto& [libName, elibrary] : aSchematic.
libraries )
756 elib->
name = elibrary->GetName();
770 for(
const std::unique_ptr<ESHEET>& esheet : aSchematic.
sheets )
774 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>(
m_rootSheet );
776 sheet->SetScreen( screen );
779 wxCHECK2( sheet && screen,
continue );
781 wxString pageNo = wxString::Format( wxT(
"%d" ),
m_sheetIndex );
791 wxCHECK2( currentScreen,
continue );
806 struct MISSING_UNIT_PLACEMENT
816 std::map<SCH_SCREEN*, MISSING_UNIT_PLACEMENT> placements;
820 const SCH_SYMBOL* origSymbol = cmp.second.cmp;
822 for(
auto& unitEntry : cmp.second.units )
824 if( unitEntry.second ==
false )
828 int unit = unitEntry.first;
839 targetScreen = fallbackSheet->
GetScreen();
841 targetScreen = schematicRoot->
GetScreen();
844 auto placementIt = placements.find( targetScreen );
846 if( placementIt == placements.end() )
848 MISSING_UNIT_PLACEMENT placement;
849 placement.screen = targetScreen;
853 SCH_SHEET* targetSheet = placement.sheetpath.Last();
858 placement.newCmpPosition =
VECTOR2I( placement.sheetBbox.GetLeft(),
859 placement.sheetBbox.GetBottom() );
860 placement.maxY = placement.sheetBbox.GetY();
861 placementIt = placements.emplace( targetScreen, placement ).first;
864 MISSING_UNIT_PLACEMENT& placement = placementIt->second;
866 symbol->SetUnitSelection( &placement.sheetpath, unit );
867 symbol->SetUnit( unit );
868 symbol->SetOrientation( 0 );
869 symbol->AddHierarchicalReference( placement.sheetpath.Path(), reference, unit );
872 BOX2I cmpBbox = symbol->GetBoundingBox();
873 int posY = placement.newCmpPosition.y + cmpBbox.
GetHeight();
874 symbol->SetPosition(
VECTOR2I( placement.newCmpPosition.x, posY ) );
875 placement.newCmpPosition.x += cmpBbox.
GetWidth();
876 placement.maxY = std::max( placement.maxY, posY );
878 if( placement.newCmpPosition.x >= placement.pageSizeIU.x )
879 placement.newCmpPosition =
VECTOR2I( placement.sheetBbox.GetLeft(),
884 placement.screen->Append( symbol.release() );
897 wxCHECK( sheet && screen, );
901 std::string filename;
908 if( aSheet->description )
909 sheet->
SetName( aSheet->description.value().text );
914 replace( filename.begin(), filename.end(),
' ',
'_' );
916 fn.SetName( filename );
922 for(
const auto& [
name, moduleinst] : aSheet->moduleinsts )
929 for(
const std::unique_ptr<EPOLYGON>& epoly : aSheet->plain->polygons )
932 for(
const std::unique_ptr<EWIRE>& ewire : aSheet->plain->wires )
938 for(
const std::unique_ptr<ETEXT>& etext : aSheet->plain->texts )
941 for(
const std::unique_ptr<ECIRCLE>& ecircle : aSheet->plain->circles )
944 for(
const std::unique_ptr<ERECT>& erectangle : aSheet->plain->rectangles )
947 for(
const std::unique_ptr<EFRAME>& eframe : aSheet->plain->frames )
949 std::vector<SCH_ITEM*> frameItems;
960 for(
const std::unique_ptr<EINSTANCE>& einstance : aSheet->instances )
968 for(
const std::unique_ptr<EBUS>& ebus : aSheet->busses )
977 for(
const std::unique_ptr<ENET>& enet : aSheet->nets )
980 wxString netName = enet->netname;
981 wxString netClass = wxString::Format( wxS(
"%i" ), enet->netcode );
1000 if( pageSizeIU.
x < targetSheetSize.
x )
1003 if( pageSizeIU.
y < targetSheetSize.
y )
1010 VECTOR2I sheetcentre( pageSizeIU.
x / 2, pageSizeIU.
y / 2 );
1014 VECTOR2I translation = sheetcentre - itemsCentre;
1015 translation.
x = translation.
x - translation.
x %
schIUScale.MilsToIU( 100 );
1016 translation.
y = translation.
y - translation.
y %
schIUScale.MilsToIU( 100 );
1028 std::vector<SCH_ITEM*> allItems;
1030 std::copy( screen->
Items().
begin(), screen->
Items().
end(), std::back_inserter( allItems ) );
1034 item->SetPosition( item->GetPosition() + translation );
1052 wxCHECK( currentSheet &¤tScreen, );
1058 auto it =
m_eagleDoc->drawing->schematic->modules.find( aModuleInstance->moduleinst );
1061 if( it ==
m_eagleDoc->drawing->schematic->modules.end() )
1063 THROW_IO_ERROR( wxString::Format(
_(
"No module instance '%s' found in schematic "
1065 aModuleInstance->name,
m_filename.GetFullPath() ) );
1069 fn.SetName( aModuleInstance->moduleinst );
1073 VECTOR2I size( it->second->dx.ToSchUnits(), it->second->dy.ToSchUnits() );
1075 int halfX =
KiROUND( size.
x / 2.0 );
1076 int halfY =
KiROUND( size.
y / 2.0 );
1077 int portExtWireLength =
schIUScale.mmToIU( 5.08 );
1078 VECTOR2I pos( aModuleInstance->x.ToSchUnits() - halfX,
1079 -aModuleInstance->y.ToSchUnits() - halfY );
1081 std::unique_ptr<SCH_SHEET> newSheet = std::make_unique<SCH_SHEET>( currentSheet, pos, size );
1089 if( schFile->GetFileName() == fn.GetFullPath() )
1091 newScreen = schFile;
1096 bool isNewSchFile = ( newScreen == nullptr );
1104 wxCHECK( newSheet && newScreen, );
1106 newSheet->SetScreen( newScreen );
1107 newSheet->SetFileName( fn.GetFullName() );
1108 newSheet->SetName( aModuleInstance->name );
1110 for(
const auto& [portName, port] : it->second->ports )
1113 int pinOffset = port->coord.ToSchUnits();
1116 if( port->side ==
"left" )
1120 pinPos.
y = pos.
y + halfY - pinOffset;
1121 portExtWireEndpoint = pinPos;
1122 portExtWireEndpoint.
x -= portExtWireLength;
1124 else if( port->side ==
"right" )
1127 pinPos.
x = pos.
x + size.
x;
1128 pinPos.
y = pos.
y + halfY - pinOffset;
1129 portExtWireEndpoint = pinPos;
1130 portExtWireEndpoint.
x += portExtWireLength;
1132 else if( port->side ==
"top" )
1135 pinPos.
x = pos.
x + halfX + pinOffset;
1137 portExtWireEndpoint = pinPos;
1138 portExtWireEndpoint.
y -= portExtWireLength;
1140 else if( port->side ==
"bottom" )
1143 pinPos.
x = pos.
x + halfX + pinOffset;
1144 pinPos.
y = pos.
y + size.
y;
1145 portExtWireEndpoint = pinPos;
1146 portExtWireEndpoint.
y += portExtWireLength;
1151 currentScreen->
Append( portExtWire );
1155 if( port->direction )
1157 if( *port->direction ==
"in" )
1159 else if( *port->direction ==
"out" )
1161 else if( *port->direction ==
"io" )
1163 else if( *port->direction ==
"hiz" )
1178 newSheet->AddPin( sheetPin );
1181 wxString pageNo = wxString::Format( wxT(
"%d" ),
m_sheetIndex );
1183 newSheet->SetParent( currentSheet );
1186 currentScreen->
Append( newSheet.release() );
1188 m_modules.push_back( it->second.get() );
1194 for(
const std::unique_ptr<ESHEET>& esheet : it->second->sheets )
1204 wxCHECK2( emoduleInst,
continue );
1206 refPrefix += emoduleInst->name + wxS(
":" );
1217 wxCHECK2( symbol && !symbol->
GetInstances().empty(),
continue );
1220 wxString newReference = refPrefix + inst.
m_Reference.AfterLast(
':' );
1234 std::vector<SCH_ITEM*>& aItems )
1236 int xMin = aFrame->x1.ToSchUnits();
1237 int xMax = aFrame->x2.ToSchUnits();
1238 int yMin = -aFrame->y1.ToSchUnits();
1239 int yMax = -aFrame->y2.ToSchUnits();
1242 std::swap( xMin, xMax );
1245 std::swap( yMin, yMax );
1253 aItems.push_back( lines );
1255 if( !( aFrame->border_left ==
false ) )
1262 aItems.push_back( lines );
1265 int height = yMax - yMin;
1268 int legendPosX = xMin +
schIUScale.MilsToIU( 75 );
1269 double rowSpacing = height / double( aFrame->rows );
1270 double legendPosY = yMin + ( rowSpacing / 2 );
1272 for( i = 1; i < aFrame->rows; i++ )
1274 int newY =
KiROUND( yMin + ( rowSpacing * (
double) i ) );
1278 aItems.push_back( lines );
1281 char legendChar =
'A';
1283 for( i = 0; i < aFrame->rows; i++ )
1289 legendText->
SetText( wxString( legendChar ) );
1292 aItems.push_back( legendText );
1294 legendPosY += rowSpacing;
1298 if( !( aFrame->border_right ==
false ) )
1305 aItems.push_back( lines );
1308 int height = yMax - yMin;
1311 int legendPosX = xMax -
schIUScale.MilsToIU( 75 );
1312 double rowSpacing = height / double( aFrame->rows );
1313 double legendPosY = yMin + ( rowSpacing / 2 );
1315 for( i = 1; i < aFrame->rows; i++ )
1317 int newY =
KiROUND( yMin + ( rowSpacing * (
double) i ) );
1321 aItems.push_back( lines );
1324 char legendChar =
'A';
1326 for( i = 0; i < aFrame->rows; i++ )
1332 legendText->
SetText( wxString( legendChar ) );
1335 aItems.push_back( legendText );
1337 legendPosY += rowSpacing;
1341 if( !( aFrame->border_top ==
false ) )
1348 aItems.push_back( lines );
1351 int width = xMax - xMin;
1354 int legendPosY = yMin +
schIUScale.MilsToIU( 75 );
1355 double columnSpacing = width / double( aFrame->columns );
1356 double legendPosX = xMin + ( columnSpacing / 2 );
1358 for( i = 1; i < aFrame->columns; i++ )
1360 int newX =
KiROUND( xMin + ( columnSpacing * (
double) i ) );
1364 aItems.push_back( lines );
1367 char legendChar =
'1';
1369 for( i = 0; i < aFrame->columns; i++ )
1375 legendText->
SetText( wxString( legendChar ) );
1378 aItems.push_back( legendText );
1380 legendPosX += columnSpacing;
1384 if( !( aFrame->border_bottom ==
false ) )
1391 aItems.push_back( lines );
1394 int width = xMax - xMin;
1397 int legendPosY = yMax -
schIUScale.MilsToIU( 75 );
1398 double columnSpacing = width / double( aFrame->columns );
1399 double legendPosX = xMin + ( columnSpacing / 2 );
1401 for( i = 1; i < aFrame->columns; i++ )
1403 int newX =
KiROUND( xMin + ( columnSpacing * (
double) i ) );
1407 aItems.push_back( lines );
1410 char legendChar =
'1';
1412 for( i = 0; i < aFrame->columns; i++ )
1418 legendText->
SetText( wxString( legendChar ) );
1421 aItems.push_back( legendText );
1423 legendPosX += columnSpacing;
1430 const wxString& netName,
1431 const wxString& aNetClass )
1438 size_t segmentCount = aSegments.size();
1440 for(
const std::unique_ptr<ESEGMENT>& esegment : aSegments )
1442 bool labelled =
false;
1443 bool firstWireFound =
false;
1449 for(
const std::unique_ptr<EWIRE>& ewire : esegment->wires )
1458 if( !firstWireFound )
1460 firstWire = thisWire;
1461 firstWireFound =
true;
1467 if( !desc.labels.empty() && desc.labels.front()->GetText() == netName )
1470 for(
const SEG& seg : desc.segs )
1479 segDesc.
segs.push_back( thisWire );
1483 for(
const std::unique_ptr<EJUNCTION>& ejunction : esegment->junctions )
1486 for(
const std::unique_ptr<ELABEL>& elabel : esegment->labels )
1491 wxASSERT( segDesc.
labels.empty()
1494 segDesc.
labels.push_back( label );
1498 for(
const std::unique_ptr<EPINREF>& epinref : esegment->pinRefs )
1500 wxString part = epinref->part;
1501 wxString
pin = epinref->pin;
1503 auto powerPort =
m_powerPorts.find( wxT(
"#" ) + part );
1515 if( !labelled && firstWireFound )
1517 std::unique_ptr<SCH_LABEL_BASE> label;
1522 else if( segmentCount > 1 )
1527 label->SetPosition( firstWire.
A );
1532 if( firstWire.
B.
x > firstWire.
A.
x )
1537 screen->
Append( label.release() );
1546 std::unique_ptr<SCH_SHAPE> poly = std::make_unique<SCH_SHAPE>(
SHAPE_T::POLY );
1550 for(
const std::unique_ptr<EVERTEX>& evertex : aPolygon->vertices )
1552 pt =
VECTOR2I( evertex->x.ToSchUnits(), -evertex->y.ToSchUnits() );
1558 poly->GetPolyShape().Append( arc, -1, -1,
ARC_ACCURACY );
1562 poly->AddPoint( pt );
1566 prev_curve = evertex->curve;
1569 poly->SetLayer(
kiCadLayer( aPolygon->layer ) );
1573 return poly.release();
1581 start.
x = aWire->x1.ToSchUnits();
1582 start.
y = -aWire->y1.ToSchUnits();
1583 end.x = aWire->x2.ToSchUnits();
1584 end.y = -aWire->y2.ToSchUnits();
1587 endpoints =
SEG( start,
end );
1591 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>(
SHAPE_T::ARC );
1594 arc->SetCenter(
center );
1595 arc->SetStart( start );
1602 return arc.release();
1606 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>();
1608 line->SetStartPoint( start );
1609 line->SetEndPoint(
end );
1610 line->SetLayer(
kiCadLayer( aWire->layer ) );
1613 return line.release();
1621 VECTOR2I center( aCircle->x.ToSchUnits(), -aCircle->y.ToSchUnits() );
1634 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>(
SHAPE_T::RECTANGLE );
1636 rectangle->SetLayer(
kiCadLayer( aRectangle->layer ) );
1637 rectangle->SetPosition(
VECTOR2I( aRectangle->x1.ToSchUnits(), -aRectangle->y1.ToSchUnits() ) );
1638 rectangle->SetEnd(
VECTOR2I( aRectangle->x2.ToSchUnits(), -aRectangle->y2.ToSchUnits() ) );
1640 if( aRectangle->rot )
1642 VECTOR2I pos( rectangle->GetPosition() );
1649 rectangle->SetPosition( pos );
1650 rectangle->SetEnd(
end );
1656 return rectangle.release();
1662 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
1664 VECTOR2I pos( aJunction->x.ToSchUnits(), -aJunction->y.ToSchUnits() );
1666 junction->SetPosition( pos );
1668 return junction.release();
1673 const wxString& aNetName )
1675 VECTOR2I elabelpos( aLabel->x.ToSchUnits(), -aLabel->y.ToSchUnits() );
1680 std::unique_ptr<SCH_LABEL_BASE> label;
1682 VECTOR2I textSize =
KiROUND( aLabel->size.ToSchUnits() * 0.7, aLabel->size.ToSchUnits() * 0.7 );
1688 label = std::make_unique<SCH_HIERLABEL>();
1691 const auto it =
m_modules.back()->ports.find( aNetName );
1695 if( it->second->direction )
1697 wxString direction = *it->second->direction;
1699 if( direction ==
"in" )
1701 else if( direction ==
"out" )
1703 else if( direction ==
"io" )
1705 else if( direction ==
"hiz" )
1713 label->SetLabelShape( type );
1718 label = std::make_unique<SCH_LABEL>();
1724 label = std::make_unique<SCH_GLOBALLABEL>();
1729 label = std::make_unique<SCH_LABEL>();
1733 label->SetPosition( elabelpos );
1734 label->SetTextSize( textSize );
1739 for(
int i = 0; i <
KiROUND( aLabel->rot->degrees / 90.0 ) %4; ++i )
1740 label->Rotate90(
false );
1742 if( aLabel->rot->mirror )
1743 label->MirrorSpinStyle(
false );
1746 return label.release();
1750std::pair<VECTOR2I, const SEG*>
1752 const std::vector<SEG>& aLines )
const
1755 const SEG* nearestLine =
nullptr;
1757 double d, mindistance = std::numeric_limits<double>::max();
1760 for(
const SEG& line : aLines )
1765 if( d < mindistance )
1768 nearestPoint = testpoint;
1769 nearestLine = &line;
1772 testpoint = line.Center();
1775 if( d < mindistance )
1778 nearestPoint = testpoint;
1779 nearestLine = &line;
1785 if( d < mindistance )
1788 nearestPoint = testpoint;
1789 nearestLine = &line;
1793 return std::make_pair( nearestPoint, nearestLine );
1798 const std::map<wxString, std::unique_ptr<EPART>>& aParts )
1800 wxCHECK( aInstance, );
1806 const auto partIt = aParts.find( aInstance->part );
1808 if( partIt == aParts.end() )
1810 Report( wxString::Format(
_(
"Error parsing Eagle file. Could not find '%s' "
1811 "instance but it is referenced in the schematic." ),
1818 const std::unique_ptr<EPART>& epart = partIt->second;
1820 wxString libName = epart->library;
1823 if( epart->libraryUrn )
1824 libName += wxS(
"_" ) + epart->libraryUrn->assetId;
1826 wxString gatename = epart->deviceset + wxS(
"_" ) + epart->device + wxS(
"_" ) +
1828 wxString symbolname = wxString( epart->deviceset + epart->device );
1829 symbolname.Replace( wxT(
"*" ), wxEmptyString );
1837 wxString altSymbolName = libName + wxT(
"_" ) + symbolname;
1840 wxString libIdSymbolName = altSymbolName;
1846 Report( wxString::Format( wxS(
"Eagle library '%s' not found while looking up symbol for "
1847 "deviceset '%s', device '%s', and gate '%s." ),
1848 libName, epart->deviceset, epart->device, aInstance->gate ) );
1852 const auto gateIt = libIt->second.GateToUnitMap.find( gatename );
1854 if( gateIt == libIt->second.GateToUnitMap.end() )
1856 Report( wxString::Format( wxS(
"Symbol not found for deviceset '%s', device '%s', and "
1857 "gate '%s in library '%s'." ),
1858 epart->deviceset, epart->device, aInstance->gate, libName ) );
1862 int unit = gateIt->second;
1867 auto p = elib->
package.find( kisymbolname );
1869 if( p != elib->
package.end() )
1870 package = p->second;
1873 std::map<std::string, UTF8> properties;
1880 part =
m_pi->LoadSymbol(
getLibFileName().GetFullPath(), kisymbolname, &properties );
1881 libIdSymbolName = kisymbolname;
1886 Report( wxString::Format(
_(
"Could not find '%s' in the imported library." ),
1893 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
1894 symbol->SetLibId( libId );
1895 symbol->SetUnit( unit );
1896 symbol->SetPosition(
VECTOR2I( aInstance->x.ToSchUnits(), -aInstance->y.ToSchUnits() ) );
1899 if( !package.IsEmpty() )
1901 wxString footprint =
m_schematic->Project().GetProjectName() + wxT(
":" ) + package;
1905 if( aInstance->rot )
1909 if( aInstance->rot->mirror )
1910 symbol->MirrorHorizontally( aInstance->x.ToSchUnits() );
1913 std::vector<SCH_FIELD*> partFields;
1916 for(
const SCH_FIELD* partField : partFields )
1920 if( partField->IsMandatory() )
1921 symbolField = symbol->GetField( partField->GetId() );
1923 symbolField = symbol->GetField( partField->GetName() );
1925 wxCHECK2( symbolField,
continue );
1928 symbolField->
SetTextPos( symbol->GetPosition() + partField->GetTextPos() );
1933 wxString reference = package.IsEmpty() ?
'#' + aInstance->part : aInstance->part;
1936 if( reference.find_last_not_of( wxT(
"0123456789" ) ) == ( reference.Length()-1 ) )
1937 reference.Append( wxT(
"0" ) );
1942 if( reference.find_first_not_of( wxT(
"0123456789" ) ) != 0 )
1943 reference.Prepend( wxT(
"UNK" ) );
1947 if( aInstance->part.find_first_not_of( wxT(
"#" ) ) != 0 )
1948 reference.Prepend( wxT(
"UNK" ) );
1951 referenceField->
SetText( reference );
1954 bool userValue =
m_userValue.at( libIdSymbolName );
1962 if( epart->value && !epart->value.CGet().IsEmpty() )
1964 valueField->
SetText( *epart->value );
1968 valueField->
SetText( kisymbolname );
1974 for(
const auto& [ attrName, attr ] : epart->attributes )
1980 if( !symbol->GetFields().empty() )
1981 newField.
SetTextPos( symbol->GetFields().back().GetPosition() );
1984 newField.
SetText( *attr->value );
1988 symbol->AddField( newField );
1991 for(
const auto& [variantName, variant] : epart->variants )
1994 field->
SetName( wxT(
"VARIANT_" ) + variant->name );
1996 if( variant->value )
1997 field->
SetText( *variant->value );
2002 bool valueAttributeFound =
false;
2003 bool nameAttributeFound =
false;
2006 for(
auto& [
name, eattr] : aInstance->attributes )
2010 if( eattr->name.Lower() == wxT(
"name" ) )
2013 nameAttributeFound =
true;
2015 else if( eattr->name.Lower() == wxT(
"value" ) )
2018 valueAttributeFound =
true;
2022 field = symbol->GetField( eattr->name );
2032 int absdegrees = eattr->rot ? eattr->rot->degrees : 0;
2033 bool mirror = eattr->rot ? eattr->rot->mirror :
false;
2035 if( aInstance->rot && aInstance->rot->mirror )
2038 bool spin = eattr->rot ? eattr->rot->spin :
false;
2043 int rotation = aInstance->rot ? aInstance->rot->degrees : 0;
2044 int reldegrees = ( absdegrees - rotation + 360.0 );
2052 if( aInstance->smashed && aInstance->smashed.Get() )
2054 symbol->GetField(
FIELD_T::VALUE )->SetVisible( valueAttributeFound );
2066 wxCHECK2( emoduleInst,
continue );
2068 refPrefix += emoduleInst->name + wxS(
":" );
2071 symbol->AddHierarchicalReference(
m_sheetPath.Path(), refPrefix + reference, unit );
2077 wxCHECK( libSymbol, );
2079 symbol->SetLibSymbol(
new LIB_SYMBOL( *libSymbol ) );
2081 for(
const SCH_PIN*
pin : symbol->GetLibPins() )
2087 symbol->ClearFlags();
2089 screen->
Append( symbol.release() );
2095 wxCHECK( aLibrary && aEagleLibrary,
nullptr );
2101 wxString prefix = edeviceset->prefix ? edeviceset->prefix.Get() : wxString( wxT(
"" ) );
2102 wxString deviceSetDescr;
2104 if( edeviceset->description )
2108 for(
const std::unique_ptr<EDEVICE>& edevice : edeviceset->devices )
2111 wxString symbolName = edeviceset->name + edevice->name;
2112 symbolName.Replace( wxT(
"*" ), wxEmptyString );
2113 wxASSERT( !symbolName.IsEmpty() );
2116 if( edevice->package )
2117 aEagleLibrary->
package[symbolName] = edevice->package.Get();
2120 std::unique_ptr<LIB_SYMBOL> libSymbol = std::make_unique<LIB_SYMBOL>( symbolName );
2123 int gate_count =
static_cast<int>( edeviceset->gates.size() );
2124 libSymbol->SetUnitCount( gate_count,
true );
2125 libSymbol->LockUnits(
true );
2129 if( prefix.length() == 0 )
2137 reference->
SetText( edevice->package ? prefix :
'#' + prefix );
2140 libSymbol->GetValueField().SetVisible(
true );
2143 bool ispower =
false;
2145 for(
const auto& [gateName, egate] : edeviceset->gates )
2147 const auto it = aLibrary->
symbols.find( egate->symbol );
2149 if( it == aLibrary->
symbols.end() )
2151 Report( wxString::Format( wxS(
"Eagle symbol '%s' not found in library '%s'." ),
2152 egate->symbol, aLibrary->
GetName() ) );
2156 wxString gateMapName = edeviceset->name + wxS(
"_" ) + edevice->name +
2157 wxS(
"_" ) + egate->name;
2159 ispower =
loadSymbol( it->second, libSymbol, edevice, gateindex, egate->name );
2164 libSymbol->SetUnitCount( gate_count,
true );
2166 if( gate_count == 1 && ispower )
2167 libSymbol->SetGlobalPower();
2170 if( edevice->package )
2177 libName =
m_schematic->Project().GetProjectName();
2184 wxString packageString = libName + wxT(
":" ) + aEagleLibrary->
package[symbolName];
2186 libSymbol->GetFootprintField().SetText( packageString );
2189 wxString libName = libSymbol->GetName();
2190 libSymbol->SetName( libName );
2191 libSymbol->SetDescription( deviceSetDescr );
2201 libName = aEagleLibrary->
name + wxT(
"_" ) + libName;
2203 libSymbol->SetName( libName );
2207 std::map<std::string, UTF8> properties;
2221 aEagleLibrary->
KiCadSymbols[ libName ] = std::move( libSymbol );
2225 m_userValue.emplace( std::make_pair( libName, edeviceset->uservalue ==
true ) );
2229 return aEagleLibrary;
2234 std::unique_ptr<LIB_SYMBOL>& aSymbol,
2235 const std::unique_ptr<EDEVICE>& aDevice,
int aGateNumber,
2236 const wxString& aGateName )
2238 wxCHECK( aEsymbol && aSymbol && aDevice,
false );
2240 std::vector<SCH_ITEM*> items;
2242 bool showRefDes =
false;
2243 bool showValue =
false;
2244 bool ispower =
false;
2247 for(
const std::unique_ptr<ECIRCLE>& ecircle : aEsymbol->circles )
2250 for(
const std::unique_ptr<EPIN>& epin : aEsymbol->pins )
2252 std::unique_ptr<SCH_PIN>
pin(
loadPin( aSymbol, epin, aGateNumber ) );
2257 if( epin->direction )
2261 if( epin->direction->Lower() == pinDir.first )
2263 pin->SetType( pinDir.second );
2265 if( pinDir.first == wxT(
"sup" ) )
2274 if( aDevice->connects.size() != 0 )
2276 for(
const std::unique_ptr<ECONNECT>& connect : aDevice->connects )
2278 if( connect->gate == aGateName &&
pin->GetName() == connect->pin )
2280 wxArrayString pads = wxSplit( wxString( connect->pad ),
' ' );
2282 pin->SetUnit( aGateNumber );
2285 if( pads.GetCount() > 1 )
2287 pin->SetNumberTextSize( 0 );
2290 for(
unsigned i = 0; i < pads.GetCount(); i++ )
2294 wxString padname( pads[i] );
2296 aSymbol->AddDrawItem( apin );
2305 pin->SetUnit( aGateNumber );
2306 pin->SetNumber( wxString::Format( wxT(
"%i" ), pincount ) );
2307 aSymbol->AddDrawItem(
pin.release() );
2311 for(
const std::unique_ptr<EPOLYGON>& epolygon : aEsymbol->polygons )
2314 for(
const std::unique_ptr<ERECT>& erectangle : aEsymbol->rectangles )
2317 for(
const std::unique_ptr<ETEXT>& etext : aEsymbol->texts )
2319 std::unique_ptr<SCH_TEXT> libtext(
loadSymbolText( aSymbol, etext, aGateNumber ) );
2321 if( libtext->GetText() == wxT(
"${REFERENCE}" ) )
2327 showRefDes = etext->text == wxT(
">NAME" );
2329 else if( libtext->GetText() == wxT(
"${VALUE}" ) )
2335 showValue = etext->text == wxT(
">VALUE" );
2339 aSymbol->AddDrawItem( libtext.release() );
2343 for(
const std::unique_ptr<EWIRE>& ewire : aEsymbol->wires )
2344 aSymbol->AddDrawItem(
loadSymbolWire( aSymbol, ewire, aGateNumber ) );
2346 for(
const std::unique_ptr<EFRAME>& eframe : aEsymbol->frames )
2348 std::vector<SCH_ITEM*> frameItems;
2354 item->SetParent( aSymbol.get() );
2355 item->SetUnit( aGateNumber );
2356 aSymbol->AddDrawItem( item );
2360 aSymbol->GetReferenceField().SetVisible( showRefDes );
2361 aSymbol->GetValueField().SetVisible( showValue );
2363 return pincount == 1 ? ispower :
false;
2368 const std::unique_ptr<ECIRCLE>& aCircle,
2371 wxCHECK( aSymbol && aCircle,
nullptr );
2375 VECTOR2I center( aCircle->x.ToSchUnits(), -aCircle->y.ToSchUnits() );
2377 circle->SetParent( aSymbol.get() );
2381 circle->SetUnit( aGateNumber );
2388 const std::unique_ptr<ERECT>& aRectangle,
2391 wxCHECK( aSymbol && aRectangle,
nullptr );
2396 rectangle->
SetPosition(
VECTOR2I( aRectangle->x1.ToSchUnits(), -aRectangle->y1.ToSchUnits() ) );
2397 rectangle->
SetEnd(
VECTOR2I( aRectangle->x2.ToSchUnits(), -aRectangle->y2.ToSchUnits() ) );
2399 if( aRectangle->rot )
2412 rectangle->
SetUnit( aGateNumber );
2422 const std::unique_ptr<EWIRE>& aWire,
int aGateNumber )
2424 wxCHECK( aSymbol && aWire,
nullptr );
2428 begin.
x = aWire->x1.ToSchUnits();
2429 begin.
y = -aWire->y1.ToSchUnits();
2430 end.x = aWire->x2.ToSchUnits();
2431 end.y = -aWire->y2.ToSchUnits();
2450 ( aWire->width.ToSchUnits() /
radius );
2451 begin =
center + centerStartVector;
2485 const std::unique_ptr<EPOLYGON>& aPolygon,
2488 wxCHECK( aSymbol && aPolygon,
nullptr );
2496 for(
const std::unique_ptr<EVERTEX>& evertex : aPolygon->vertices )
2498 pt =
VECTOR2I( evertex->x.ToSchUnits(), evertex->y.ToSchUnits() );
2512 prev_curve = evertex->curve;
2524 const std::unique_ptr<EPIN>& aPin,
int aGateNumber )
2526 wxCHECK( aSymbol && aPin,
nullptr );
2528 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>( aSymbol.get() );
2529 pin->SetPosition(
VECTOR2I( aPin->x.ToSchUnits(), -aPin->y.ToSchUnits() ) );
2530 pin->SetName( aPin->name );
2531 pin->SetUnit( aGateNumber );
2533 int roti = aPin->rot ? aPin->rot->degrees : 0;
2541 default: wxFAIL_MSG( wxString::Format( wxT(
"Unhandled orientation (%d degrees)." ), roti ) );
2548 wxString length = aPin->length.Get();
2550 if( length == wxT(
"short" ) )
2552 else if( length == wxT(
"middle" ) )
2554 else if( length == wxT(
"long" ) )
2556 else if( length == wxT(
"point" ) )
2567 wxString visible = aPin->visible.Get();
2569 if( visible == wxT(
"off" ) )
2571 pin->SetNameTextSize( 0 );
2572 pin->SetNumberTextSize( 0 );
2574 else if( visible == wxT(
"pad" ) )
2576 pin->SetNameTextSize( 0 );
2578 else if( visible == wxT(
"pin" ) )
2580 pin->SetNumberTextSize( 0 );
2590 if( aPin->function )
2592 wxString function = aPin->function.Get();
2594 if( function == wxT(
"dot" ) )
2596 else if( function == wxT(
"clk" ) )
2598 else if( function == wxT(
"dotclk" ) )
2602 return pin.release();
2607 const std::unique_ptr<ETEXT>& aText,
int aGateNumber )
2609 wxCHECK( aSymbol && aText,
nullptr );
2611 std::unique_ptr<SCH_TEXT> libtext = std::make_unique<SCH_TEXT>();
2613 libtext->SetParent( aSymbol.get() );
2614 libtext->SetUnit( aGateNumber );
2615 libtext->SetPosition(
VECTOR2I( aText->x.ToSchUnits(), -aText->y.ToSchUnits() ) );
2617 const wxString& eagleText = aText->text;
2618 wxString adjustedText;
2619 wxStringTokenizer tokenizer( eagleText,
"\r\n" );
2622 while( tokenizer.HasMoreTokens() )
2624 wxString tmp =
interpretText( tokenizer.GetNextToken().Trim(
true ).Trim(
false ) );
2626 if( tokenizer.HasMoreTokens() )
2629 adjustedText += tmp;
2632 libtext->SetText( adjustedText.IsEmpty() ? wxString( wxS(
"~" ) ) : adjustedText );
2636 return libtext.release();
2642 wxCHECK( aText,
nullptr );
2644 std::unique_ptr<SCH_TEXT> schtext = std::make_unique<SCH_TEXT>();
2646 const wxString& eagleText = aText->text;
2647 wxString adjustedText;
2648 wxStringTokenizer tokenizer( eagleText,
"\r\n" );
2651 while( tokenizer.HasMoreTokens() )
2653 wxString tmp =
interpretText( tokenizer.GetNextToken().Trim(
true ).Trim(
false ) );
2655 if( tokenizer.HasMoreTokens() )
2658 adjustedText += tmp;
2661 schtext->SetText( adjustedText.IsEmpty() ? wxString( wxS(
"\" \"" ) )
2664 schtext->SetPosition(
VECTOR2I( aText->x.ToSchUnits(), -aText->y.ToSchUnits() ) );
2666 schtext->SetItalic(
false );
2668 return schtext.release();
2673 const std::unique_ptr<ETEXT>& aAttributes )
const
2675 wxCHECK( aText && aAttributes, );
2680 if( aAttributes->ratio && aAttributes->ratio.CGet() > 12 )
2684 int degrees = aAttributes->rot ? aAttributes->rot->degrees : 0;
2685 bool mirror = aAttributes->rot ? aAttributes->rot->mirror :
false;
2686 bool spin = aAttributes->rot ? aAttributes->rot->spin :
false;
2694 wxCHECK( aField && aText, );
2718 auto onIntersection =
2727 for(
SCH_TEXT* label : segDesc.labels )
2730 const SEG* segAttached = segDesc.LabelAttached( label );
2732 if( segAttached && !onIntersection( labelPos ) )
2746 VECTOR2I wireDirection( segAttached->
B - segAttached->
A );
2748 const VECTOR2I origPos( labelPos );
2751 bool checkPositive =
true, checkNegative =
true,
move =
false;
2755 while( ( !
move || onIntersection( labelPos ) ) && ( checkPositive || checkNegative ) )
2760 if( trial % 2 == 1 )
2762 labelPos =
VECTOR2I( origPos + wireDirection * trial / 2 );
2763 move = checkPositive = segAttached->
Contains( labelPos );
2767 labelPos =
VECTOR2I( origPos - wireDirection * trial / 2 );
2768 move = checkNegative = segAttached->
Contains( labelPos );
2804 wxFileInputStream input( aFileName );
2809 wxTextInputStream
text( input );
2811 for(
int i = 0; i < 8; i++ )
2816 if(
text.ReadLine().Contains( wxS(
"<eagle" ) ) )
2834 if( !item->IsType( { SCH_LABEL_LOCATE_ANY_T } ) )
2838 item->SetPosition( aNewEndPoint );
2851 std::vector<SCH_LINE*> buses;
2852 std::vector<SCH_LINE*> wires;
2863 buses.push_back( line );
2864 else if( line->
IsWire() )
2865 wires.push_back( line );
2870 VECTOR2I wireStart = wire->GetStartPoint();
2871 VECTOR2I wireEnd = wire->GetEndPoint();
2875 VECTOR2I busStart = bus->GetStartPoint();
2876 VECTOR2I busEnd = bus->GetEndPoint();
2879 [](
int signX,
int signY ) ->
VECTOR2I
2891 if( wireStart.
y == wireEnd.
y && busStart.
x == busEnd.
x )
2895 if( testBusHit( wireStart ) )
2899 if( wireEnd.
x < busStart.
x )
2906 VECTOR2I p = wireStart + entrySize( -1, 0 );
2908 if( testBusHit( wireStart + entrySize( 0, -1 ) ) )
2917 screen->
Append( busEntry );
2919 wire->SetStartPoint( p );
2921 else if( testBusHit( wireStart + entrySize( 0, 1 ) ) )
2930 screen->
Append( busEntry );
2932 wire->SetStartPoint( p );
2947 VECTOR2I p = wireStart + entrySize( 1, 0 );
2949 if( testBusHit( wireStart + entrySize( 0, -1 ) ) )
2958 screen->
Append( busEntry );
2960 wire->SetStartPoint( p );
2962 else if( testBusHit( wireStart + entrySize( 0, 1 ) ) )
2971 screen->
Append( busEntry );
2973 wire->SetStartPoint( p );
2984 else if( testBusHit( wireEnd ) )
2988 if( wireStart.
x < busStart.
x )
2995 VECTOR2I p = wireEnd + entrySize( -1, 0 );
2997 if( testBusHit( wireEnd + entrySize( 0, -1 ) ) )
3006 screen->
Append( busEntry );
3008 wire->SetEndPoint( p );
3010 else if( testBusHit( wireEnd + entrySize( 0, -1 ) ) )
3019 screen->
Append( busEntry );
3020 moveLabels( wire, wireEnd + entrySize( -1, 0 ) );
3021 wire->SetEndPoint( wireEnd + entrySize( -1, 0 ) );
3036 VECTOR2I p = wireEnd + entrySize( 1, 0 );
3038 if( testBusHit( wireEnd + entrySize( 0, -1 ) ) )
3047 screen->
Append( busEntry );
3049 wire->SetEndPoint( p );
3051 else if( testBusHit( wireEnd + entrySize( 0, 1 ) ) )
3060 screen->
Append( busEntry );
3062 wire->SetEndPoint( p );
3074 else if( wireStart.
x == wireEnd.
x && busStart.
y == busEnd.
y )
3078 if( testBusHit( wireStart ) )
3082 if( wireEnd.
y < busStart.
y )
3090 VECTOR2I p = wireStart + entrySize( 0, -1 );
3092 if( testBusHit( wireStart + entrySize( -1, 0 ) ) )
3102 screen->
Append( busEntry );
3104 wire->SetStartPoint( p );
3106 else if( testBusHit( wireStart + entrySize( 1, 0 ) ) )
3116 screen->
Append( busEntry );
3118 wire->SetStartPoint( p );
3134 VECTOR2I p = wireStart + entrySize( 0, 1 );
3136 if( testBusHit( wireStart + entrySize( -1, 0 ) ) )
3146 screen->
Append( busEntry );
3148 wire->SetStartPoint( p );
3150 else if( testBusHit( wireStart + entrySize( 1, 0 ) ) )
3160 screen->
Append( busEntry );
3162 wire->SetStartPoint( p );
3173 else if( testBusHit( wireEnd ) )
3177 if( wireStart.
y < busStart.
y )
3185 VECTOR2I p = wireEnd + entrySize( 0, -1 );
3187 if( testBusHit( wireEnd + entrySize( -1, 0 ) ) )
3197 screen->
Append( busEntry );
3199 wire->SetEndPoint( p );
3201 else if( testBusHit( wireEnd + entrySize( 1, 0 ) ) )
3211 screen->
Append( busEntry );
3213 wire->SetEndPoint( p );
3229 VECTOR2I p = wireEnd + entrySize( 0, 1 );
3231 if( testBusHit( wireEnd + entrySize( -1, 0 ) ) )
3241 screen->
Append( busEntry );
3243 wire->SetEndPoint( p );
3245 else if( testBusHit( wireEnd + entrySize( 1, 0 ) ) )
3255 screen->
Append( busEntry );
3257 wire->SetEndPoint( p );
3273 if( testBusHit( wireStart ) )
3275 VECTOR2I wirevector = wireStart - wireEnd;
3277 if( wirevector.
x > 0 )
3279 if( wirevector.
y > 0 )
3281 VECTOR2I p = wireStart + entrySize( -1, -1 );
3284 screen->
Append( busEntry );
3287 wire->SetStartPoint( p );
3291 VECTOR2I p = wireStart + entrySize( -1, 1 );
3294 screen->
Append( busEntry );
3297 wire->SetStartPoint( p );
3302 if( wirevector.
y > 0 )
3304 VECTOR2I p = wireStart + entrySize( 1, -1 );
3307 screen->
Append( busEntry );
3310 wire->SetStartPoint( p );
3314 VECTOR2I p = wireStart + entrySize( 1, 1 );
3317 screen->
Append( busEntry );
3320 wire->SetStartPoint( p );
3326 else if( testBusHit( wireEnd ) )
3328 VECTOR2I wirevector = wireStart - wireEnd;
3330 if( wirevector.
x > 0 )
3332 if( wirevector.
y > 0 )
3334 VECTOR2I p = wireEnd + entrySize( 1, 1 );
3337 screen->
Append( busEntry );
3340 wire->SetEndPoint( p );
3344 VECTOR2I p = wireEnd + entrySize( 1, -1 );
3347 screen->
Append( busEntry );
3350 wire->SetEndPoint( p );
3355 if( wirevector.
y > 0 )
3357 VECTOR2I p = wireEnd + entrySize( -1, 1 );
3360 screen->
Append( busEntry );
3363 wire->SetEndPoint( p );
3367 VECTOR2I p = wireEnd + entrySize( -1, -1 );
3370 screen->
Append( busEntry );
3373 wire->SetEndPoint( p );
3387 wxCHECK( aLabel,
nullptr );
3393 if( seg.Contains( labelPos ) )
3405 wxCHECK( aSymbol && aPin,
false );
3413 const auto& items = pointIt->second;
3415 wxCHECK( items.find( aPin ) != items.end(),
false );
3417 return items.size() > 1;
3431 int unit = aSymbol->
GetUnit();
3434 std::set<int> missingUnits;
3441 bool pinInUnit = !unit ||
pin->GetUnit() == unit;
3455 switch(
pin->GetOrientation() )
3472 aScreen->
Append( netLabel );
3475 else if( aUpdateSet )
3480 wxASSERT(
pin->GetUnit() );
3481 missingUnits.insert(
pin->GetUnit() );
3494 entry.
cmp = aSymbol;
3496 entry.
units.emplace( unit,
false );
3501 cmpIt->second.units[unit] =
false;
3504 if( !missingUnits.empty() )
3507 entry.
cmp = aSymbol;
3511 for(
int i : missingUnits )
3513 if( entry.
units.find( i ) != entry.
units.end() )
3514 entry.
units.emplace( i,
true );
3526 wxString ret = wxT(
"{" );
3528 wxStringTokenizer tokenizer( aEagleName,
"," );
3530 while( tokenizer.HasMoreTokens() )
3532 wxString member = tokenizer.GetNextToken();
3539 if( member.Freq(
'!' ) % 2 > 0 )
3540 member << wxT(
"!" );
3542 ret << member << wxS(
" " );
3557 std::unique_ptr<EPART>& epart =
m_eagleDoc->drawing->schematic->parts[aInstance->part];
3559 if( !epart || epart->deviceset.IsEmpty() )
3562 std::unique_ptr<ELIBRARY>& elibrary =
m_eagleDoc->drawing->schematic->libraries[epart->library];
3567 std::unique_ptr<EDEVICE_SET>& edeviceset = elibrary->devicesets[epart->deviceset];
3572 std::unique_ptr<EGATE>& egate = edeviceset->gates[aInstance->gate];
3577 std::unique_ptr<ESYMBOL>& esymbol = elibrary->symbols[egate->symbol];
3580 return esymbol.get();
3587 const wxString& aEagleFieldName,
3590 wxCHECK( aField && !aEagleFieldName.
IsEmpty(), );
3596 for(
const std::unique_ptr<ETEXT>&
text : esymbol->
texts )
3598 if(
text->text == aEagleFieldName )
3601 VECTOR2I pos(
text->x.ToSchUnits() + aInstance->x.ToSchUnits(),
3602 -
text->y.ToSchUnits() - aInstance->y.ToSchUnits() );
3604 bool mirror =
text->rot ?
text->rot->mirror :
false;
3606 if( aInstance->rot && aInstance->rot->mirror )
3610 pos.
y = -aInstance->y.ToSchUnits() +
text->y.ToSchUnits();
constexpr EDA_IU_SCALE schIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
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 const SizeVec & GetSize() 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.
RAII class to set and restore the fontconfig reporter.
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 LOAD_INFO_REPORTER & GetInstance()
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.
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
void SetTopLevelSheets(const std::vector< SCH_SHEET * > &aSheets)
std::vector< SCH_SHEET * > GetTopLevelSheets() const
Get the list of top-level sheets.
Class for a wire to bus entry.
virtual const wxString & GetText() const override
Return the string associated with the text object.
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...
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)
bool LocatePathOfScreen(SCH_SCREEN *aScreen, SCH_SHEET_PATH *aList)
Search the existing hierarchy for an instance of screen loaded from 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()
#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.
const SCH_SYMBOL * cmp
Screen where the parent symbol is located.
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.