56#include <wx/xml/xml.h>
57#include <wx/filename.h>
59#include <wx/wfstream.h>
60#include <wx/txtstrm.h>
96 ECOORD coord( aDistance, unit );
107 T ret = std::max( aMin, aValue );
108 return std::min( aMax, ret );
114static wxString
makeKey(
const wxString& aFirst,
const wxString& aSecond )
116 wxString key = aFirst +
'\x02' + aSecond;
164 wxXmlNode* child = aRules->GetChildren();
170 if( child->GetName() == wxT(
"param" ) )
172 const wxString&
name = child->GetAttribute( wxT(
"name" ) );
173 const wxString& value = child->GetAttribute( wxT(
"value" ) );
175 if(
name == wxT(
"psElongationLong" ) )
177 else if(
name == wxT(
"psElongationOffset" ) )
179 else if(
name == wxT(
"mvStopFrame" ) )
181 else if(
name == wxT(
"mvCreamFrame" ) )
183 else if(
name == wxT(
"mlMinStopFrame" ) )
185 else if(
name == wxT(
"mlMaxStopFrame" ) )
187 else if(
name == wxT(
"mlMinCreamFrame" ) )
189 else if(
name == wxT(
"mlMaxCreamFrame" ) )
191 else if(
name == wxT(
"srRoundness" ) )
193 else if(
name == wxT(
"srMinRoundness" ) )
195 else if(
name == wxT(
"srMaxRoundness" ) )
197 else if(
name == wxT(
"psTop" ) )
198 psTop = wxAtoi( value );
199 else if(
name == wxT(
"psBottom" ) )
201 else if(
name == wxT(
"psFirst" ) )
203 else if(
name == wxT(
"rvPadTop" ) )
205 else if(
name == wxT(
"rlMinPadTop" ) )
207 else if(
name == wxT(
"rlMaxPadTop" ) )
209 else if(
name == wxT(
"rvViaOuter" ) )
211 else if(
name == wxT(
"rlMinViaOuter" ) )
213 else if(
name == wxT(
"rlMaxViaOuter" ) )
215 else if(
name == wxT(
"mdWireWire" ) )
219 child = child->GetNext();
232 m_timestamp( wxDateTime::Now().GetValue().GetValue() )
234 using namespace std::placeholders;
276 wxFileInputStream input( aFileName );
281 wxTextInputStream
text( input );
283 for(
int i = 0; i < 8; i++ )
288 if(
text.ReadLine().Contains( wxS(
"<eagle" ) ) )
298 const unsigned PROGRESS_DELTA = 50;
319 return VECTOR2I( kz - aTextThickness, kz - aTextThickness );
324 const std::map<std::string, UTF8>* aProperties,
PROJECT* aProject )
337 m_board->SetFileName( aFileName );
340 unique_ptr<BOARD> deleter( aAppendToMe ?
nullptr :
m_board );
352 wxFileName fn = aFileName;
355 wxFFileInputStream stream( fn.GetFullPath() );
356 wxXmlDocument xmlDocument;
358 if( !stream.IsOk() || !xmlDocument.Load( stream ) )
361 fn.GetFullPath() ) );
364 doc = xmlDocument.GetRoot();
390 NETCLASS defaults( wxT(
"dummy" ) );
392 auto finishNetclass =
393 [&](
const std::shared_ptr<NETCLASS>& netclass )
397 if( !netclass->HasClearance() )
402 if( netclass->GetTrackWidth() == INT_MAX )
405 if( netclass->GetViaDiameter() == INT_MAX )
408 if( netclass->GetViaDrill() == INT_MAX )
412 std::shared_ptr<NET_SETTINGS>& netSettings = bds.
m_NetSettings;
414 finishNetclass( netSettings->GetDefaultNetclass() );
416 for(
const auto& [
name, netclass] : netSettings->GetNetclasses() )
417 finishNetclass( netclass );
419 m_board->m_LegacyNetclassesLoaded =
true;
420 m_board->m_LegacyDesignSettingsLoaded =
true;
422 fn.SetExt( wxT(
"kicad_dru" ) );
423 wxFile rulesFile( fn.GetFullPath(), wxFile::write );
427 wxASSERT(
m_xpath->Contents().size() == 0 );
431 wxString errmsg = exc.what();
433 errmsg += wxT(
"\n@ " );
443 LSET enabledLayers =
m_board->GetDesignSettings().GetEnabledLayers();
445 for(
const auto& [eagleLayerName, layer] :
m_layer_map )
446 enabledLayers.
set( layer );
448 m_board->GetDesignSettings().SetEnabledLayers( enabledLayers );
459 std::vector<FOOTPRINT*> retval;
462 retval.push_back(
static_cast<FOOTPRINT*
>( footprint->Clone() ) );
498 wxXmlNode* drawing =
MapChildren( aDoc )[
"drawing"];
501 wxXmlNode* board = drawingChildren[
"board"];
504 auto count_children =
505 [
this]( wxXmlNode* aNode )
509 wxXmlNode* child = aNode->GetChildren();
514 child = child->GetNext();
519 wxXmlNode* designrules = boardChildren[
"designrules"];
520 wxXmlNode* layers = drawingChildren[
"layers"];
521 wxXmlNode* plain = boardChildren[
"plain"];
522 wxXmlNode* classes = boardChildren[
"classes"];
523 wxXmlNode* signals = boardChildren[
"signals"];
524 wxXmlNode* libs = boardChildren[
"libraries"];
525 wxXmlNode* elems = boardChildren[
"elements"];
532 count_children( designrules );
533 count_children( layers );
534 count_children( plain );
535 count_children( signals );
536 count_children( elems );
541 libs = libs->GetNext();
545 libs = boardChildren[
"libraries"];
548 m_xpath->push(
"eagle.drawing" );
587 m_xpath->push(
"designrules" );
606 wxXmlNode* layerNode = aLayers->GetChildren();
613 ELAYER elayer( layerNode );
619 cu.push_back( elayer );
621 layerNode = layerNode->GetNext();
625 int ki_layer_count = 0;
627 for(
EITER it = cu.begin(); it != cu.end(); ++it, ++ki_layer_count )
629 if( ki_layer_count == 0 )
633 else if( ki_layer_count ==
int( cu.size()-1 ) )
647 m_board->SetCopperLayerCount( cu.size() );
649 for(
EITER it = cu.begin(); it != cu.end(); ++it )
656 m_board->SetLayerName( layer, it->name );
666#define DIMENSION_PRECISION DIM_PRECISION::X_XX
677 wxXmlNode* gr = aGraphics->GetChildren();
684 wxString grName = gr->GetName();
686 if( grName == wxT(
"wire" ) )
703 width =
m_board->GetDesignSettings().GetLineThickness( layer );
729 else if( grName == wxT(
"text" ) )
770 if( degrees > 90 && degrees <= 270 )
795 offset.
y = -signY * (int) textbox.
GetHeight();
807 offset.
x = signX * (int) textbox.
GetWidth();
813 offset.
x = -signX * (int) textbox.
GetWidth();
872 if( pcbtxt->
IsMirrored() && degrees < -90 && degrees >= -270 )
890 else if( grName == wxT(
"circle" ) )
909 int outlineRadius =
radius + ( width / 2 );
915 VECTOR2I rotatedPoint( outlineRadius, 0 );
923 int innerRadius =
radius - ( width / 2 );
929 VECTOR2I rotatedPoint( innerRadius, 0 );
956 else if( grName == wxT(
"rectangle" ) )
976 const int outlineIdx = -1;
995 else if( grName == wxT(
"hole" ) )
1005 footprint->
SetReference( wxString::Format( wxT(
"UNK_HOLE_%d" ), hole_count ) );
1008 LIB_ID fpid( wxEmptyString, wxString::Format( wxT(
"dummyfp%d" ), hole_count ) );
1015 else if( grName == wxT(
"frame" ) )
1019 else if( grName == wxT(
"polygon" ) )
1025 else if( grName == wxT(
"dimension" ) )
1059 dimension->
SetEnd( pt2 );
1094 int newY = ( pt1.
y + pt2.
y ) / 2;
1100 int newX = ( pt1.
x + pt2.
x ) / 2;
1111 dimension->
SetEnd( pt2 );
1121 if(
abs( pt1.
x - pt2.
x ) < 50000 )
1123 int offset = pt3.
x - pt1.
x;
1130 else if(
abs( pt1.
y - pt2.
y ) < 50000 )
1132 int offset = pt3.
y - pt1.
y;
1165 wxString urn = aLib->GetAttribute(
"urn" );
1167 wxString urnOrdinal;
1169 if( !urn.IsEmpty() )
1170 urnOrdinal = urn.AfterLast(
':' );
1173 wxXmlNode* packages =
MapChildren( aLib )[
"packages"];
1185 wxXmlNode*
package = packages->GetChildren();
1191 m_xpath->push(
"package",
"name" );
1193 wxString pack_ref = package->GetAttribute(
"name" );
1195 if( !urnOrdinal.IsEmpty() )
1196 pack_ref += wxS(
"_" ) + urnOrdinal;
1200 m_xpath->Value( pack_ref.ToUTF8() );
1202 wxString key = aLibName ?
makeKey( *aLibName, pack_ref ) : pack_ref;
1207 auto r =
m_templates.insert( { key, footprint } );
1211 wxString lib = aLibName ? *aLibName :
m_lib_path;
1212 const wxString& pkg = pack_ref;
1214 wxString emsg = wxString::Format(
_(
"<package> '%s' duplicated in <library> '%s'" ),
1222 package = package->GetNext();
1234 m_xpath->push(
"libraries.library",
"name" );
1237 wxXmlNode*
library = aLibs->GetChildren();
1241 const wxString& lib_name =
library->GetAttribute(
"name" );
1243 m_xpath->Value( lib_name.c_str() );
1257 m_xpath->push(
"elements.element",
"name" );
1261 bool refanceNamePresetInPackageLayout;
1262 bool valueNamePresetInPackageLayout;
1265 wxXmlNode* element = aElements->GetChildren();
1271 if( element->GetName() != wxT(
"element" ) )
1274 element = element->GetNext();
1281 EATTR* nameAttr =
nullptr;
1282 EATTR* valueAttr =
nullptr;
1286 wxString packageName = e.
package;
1296 wxString emsg = wxString::Format(
_(
"No '%s' package in library '%s'." ),
1313 const ENET* enet = &ni->second;
1318 refanceNamePresetInPackageLayout =
true;
1319 valueNamePresetInPackageLayout =
true;
1326 refanceNamePresetInPackageLayout =
false;
1330 if( footprint->
GetValue().size() == 0 )
1333 valueNamePresetInPackageLayout =
false;
1336 wxString reference = e.
name;
1342 if( reference.find_first_not_of(
"0123456789" ) != 0 )
1343 reference.Prepend(
"UNK" );
1347 if( reference.find_first_not_of(
"#" ) != 0 )
1348 reference.Prepend(
"UNK" );
1351 if( reference.find_last_not_of(
"0123456789" ) == (reference.Length()-1) )
1352 reference.Append(
"0" );
1360 if( valueNamePresetInPackageLayout )
1363 if( refanceNamePresetInPackageLayout )
1373 m_xpath->push(
"attribute",
"name" );
1383 wxXmlNode* attribute = element->GetChildren();
1387 if( attribute->GetName() != wxT(
"attribute" ) )
1389 attribute = attribute->GetNext();
1393 EATTR a( attribute );
1395 if( a.
name == wxT(
"NAME" ) )
1408 nameAttr->
name = reference;
1410 if( refanceNamePresetInPackageLayout )
1417 if( refanceNamePresetInPackageLayout )
1426 if( refanceNamePresetInPackageLayout )
1429 nameAttr->
name = nameAttr->
name + wxT(
" = " ) + e.
name;
1440 if( refanceNamePresetInPackageLayout )
1450 else if( a.
name == wxT(
"VALUE" ) )
1464 if( valueNamePresetInPackageLayout )
1470 if( valueNamePresetInPackageLayout )
1473 footprint->
SetValue( wxT(
"VALUE" ) );
1477 if( valueNamePresetInPackageLayout )
1491 if( valueNamePresetInPackageLayout )
1503 attribute = attribute->GetNext();
1512 element = element->GetNext();
1529 wxLogMessage( wxString::Format(
_(
"Ignoring a polygon since Eagle layer '%s' (%d) was not mapped" ),
1536 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
1539 zone->SetLayer( layer );
1544 wxXmlNode* vertex = aPolyNode->GetChildren();
1545 std::vector<EVERTEX> vertices;
1553 if( vertex->GetName() == wxT(
"vertex" ) )
1554 vertices.emplace_back( vertex );
1556 vertex = vertex->GetNext();
1566 vertices.push_back( vertices[0] );
1571 for(
size_t i = 0; i < vertices.size() - 1; i++ )
1589 double delta_angle = angle / segCount;
1591 for(
double a = end_angle + angle; fabs( a - end_angle ) > fabs( delta_angle ); a -= delta_angle )
1606 wxLogMessage( wxString::Format(
_(
"Skipping a polygon on layer '%s' (%d): outline count is not 1" ),
1613 zone->AddPolygon( polygon.
COutline( 0 ) );
1618 zone->SetIsRuleArea(
true );
1619 zone->SetDoNotAllowVias(
false );
1620 zone->SetDoNotAllowTracks(
false );
1621 zone->SetDoNotAllowPads(
false );
1622 zone->SetDoNotAllowFootprints(
false );
1623 zone->SetDoNotAllowZoneFills(
true );
1633 zone->SetHatchOrientation(
ANGLE_0 );
1644 zone->SetLocalClearance( 1 );
1661 zone->SetAssignedPriority( rank );
1663 ZONE* zonePtr = zone.release();
1671 const EATTR* aNameAttr,
const EATTR* aValueAttr )
1692 const EATTR* aAttr )
1698 const EATTR& a = *aAttr;
1717 int textThickness =
KiROUND( fontz.
y * ratio / 100.0 );
1747 if( degrees == 90 || degrees == 0 || spin )
1751 else if( degrees == 180 )
1756 else if( degrees == 270 )
1759 degrees =
sign * 90;
1763 degrees = 90 - (
sign * degrees);
1820 if( aFPText->
IsMirrored() && degrees < -90 && degrees >= -270 )
1857 std::unique_ptr<FOOTPRINT> m = std::make_unique<FOOTPRINT>(
m_board );
1860 fpID.
Parse( aPkgName,
true );
1864 wxXmlNode* packageItem = aPackage->GetChildren();
1869 m.get()->Value().SetLayer( layer );
1871 while( packageItem )
1873 const wxString& itemName = packageItem->GetName();
1875 if( itemName == wxT(
"description" ) )
1878 m->SetLibDescription( descr );
1880 else if( itemName == wxT(
"wire" ) )
1882 else if( itemName == wxT(
"pad" ) )
1884 else if( itemName == wxT(
"text" ) )
1886 else if( itemName == wxT(
"rectangle" ) )
1888 else if( itemName == wxT(
"polygon" ) )
1890 else if( itemName == wxT(
"circle" ) )
1892 else if( itemName == wxT(
"hole" ) )
1894 else if( itemName == wxT(
"smd" ) )
1897 packageItem = packageItem->GetNext();
1914 wxLogMessage( wxString::Format(
_(
"Ignoring a wire since Eagle layer '%s' (%d) was not mapped" ),
1973 aFootprint->
Add( dwg );
1984 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
1994 pad->SetDrillSize(
VECTOR2I( eagleDrillz, eagleDrillz ) );
2046 double drillz =
pad->GetDrillSize().x;
2047 double annulus = drillz *
m_rules->rvPadTop;
2049 int diameter =
KiROUND( drillz + 2 * annulus );
2057 sz.
x = ( sz.
x * ( 100 +
m_rules->psElongationLong ) ) / 100;
2062 int offset =
KiROUND( ( sz.
x - sz.
y ) / 2.0 );
2073 if(
pad->GetSizeX() > 0 &&
pad->GetSizeY() > 0 &&
pad->HasHole() )
2075 aFootprint->
Add(
pad.release() );
2082 wxLogError(
_(
"Invalid zero-sized pad ignored in\nfile: %s" ),
m_board->GetFileName() );
2084 wxLogError(
_(
"Invalid zero-sized pad ignored in\nfile: %s" ), fileName.GetFullName() );
2096 wxLogMessage( wxString::Format(
_(
"Ignoring a text since Eagle layer '%s' (%d) was not mapped" ),
2104 if( t.
text.Upper() == wxT(
">NAME" ) && aFootprint->
GetReference().IsEmpty() )
2108 textItem->
SetText( wxT(
"REF**" ) );
2110 else if( t.
text.Upper() == wxT(
">VALUE" ) && aFootprint->
GetValue().IsEmpty() )
2112 textItem = &aFootprint->
Value();
2118 textItem =
new PCB_TEXT( aFootprint );
2119 aFootprint->
Add( textItem );
2207 ZONE* zone =
new ZONE( aFootprint );
2212 const int outlineIdx = -1;
2234 wxLogMessage( wxString::Format(
_(
"Ignoring a rectangle since Eagle layer '%s' (%d) was not mapped" ),
2242 aFootprint->
Add( dwg );
2248 std::vector<VECTOR2I> pts;
2253 pts.push_back( start );
2256 pts.push_back(
end );
2273 std::vector<VECTOR2I> pts;
2276 wxXmlNode* vertex = aTree->GetChildren();
2277 std::vector<EVERTEX> vertices;
2285 if( vertex->GetName() == wxT(
"vertex" ) )
2286 vertices.emplace_back( vertex );
2288 vertex = vertex->GetNext();
2291 vertices.push_back( vertices[0] );
2293 for(
size_t i = 0; i < vertices.size() - 1; i++ )
2316 double delta = angle / segCount;
2318 for(
double a = end_angle + angle; fabs( a - end_angle ) > fabs(
delta ); a -=
delta )
2333 ZONE* zone =
new ZONE( aFootprint );
2349 wxLogMessage( wxString::Format(
_(
"Ignoring a polygon since Eagle layer '%s' (%d) was not mapped" ),
2357 aFootprint->
Add( dwg );
2383 ZONE* zone =
new ZONE( aFootprint );
2390 int outlineRadius =
radius + ( width / 2 );
2396 VECTOR2I rotatedPoint( outlineRadius, 0 );
2404 int innerRadius =
radius - ( width / 2 );
2410 VECTOR2I rotatedPoint( innerRadius, 0 );
2425 wxLogMessage( wxString::Format(
_(
"Ignoring a circle since Eagle layer '%s' (%d) was not mapped" ),
2441 aFootprint->
Add( gr );
2444 switch( (
int) layer )
2486 pad->SetPosition( padpos );
2495 pad->SetDrillSize( sz );
2519 pad->SetLayer( layer );
2525 pad->SetLayerSet( front );
2526 else if( layer ==
B_Cu )
2527 pad->SetLayerSet( back );
2529 int minPadSize = std::min( padSize.
x, padSize.
y );
2533 (
int) ( minPadSize *
m_rules->srRoundness ),
2534 m_rules->srMaxRoundness * 2 );
2538 double roundRatio = (double) roundRadius / minPadSize / 2.0;
2542 roundRatio = std::fmax( *e.
roundness / 200.0, roundRatio );
2555 (
int) (
m_rules->mvCreamFrame * minPadSize ),
2562 pad->SetLayerSet(
pad->GetLayerSet().set(
F_Mask,
false ) );
2563 else if( layer ==
B_Cu )
2564 pad->SetLayerSet(
pad->GetLayerSet().set(
B_Mask,
false ) );
2571 pad->SetLayerSet(
pad->GetLayerSet().set(
F_Paste,
false ) );
2572 else if( layer ==
B_Cu )
2573 pad->SetLayerSet(
pad->GetLayerSet().set(
B_Paste,
false ) );
2588 (
int) (
m_rules->mvStopFrame * std::min( padSize.
x, padSize.
y ) ),
2596 wxCHECK( footprint, );
2606 footprint->SetParent(
nullptr );
2622 m_xpath->push(
"classes.class",
"number" );
2624 std::vector<ECLASS> eClasses;
2625 wxXmlNode* classNode = aClasses->GetChildren();
2631 ECLASS eClass( classNode );
2632 std::shared_ptr<NETCLASS> netclass;
2634 if( eClass.
name.CmpNoCase( wxT(
"default" ) ) == 0 )
2644 netclass->SetTrackWidth( INT_MAX );
2645 netclass->SetViaDiameter( INT_MAX );
2646 netclass->SetViaDrill( INT_MAX );
2648 eClasses.emplace_back( eClass );
2652 auto clearanceToDefaultIt = eClass.
clearanceMap.find( wxT(
"0" ) );
2654 if( clearanceToDefaultIt != eClass.
clearanceMap.end() )
2656 netclass->SetClearance( clearanceToDefaultIt->second.ToPcbUnits() );
2660 classNode = classNode->GetNext();
2665 for(
ECLASS& eClass : eClasses )
2667 for(
const auto& [className, pt] : eClass.clearanceMap )
2670 if( className == wxT(
"0" ) )
2676 rule.Printf( wxT(
"(rule \"class %s:%s\"\n"
2677 " (condition \"A.NetClass == '%s' && B.NetClass == '%s'\")\n"
2678 " (constraint clearance (min %smm)))\n" ),
2705 m_xpath->push(
"signals.signal",
"name" );
2708 wxXmlNode* net = aSignals->GetChildren();
2714 bool sawPad =
false;
2718 const wxString& netName =
escapeName( net->GetAttribute(
"name" ) );
2720 std::shared_ptr<NETCLASS> netclass;
2722 if( net->HasAttribute(
"class" ) )
2724 auto netclassIt =
m_classMap.find( net->GetAttribute(
"class" ) );
2730 netclass = netclassIt->second;
2736 m_xpath->Value( netName.c_str() );
2739 wxXmlNode* netItem = net->GetChildren();
2744 const wxString& itemName = netItem->GetName();
2746 if( itemName == wxT(
"wire" ) )
2763 if( netclass && width < netclass->GetTrackWidth() )
2764 netclass->SetTrackWidth( width );
2774 double radiusA = ( mid -
center ).EuclideanNorm();
2775 double radiusB = ( otherMid -
center ).EuclideanNorm();
2778 std::swap( mid, otherMid );
2811 else if( itemName == wxT(
"via" ) )
2823 && layer_front_most != layer_back_most )
2837 double annulus = drillz *
m_rules->rvViaOuter;
2839 kidiam =
KiROUND( drillz + 2 * annulus );
2843 via->SetDrill( drillz );
2849 if( !v.
diam || via_width <= via->GetDrill() )
2851 double annular_width = ( via_width -
via->GetDrill() ) / 2.0;
2861 if( netclass && kidiam < netclass->GetViaDiameter() )
2862 netclass->SetViaDiameter( kidiam );
2867 if( netclass && drillz < netclass->GetViaDrill() )
2868 netclass->SetViaDrill( drillz );
2873 if( layer_front_most ==
F_Cu && layer_back_most ==
B_Cu )
2877 else if( layer_front_most ==
F_Cu || layer_back_most ==
B_Cu )
2888 via->SetLayerPair( layer_front_most, layer_back_most );
2889 via->SetPosition( pos );
2892 via->SetNetCode( netCode );
2898 else if( itemName == wxT(
"contactref" ) )
2900 m_xpath->push(
"contactref" );
2903 const wxString& reference = netItem->GetAttribute(
"element" );
2904 const wxString&
pad = netItem->GetAttribute(
"pad" );
2914 else if( itemName == wxT(
"polygon" ) )
2921 zones.push_back( zone );
2923 if( !zone->GetIsRuleArea() )
2924 zone->SetNetCode( netCode );
2930 netItem = netItem->GetNext();
2933 if( zones.size() && !sawPad )
2937 for(
ZONE* zone : zones )
2947 net = net->GetNext();
2955 const std::vector<INPUT_LAYER_DESC>& aInputLayerDescriptionVector )
2957 std::map<wxString, PCB_LAYER_ID> layer_map;
2962 layer_map.emplace( layer.Name, layerId );
2971 std::vector<INPUT_LAYER_DESC> inputDescs;
2973 for (
const std::pair<const int, ELAYER>& layerPair :
m_eagleLayers )
2975 const ELAYER& eLayer = layerPair.second;
2986 inputDescs.push_back( layerDesc );
3007 bool aIsLibraryCache )
const
3016 if( copperLayer >= 0 )
3017 copperLayers[copperLayer] =
true;
3024 bool required =
false;
3025 LSET permittedLayers;
3027 permittedLayers.
set();
3030 switch( aEagleLayer )
3128 if( aIsLibraryCache )
3136 return {
PCB_LAYER_ID( kiLayer ), permittedLayers, required };
3142 static const wxString
unknown(
"unknown" );
3150 static const int unknown = -1;
3163 if(
auto it =
m_props->find(
"page_width" ); it !=
m_props->end() )
3164 page_width = it->second;
3166 if(
auto it =
m_props->find(
"page_height" ); it !=
m_props->end() )
3167 page_height = it->second;
3169 if( !page_width.
empty() && !page_height.
empty() )
3173 int w = atoi( page_width.
c_str() );
3174 int h = atoi( page_height.
c_str() );
3176 int desired_x = ( w - bbbox.
GetWidth() ) / 2;
3177 int desired_y = ( h - bbbox.
GetHeight() ) / 2;
3188 if( aPath.IsEmpty() )
3189 return wxDateTime::Now().GetValue().GetValue();
3191 wxFileName fn( aPath );
3193 if( fn.IsFileReadable() && fn.GetModificationTime().IsValid() )
3194 return fn.GetModificationTime().GetValue().GetValue();
3223 string filename = (
const char*) aLibPath.char_str( wxConvFile );
3226 wxFileName fn( filename );
3227 wxFFileInputStream stream( fn.GetFullPath() );
3228 wxXmlDocument xmlDocument;
3230 if( !stream.IsOk() || !xmlDocument.Load( stream ) )
3231 THROW_IO_ERROR( wxString::Format(
_(
"Unable to read file '%s'." ), fn.GetFullPath() ) );
3233 doc = xmlDocument.GetRoot();
3235 wxXmlNode* drawing =
MapChildren( doc )[
"drawing"];
3241 m_xpath->push(
"eagle.drawing.layers" );
3242 wxXmlNode* layers = drawingChildren[
"layers"];
3247 m_xpath->push(
"eagle.drawing.library" );
3248 wxXmlNode*
library = drawingChildren[
"library"];
3282 bool aBestEfforts,
const std::map<std::string, UTF8>* aProperties )
3286 init( aProperties );
3294 errorMsg = ioe.
What();
3301 aFootprintNames.Add(
name );
3303 if( !errorMsg.IsEmpty() && !aBestEfforts )
3309 bool aKeepUUID,
const std::map<std::string, UTF8>* aProperties )
3311 init( aProperties );
3320 copy->SetParent(
nullptr );
3327 int minLayerCount = 2;
3329 std::map<wxString, PCB_LAYER_ID>::const_iterator it;
3340 if( ( ordinal + 2 ) > minLayerCount )
3341 minLayerCount = ordinal + 2;
3347 if( ( minLayerCount % 2 ) != 0 )
3350 return minLayerCount;
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
constexpr int ARC_HIGH_DEF
constexpr EDA_IU_SCALE pcbIUScale
#define DEFAULT_SILK_LINE_WIDTH
#define DEFAULT_EDGE_WIDTH
#define DEFAULT_LINE_WIDTH
#define DEFAULT_COURTYARD_WIDTH
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
BASE_SET & set(size_t pos)
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
VECTOR2I GetTextSize(PCB_LAYER_ID aLayer) const
Return the default text size from the layer class for the given layer.
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
int m_ViasMinAnnularWidth
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
FOOTPRINT * GetParentFootprint() const
Information pertinent to a Pcbnew printed circuit board.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
constexpr coord_type GetY() const
constexpr size_type GetWidth() const
constexpr coord_type GetX() const
constexpr size_type GetHeight() const
void SetCenter(const VECTOR2I &aCenter)
SHAPE_POLY_SET & GetPolyShape()
virtual void SetFilled(bool aFlag)
void SetStart(const VECTOR2I &aStart)
void SetShape(SHAPE_T aShape)
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 SetPolyPoints(const std::vector< VECTOR2I > &aPoints)
const EDA_ANGLE & GetTextAngle() const
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
void SetTextPos(const VECTOR2I &aPoint)
void SetMirrored(bool isMirrored)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
GR_TEXT_H_ALIGN_T GetHorizJustify() const
virtual void SetVisible(bool aVisible)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
void SetKeepUpright(bool aKeepUpright)
GR_TEXT_V_ALIGN_T GetVertJustify() const
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
VECTOR2I GetTextSize() const
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
RAII class to set and restore the fontconfig reporter.
virtual bool CanReadLibrary(const wxString &aFileName) const
Checks if this IO object can read the specified library file/directory.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
virtual void RegisterCallback(LAYER_MAPPING_HANDLER aLayerMappingHandler)
Register a different handler to be called when mapping of input layers to KiCad layers occurs.
LAYER_MAPPING_HANDLER m_layer_mapping_handler
Callback to get layer mapping.
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
const UTF8 & GetLibItemName() const
static LOAD_INFO_REPORTER & GetInstance()
LSET is a set of PCB_LAYER_IDs.
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
A collection of nets and the parameters used to route or test these nets.
int GetViaDiameter() const
int GetTrackWidth() const
Handle the data for a net.
void SetNetClass(const std::shared_ptr< NETCLASS > &aNetClass)
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
void SetNetclassPatternAssignment(const wxString &pattern, const wxString &netclass)
Sets a netclass pattern assignment Calling this method will reset the effective netclass calculation ...
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
void SetNetclass(const wxString &netclassName, std::shared_ptr< NETCLASS > &netclass)
Sets the given netclass Calling user is responsible for resetting the effective netclass calculation ...
T & Get()
Return a reference to the value of the attribute assuming it is available.
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
void SetNumber(const wxString &aNumber)
Set the pad number (note that it can be alphanumeric, such as the array reference "AA12").
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
void SetLocalZoneConnection(ZONE_CONNECTION aType)
void SetPosition(const VECTOR2I &aPos) override
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) const
void SetPosition(const VECTOR2I &aPos) override
void SetMid(const VECTOR2I &aMid)
void SetUnits(EDA_UNITS aUnits)
void SetLineThickness(int aWidth)
virtual void SetEnd(const VECTOR2I &aPoint)
void SetPrecision(DIM_PRECISION aPrecision)
virtual void SetStart(const VECTOR2I &aPoint)
void SetOverrideText(const wxString &aValue)
For better understanding of the points that make a dimension:
void SetHeight(int aHeight)
Set the distance from the feature points to the crossbar line.
A leader is a dimension-like object pointing to a specific point.
A radial dimension indicates either the radius or diameter of an arc or circle.
std::vector< ELAYER > ELAYERS
void packageSMD(FOOTPRINT *aFootprint, wxXmlNode *aTree) const
Handles common pad properties.
void loadPlain(wxXmlNode *aPlain)
int m_min_trace
smallest trace we find on Load(), in BIU.
std::map< wxString, PCB_LAYER_ID > m_layer_map
Map of Eagle layers to KiCad layers.
void orientFPText(FOOTPRINT *aFootprint, const EELEMENT &e, PCB_TEXT *aFPText, const EATTR *aAttr)
VECTOR2I kicad_fontsize(const ECOORD &d, int aTextThickness) const
create a font size (fontz) from an eagle font size scalar and KiCad font thickness
std::map< wxString, PCB_LAYER_ID > DefaultLayerMappingCallback(const std::vector< INPUT_LAYER_DESC > &aInputLayerDescriptionVector)
Return the automapped layers.
bool checkHeader(const wxString &aFileName) const
void loadElements(wxXmlNode *aElements)
FOOTPRINT * makeFootprint(wxXmlNode *aPackage, const wxString &aPkgName)
Create a FOOTPRINT from an Eagle package.
int m_min_hole
smallest diameter hole we find on Load(), in BIU.
std::vector< FOOTPRINT * > GetImportedCachedLibraryFootprints() override
Return a container with the cached library footprints generated in the last call to Load.
XPATH * m_xpath
keeps track of what we are working on within XML document during a Load().
unsigned m_totalCount
for progress reporting
void cacheLib(const wxString &aLibraryPath)
This PLUGIN only caches one footprint library, this determines which one.
int m_hole_count
generates unique footprint names from eagle "hole"s.
std::map< wxString, FOOTPRINT * > m_templates
is part of a FOOTPRINT factory that operates using copy construction.
std::map< wxString, int > m_eagleLayersIds
Eagle layer ids stored by layer name.
void mapEagleLayersToKicad(bool aIsLibraryCache=false)
Generate mapping between Eagle and KiCad layers.
std::map< wxString, std::shared_ptr< NETCLASS > > m_classMap
std::tuple< PCB_LAYER_ID, LSET, bool > defaultKicadLayer(int aEagleLayer, bool aIsLibraryCache=false) const
Get the default KiCad layer corresponding to an Eagle layer of the board, a set of sensible layer map...
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
void loadLibraries(wxXmlNode *aLibs)
void init(const std::map< std::string, UTF8 > *aProperties)
initialize PLUGIN like a constructor would, and futz with fresh BOARD if needed.
FOOTPRINT * FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, bool aKeepUUID=false, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a footprint having aFootprintName from the aLibraryPath containing a library format that this PC...
int eagle_layer_id(const wxString &aLayerName) const
Get Eagle layer number by its name.
void loadAllSections(wxXmlNode *aDocument)
bool CanReadFootprint(const wxString &aFileName) const override
Checks if this PCB_IO can read a footprint from specified file or directory.
void packageWire(FOOTPRINT *aFootprint, wxXmlNode *aTree) const
bool CanReadBoard(const wxString &aFileName) const override
Checks if this PCB_IO can read the specified board file.
const wxString & eagle_layer_name(int aLayer) const
Get Eagle layer name by its number.
ELAYERS::const_iterator EITER
void packageRectangle(FOOTPRINT *aFootprint, wxXmlNode *aTree) const
int kicad_y(const ECOORD &y) const
Convert an Eagle distance to a KiCad distance.
void loadClasses(wxXmlNode *aClasses)
std::map< int, ELAYER > m_eagleLayers
Eagle layer data stored by layer number.
NET_MAP m_pads_to_nets
net list
void packageText(FOOTPRINT *aFootprint, wxXmlNode *aTree) const
int getMinimumCopperLayerCount() const
Determines the minimum copper layer stackup count that includes all mapped layers.
void packageHole(FOOTPRINT *aFootprint, wxXmlNode *aTree, bool aCenter) const
void packagePolygon(FOOTPRINT *aFootprint, wxXmlNode *aTree) const
void centerBoard()
move the BOARD into the center of the page
unsigned m_lastProgressCount
int m_cu_map[17]
map eagle to KiCad, cu layers only.
ZONE * loadPolygon(wxXmlNode *aPolyNode)
Load a copper or keepout polygon and adds it to the board.
int m_min_via
smallest via we find on Load(), in BIU.
bool CanReadLibrary(const wxString &aFileName) const override
Checks if this IO object can read the specified library file/directory.
void packageCircle(FOOTPRINT *aFootprint, wxXmlNode *aTree) const
void loadLibrary(wxXmlNode *aLib, const wxString *aLibName)
Load the Eagle "library" XML element, which can occur either under a "libraries" element (if a *....
void packagePad(FOOTPRINT *aFootprint, wxXmlNode *aTree)
void loadSignals(wxXmlNode *aSignals)
ERULES * m_rules
Eagle design rules.
PCB_LAYER_ID kicad_layer(int aLayer) const
Convert an Eagle layer to a KiCad layer.
void orientFootprintAndText(FOOTPRINT *aFootprint, const EELEMENT &e, const EATTR *aNameAttr, const EATTR *aValueAttr)
long long GetLibraryTimestamp(const wxString &aLibraryPath) const override
Generate a timestamp representing all the files in the library (including the library directory).
int m_min_annulus
smallest via annulus we find on Load(), in BIU.
void loadLayerDefs(wxXmlNode *aLayers)
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, bool aBestEfforts, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Return a list of footprint names contained within the library at aLibraryPath.
void setKeepoutSettingsToZone(ZONE *aZone, int aLayer) const
void transferPad(const EPAD_COMMON &aEaglePad, PAD *aPad) const
Deletes the footprint templates list.
int kicad_x(const ECOORD &x) const
void loadDesignRules(wxXmlNode *aDesignRules)
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
BOARD * m_board
The board BOARD being worked on, no ownership here.
virtual bool CanReadBoard(const wxString &aFileName) const
Checks if this PCB_IO can read the specified board file.
PCB_IO(const wxString &aName)
const std::map< std::string, UTF8 > * m_props
Properties passed via Save() or Load(), no ownership, may be NULL.
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void Move(const VECTOR2I &aMoveVector) override
Move this object.
void SetStroke(const STROKE_PARAMS &aStroke) override
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
virtual void SetPosition(const VECTOR2I &aPos) override
void SetEnd(const VECTOR2I &aEnd)
void SetPosition(const VECTOR2I &aPos) override
virtual void SetWidth(int aWidth)
Container for project specific data.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
Represent a set of closed polygons.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
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)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Simple container to manage line stroke parameters.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
const char * c_str() const
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
Keep track of what we are working on within a PTREE.
Handle a list of polygons defining a copper zone.
void SetDoNotAllowPads(bool aEnable)
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aBorderHatchStyle, int aBorderHatchPitch, bool aRebuilBorderdHatch)
Set all hatch parameters for the zone.
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
SHAPE_POLY_SET * Outline()
void NewHole()
Create a new hole on the zone; i.e., a new contour on the zone's outline.
void SetIsRuleArea(bool aEnable)
void SetDoNotAllowTracks(bool aEnable)
void Rotate(const VECTOR2I &aCentre, const EDA_ANGLE &aAngle) override
Rotate the outlines.
void SetLayerSet(const LSET &aLayerSet) override
void SetDoNotAllowVias(bool aEnable)
void SetDoNotAllowFootprints(bool aEnable)
bool AppendCorner(VECTOR2I aPosition, int aHoleIdx, bool aAllowDuplication=false)
Add a new corner to the zone outline (to the main outline or a hole)
void SetDoNotAllowZoneFills(bool aEnable)
static int GetDefaultHatchPitch()
@ ALLOW_ACUTE_CORNERS
just inflate the polygon. Acute angles create spikes
NODE_MAP MapChildren(wxXmlNode *aCurrentNode)
Provide an easy access to the children of an XML node via their names.
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.
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< wxString > opt_wxString
std::unordered_map< wxString, wxXmlNode * > NODE_MAP
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE FULL_CIRCLE
static constexpr EDA_ANGLE ANGLE_360
#define IGNORE_PARENT_GROUP
a few functions useful in geometry calculations.
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
PCB_LAYER_ID BoardLayerFromLegacyId(int aLegacyId)
Retrieve a layer ID from an integer converted from a legacy (pre-V9) enum value.
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
size_t CopperLayerToOrdinal(PCB_LAYER_ID aLayer)
Converts KiCad copper layer enum to an ordinal between the front and back layers.
PCB_LAYER_ID
A quick note on layer IDs:
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
KICOMMON_API wxString StringFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Return the string from aValue according to aUnits (inch, mm ...) for display.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ SMD
Smd pad, appears on the solder paste layer (default)
static wxString makeKey(const wxString &aFirst, const wxString &aSecond)
Assemble a two part key as a simple concatenation of aFirst and aSecond parts, using a separator.
#define DIMENSION_PRECISION
static int parseEagle(const wxString &aDistance)
Parse an eagle distance which is either mm, or mils if there is "mil" suffix.
static T eagleClamp(T aMin, T aValue, T aMax)
std::vector< ZONE * > ZONES
NET_MAP::const_iterator NET_MAP_CITER
bool ReplaceIllegalFileNameChars(std::string &aName, int aReplaceChar)
Checks aName for illegal file name characters.
wxString UnescapeHTML(const wxString &aString)
Return a new wxString unescaped from HTML format.
Parse an Eagle "attribute" XML element.
std::map< wxString, ECOORD > clearanceMap
long long int value
Value expressed in nanometers.
opt_wxString dimensionType
Structure holding common properties for through-hole and SMD pads.
Eagle polygon, without vertices which are parsed as needed.
static const int max_priority
Eagle XML rectangle in binary.
subset of eagle.drawing.board.designrules in the XML document
int psBottom
Shape of the bottom pads.
double mvStopFrame
solderpaste mask, expressed as percentage of the smaller pad/via dimension
double srRoundness
corner rounding ratio for SMD pads (percentage)
double rlMinViaOuter
minimum copper annulus on via
int mlMaxCreamFrame
solder paste mask, maximum size (Eagle mils, here nanometers)
int mlMinCreamFrame
solder paste mask, minimum size (Eagle mils, here nanometers)
int psTop
Shape of the top pads.
double rlMaxViaOuter
maximum copper annulus on via
void parse(wxXmlNode *aRules, std::function< void()> aCheckpoint)
percent over 100%.
double mdWireWire
wire to wire spacing I presume.
double rvPadTop
top pad size as percent of drill size
double rvViaOuter
copper annulus is this percent of via hole
double rlMinPadTop
minimum copper annulus on through hole pads
int psElongationOffset
the offset of the hole within the "long" pad.
int mlMinStopFrame
solder mask, minimum size (Eagle mils, here nanometers)
int srMinRoundness
corner rounding radius, maximum size (Eagle mils, here nanometers)
int mlMaxStopFrame
solder mask, maximum size (Eagle mils, here nanometers)
double rlMaxPadTop
maximum copper annulus on through hole pads
int psFirst
Shape of the first pads.
wxString assetId
The unique asset identifier for the asset type.
int layer_back_most
< extent
opt_double curve
range is -359.9..359.9
Implement a simple wrapper around runtime_error to isolate the errors thrown by the Eagle XML parser.
wxString result
Test unit parsing edge cases and error handling.
const VECTOR2I CalcArcMid(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCenter, bool aMinArcAngle=true)
Return the middle point of an arc, half-way between 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.
double DEG2RAD(double deg)
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
constexpr int sign(T val)
VECTOR2< int32_t > VECTOR2I
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
@ THERMAL
Use thermal relief for pads.
@ FULL
pads are covered by copper
#define ZONE_THICKNESS_MIN_VALUE_MM