56#include <wx/xml/xml.h>
57#include <wx/filename.h>
59#include <wx/wfstream.h>
60#include <wx/txtstrm.h>
97 ECOORD coord( aDistance, unit );
108 T ret = std::max( aMin, aValue );
109 return std::min( aMax, ret );
115static wxString
makeKey(
const wxString& aFirst,
const wxString& aSecond )
117 wxString key = aFirst +
'\x02' + aSecond;
165 wxXmlNode* child = aRules->GetChildren();
171 if( child->GetName() == wxT(
"param" ) )
173 const wxString&
name = child->GetAttribute( wxT(
"name" ) );
174 const wxString& value = child->GetAttribute( wxT(
"value" ) );
176 if(
name == wxT(
"psElongationLong" ) )
178 else if(
name == wxT(
"psElongationOffset" ) )
180 else if(
name == wxT(
"mvStopFrame" ) )
182 else if(
name == wxT(
"mvCreamFrame" ) )
184 else if(
name == wxT(
"mlMinStopFrame" ) )
186 else if(
name == wxT(
"mlMaxStopFrame" ) )
188 else if(
name == wxT(
"mlMinCreamFrame" ) )
190 else if(
name == wxT(
"mlMaxCreamFrame" ) )
192 else if(
name == wxT(
"srRoundness" ) )
194 else if(
name == wxT(
"srMinRoundness" ) )
196 else if(
name == wxT(
"srMaxRoundness" ) )
198 else if(
name == wxT(
"psTop" ) )
199 psTop = wxAtoi( value );
200 else if(
name == wxT(
"psBottom" ) )
202 else if(
name == wxT(
"psFirst" ) )
204 else if(
name == wxT(
"rvPadTop" ) )
206 else if(
name == wxT(
"rlMinPadTop" ) )
208 else if(
name == wxT(
"rlMaxPadTop" ) )
210 else if(
name == wxT(
"rvViaOuter" ) )
212 else if(
name == wxT(
"rlMinViaOuter" ) )
214 else if(
name == wxT(
"rlMaxViaOuter" ) )
216 else if(
name == wxT(
"mdWireWire" ) )
220 child = child->GetNext();
233 m_timestamp( wxDateTime::Now().GetValue().GetValue() )
235 using namespace std::placeholders;
277 wxFileInputStream input( aFileName );
282 wxTextInputStream
text( input );
284 for(
int i = 0; i < 8; i++ )
289 if(
text.ReadLine().Contains( wxS(
"<eagle" ) ) )
299 const unsigned PROGRESS_DELTA = 50;
320 return VECTOR2I( kz - aTextThickness, kz - aTextThickness );
325 const std::map<std::string, UTF8>* aProperties,
PROJECT* aProject )
338 m_board->SetFileName( aFileName );
341 unique_ptr<BOARD> deleter( aAppendToMe ?
nullptr :
m_board );
353 wxFileName fn = aFileName;
356 wxFFileInputStream stream( fn.GetFullPath() );
357 wxXmlDocument xmlDocument;
359 if( !stream.IsOk() || !xmlDocument.Load( stream ) )
362 fn.GetFullPath() ) );
365 doc = xmlDocument.GetRoot();
391 NETCLASS defaults( wxT(
"dummy" ) );
393 auto finishNetclass =
394 [&](
const std::shared_ptr<NETCLASS>& netclass )
398 if( !netclass->HasClearance() )
403 if( netclass->GetTrackWidth() == INT_MAX )
406 if( netclass->GetViaDiameter() == INT_MAX )
409 if( netclass->GetViaDrill() == INT_MAX )
413 std::shared_ptr<NET_SETTINGS>& netSettings = bds.
m_NetSettings;
415 finishNetclass( netSettings->GetDefaultNetclass() );
417 for(
const auto& [
name, netclass] : netSettings->GetNetclasses() )
418 finishNetclass( netclass );
420 m_board->m_LegacyNetclassesLoaded =
true;
421 m_board->m_LegacyDesignSettingsLoaded =
true;
423 fn.SetExt( wxT(
"kicad_dru" ) );
424 wxFile rulesFile( fn.GetFullPath(), wxFile::write );
428 wxASSERT(
m_xpath->Contents().size() == 0 );
432 wxString errmsg = exc.what();
434 errmsg += wxT(
"\n@ " );
444 LSET enabledLayers =
m_board->GetDesignSettings().GetEnabledLayers();
446 for(
const auto& [eagleLayerName, layer] :
m_layer_map )
449 enabledLayers.
set( layer );
452 m_board->GetDesignSettings().SetEnabledLayers( enabledLayers );
463 std::vector<FOOTPRINT*> retval;
466 retval.push_back(
static_cast<FOOTPRINT*
>( footprint->Clone() ) );
502 wxXmlNode* drawing =
MapChildren( aDoc )[
"drawing"];
505 wxXmlNode* board = drawingChildren[
"board"];
508 auto count_children =
509 [
this]( wxXmlNode* aNode )
513 wxXmlNode* child = aNode->GetChildren();
518 child = child->GetNext();
523 wxXmlNode* designrules = boardChildren[
"designrules"];
524 wxXmlNode* layers = drawingChildren[
"layers"];
525 wxXmlNode* plain = boardChildren[
"plain"];
526 wxXmlNode* classes = boardChildren[
"classes"];
527 wxXmlNode* signals = boardChildren[
"signals"];
528 wxXmlNode* libs = boardChildren[
"libraries"];
529 wxXmlNode* elems = boardChildren[
"elements"];
536 count_children( designrules );
537 count_children( layers );
538 count_children( plain );
539 count_children( signals );
540 count_children( elems );
545 libs = libs->GetNext();
549 libs = boardChildren[
"libraries"];
552 m_xpath->push(
"eagle.drawing" );
591 m_xpath->push(
"designrules" );
610 wxXmlNode* layerNode = aLayers->GetChildren();
617 ELAYER elayer( layerNode );
623 cu.push_back( elayer );
625 layerNode = layerNode->GetNext();
629 int ki_layer_count = 0;
631 for(
EITER it = cu.begin(); it != cu.end(); ++it, ++ki_layer_count )
633 if( ki_layer_count == 0 )
637 else if( ki_layer_count ==
int( cu.size()-1 ) )
651 m_board->SetCopperLayerCount( cu.size() );
653 for(
EITER it = cu.begin(); it != cu.end(); ++it )
660 m_board->SetLayerName( layer, it->name );
670#define DIMENSION_PRECISION DIM_PRECISION::X_XX
681 wxXmlNode* gr = aGraphics->GetChildren();
688 wxString grName = gr->GetName();
690 if( grName == wxT(
"wire" ) )
707 width =
m_board->GetDesignSettings().GetLineThickness( layer );
733 else if( grName == wxT(
"text" ) )
774 if( degrees > 90 && degrees <= 270 )
799 offset.
y = -signY * (int) textbox.
GetHeight();
811 offset.
x = signX * (int) textbox.
GetWidth();
817 offset.
x = -signX * (int) textbox.
GetWidth();
876 if( pcbtxt->
IsMirrored() && degrees < -90 && degrees >= -270 )
894 else if( grName == wxT(
"circle" ) )
913 int outlineRadius =
radius + ( width / 2 );
919 VECTOR2I rotatedPoint( outlineRadius, 0 );
927 int innerRadius =
radius - ( width / 2 );
933 VECTOR2I rotatedPoint( innerRadius, 0 );
960 else if( grName == wxT(
"rectangle" ) )
980 const int outlineIdx = -1;
999 else if( grName == wxT(
"hole" ) )
1009 footprint->
SetReference( wxString::Format( wxT(
"UNK_HOLE_%d" ), hole_count ) );
1012 LIB_ID fpid( wxEmptyString, wxString::Format( wxT(
"dummyfp%d" ), hole_count ) );
1019 else if( grName == wxT(
"frame" ) )
1023 else if( grName == wxT(
"polygon" ) )
1029 else if( grName == wxT(
"dimension" ) )
1063 dimension->
SetEnd( pt2 );
1098 int newY = ( pt1.
y + pt2.
y ) / 2;
1104 int newX = ( pt1.
x + pt2.
x ) / 2;
1115 dimension->
SetEnd( pt2 );
1125 if(
abs( pt1.
x - pt2.
x ) < 50000 )
1127 int offset = pt3.
x - pt1.
x;
1134 else if(
abs( pt1.
y - pt2.
y ) < 50000 )
1136 int offset = pt3.
y - pt1.
y;
1169 wxString urn = aLib->GetAttribute(
"urn" );
1171 wxString urnOrdinal;
1173 if( !urn.IsEmpty() )
1174 urnOrdinal = urn.AfterLast(
':' );
1177 wxXmlNode* packages =
MapChildren( aLib )[
"packages"];
1189 wxXmlNode*
package = packages->GetChildren();
1195 m_xpath->push(
"package",
"name" );
1197 wxString pack_ref = package->GetAttribute(
"name" );
1199 if( !urnOrdinal.IsEmpty() )
1200 pack_ref += wxS(
"_" ) + urnOrdinal;
1204 m_xpath->Value( pack_ref.ToUTF8() );
1206 wxString key = aLibName ?
makeKey( *aLibName, pack_ref ) : pack_ref;
1211 auto r =
m_templates.insert( { key, footprint } );
1215 wxString lib = aLibName ? *aLibName :
m_lib_path;
1216 const wxString& pkg = pack_ref;
1218 wxString emsg = wxString::Format(
_(
"<package> '%s' duplicated in <library> '%s'" ),
1226 package = package->GetNext();
1238 m_xpath->push(
"libraries.library",
"name" );
1241 wxXmlNode*
library = aLibs->GetChildren();
1245 const wxString& lib_name =
library->GetAttribute(
"name" );
1247 m_xpath->Value( lib_name.c_str() );
1261 m_xpath->push(
"elements.element",
"name" );
1265 bool refanceNamePresetInPackageLayout;
1266 bool valueNamePresetInPackageLayout;
1269 wxXmlNode* element = aElements->GetChildren();
1275 if( element->GetName() != wxT(
"element" ) )
1278 element = element->GetNext();
1285 EATTR* nameAttr =
nullptr;
1286 EATTR* valueAttr =
nullptr;
1290 wxString packageName = e.
package;
1300 wxString emsg = wxString::Format(
_(
"No '%s' package in library '%s'." ),
1317 const ENET* enet = &ni->second;
1322 refanceNamePresetInPackageLayout =
true;
1323 valueNamePresetInPackageLayout =
true;
1330 refanceNamePresetInPackageLayout =
false;
1334 if( footprint->
GetValue().size() == 0 )
1337 valueNamePresetInPackageLayout =
false;
1340 wxString reference = e.
name;
1346 if( reference.find_first_not_of(
"0123456789" ) != 0 )
1347 reference.Prepend(
"UNK" );
1351 if( reference.find_first_not_of(
"#" ) != 0 )
1352 reference.Prepend(
"UNK" );
1355 if( reference.find_last_not_of(
"0123456789" ) == (reference.Length()-1) )
1356 reference.Append(
"0" );
1364 if( valueNamePresetInPackageLayout )
1367 if( refanceNamePresetInPackageLayout )
1377 m_xpath->push(
"attribute",
"name" );
1387 wxXmlNode* attribute = element->GetChildren();
1391 if( attribute->GetName() != wxT(
"attribute" ) )
1393 attribute = attribute->GetNext();
1397 EATTR a( attribute );
1399 if( a.
name == wxT(
"NAME" ) )
1412 nameAttr->
name = reference;
1414 if( refanceNamePresetInPackageLayout )
1421 if( refanceNamePresetInPackageLayout )
1430 if( refanceNamePresetInPackageLayout )
1433 nameAttr->
name = nameAttr->
name + wxT(
" = " ) + e.
name;
1444 if( refanceNamePresetInPackageLayout )
1454 else if( a.
name == wxT(
"VALUE" ) )
1468 if( valueNamePresetInPackageLayout )
1474 if( valueNamePresetInPackageLayout )
1477 footprint->
SetValue( wxT(
"VALUE" ) );
1481 if( valueNamePresetInPackageLayout )
1495 if( valueNamePresetInPackageLayout )
1507 attribute = attribute->GetNext();
1516 element = element->GetNext();
1533 wxLogMessage( wxString::Format(
_(
"Ignoring a polygon since Eagle layer '%s' (%d) was not mapped" ),
1540 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
1543 zone->SetLayer( layer );
1548 wxXmlNode* vertex = aPolyNode->GetChildren();
1549 std::vector<EVERTEX> vertices;
1557 if( vertex->GetName() == wxT(
"vertex" ) )
1558 vertices.emplace_back( vertex );
1560 vertex = vertex->GetNext();
1570 if( vertices.size() < 3 )
1572 wxLogMessage( wxString::Format(
_(
"Skipping a polygon on layer '%s' (%d): less than 3 vertices" ),
1578 vertices.push_back( vertices[0] );
1583 for(
size_t i = 0; i < vertices.size() - 1; i++ )
1601 double delta_angle = angle / segCount;
1603 for(
double a = end_angle + angle; fabs( a - end_angle ) > fabs( delta_angle ); a -= delta_angle )
1618 wxLogMessage( wxString::Format(
_(
"Skipping a polygon on layer '%s' (%d): outline count is not 1" ),
1625 zone->AddPolygon( polygon.
COutline( 0 ) );
1630 zone->SetIsRuleArea(
true );
1631 zone->SetDoNotAllowVias(
false );
1632 zone->SetDoNotAllowTracks(
false );
1633 zone->SetDoNotAllowPads(
false );
1634 zone->SetDoNotAllowFootprints(
false );
1635 zone->SetDoNotAllowZoneFills(
true );
1645 zone->SetHatchOrientation(
ANGLE_0 );
1656 zone->SetLocalClearance( 1 );
1673 zone->SetAssignedPriority( rank );
1675 ZONE* zonePtr = zone.release();
1683 const EATTR* aNameAttr,
const EATTR* aValueAttr )
1704 const EATTR* aAttr )
1710 const EATTR& a = *aAttr;
1729 int textThickness =
KiROUND( fontz.
y * ratio / 100.0 );
1759 if( degrees == 90 || degrees == 0 || spin )
1763 else if( degrees == 180 )
1768 else if( degrees == 270 )
1771 degrees =
sign * 90;
1775 degrees = 90 - (
sign * degrees);
1832 if( aFPText->
IsMirrored() && degrees < -90 && degrees >= -270 )
1869 std::unique_ptr<FOOTPRINT> m = std::make_unique<FOOTPRINT>(
m_board );
1872 fpID.
Parse( aPkgName,
true );
1876 wxXmlNode* packageItem = aPackage->GetChildren();
1881 m.get()->Value().SetLayer( layer );
1883 while( packageItem )
1885 const wxString& itemName = packageItem->GetName();
1887 if( itemName == wxT(
"description" ) )
1890 m->SetLibDescription( descr );
1892 else if( itemName == wxT(
"wire" ) )
1894 else if( itemName == wxT(
"pad" ) )
1896 else if( itemName == wxT(
"text" ) )
1898 else if( itemName == wxT(
"rectangle" ) )
1900 else if( itemName == wxT(
"polygon" ) )
1902 else if( itemName == wxT(
"circle" ) )
1904 else if( itemName == wxT(
"hole" ) )
1906 else if( itemName == wxT(
"smd" ) )
1909 packageItem = packageItem->GetNext();
1926 wxLogMessage( wxString::Format(
_(
"Ignoring a wire since Eagle layer '%s' (%d) was not mapped" ),
1985 aFootprint->
Add( dwg );
1996 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
2006 pad->SetDrillSize(
VECTOR2I( eagleDrillz, eagleDrillz ) );
2058 double drillz =
pad->GetDrillSize().x;
2059 double annulus = drillz *
m_rules->rvPadTop;
2061 int diameter =
KiROUND( drillz + 2 * annulus );
2069 sz.
x = ( sz.
x * ( 100 +
m_rules->psElongationLong ) ) / 100;
2074 int offset =
KiROUND( ( sz.
x - sz.
y ) / 2.0 );
2085 if(
pad->GetSizeX() > 0 &&
pad->GetSizeY() > 0 &&
pad->HasHole() )
2087 aFootprint->
Add(
pad.release() );
2094 wxLogError(
_(
"Invalid zero-sized pad ignored in\nfile: %s" ),
m_board->GetFileName() );
2096 wxLogError(
_(
"Invalid zero-sized pad ignored in\nfile: %s" ), fileName.GetFullName() );
2108 wxLogMessage( wxString::Format(
_(
"Ignoring a text since Eagle layer '%s' (%d) was not mapped" ),
2116 if( t.
text.Upper() == wxT(
">NAME" ) && aFootprint->
GetReference().IsEmpty() )
2120 textItem->
SetText( wxT(
"REF**" ) );
2122 else if( t.
text.Upper() == wxT(
">VALUE" ) && aFootprint->
GetValue().IsEmpty() )
2124 textItem = &aFootprint->
Value();
2130 textItem =
new PCB_TEXT( aFootprint );
2131 aFootprint->
Add( textItem );
2219 ZONE* zone =
new ZONE( aFootprint );
2224 const int outlineIdx = -1;
2246 wxLogMessage( wxString::Format(
_(
"Ignoring a rectangle since Eagle layer '%s' (%d) was not mapped" ),
2254 aFootprint->
Add( dwg );
2260 std::vector<VECTOR2I> pts;
2265 pts.push_back( start );
2268 pts.push_back(
end );
2285 std::vector<VECTOR2I> pts;
2288 wxXmlNode* vertex = aTree->GetChildren();
2289 std::vector<EVERTEX> vertices;
2297 if( vertex->GetName() == wxT(
"vertex" ) )
2298 vertices.emplace_back( vertex );
2300 vertex = vertex->GetNext();
2303 vertices.push_back( vertices[0] );
2305 for(
size_t i = 0; i < vertices.size() - 1; i++ )
2328 double delta = angle / segCount;
2330 for(
double a = end_angle + angle; fabs( a - end_angle ) > fabs(
delta ); a -=
delta )
2345 ZONE* zone =
new ZONE( aFootprint );
2361 wxLogMessage( wxString::Format(
_(
"Ignoring a polygon since Eagle layer '%s' (%d) was not mapped" ),
2369 aFootprint->
Add( dwg );
2395 ZONE* zone =
new ZONE( aFootprint );
2402 int outlineRadius =
radius + ( width / 2 );
2408 VECTOR2I rotatedPoint( outlineRadius, 0 );
2416 int innerRadius =
radius - ( width / 2 );
2422 VECTOR2I rotatedPoint( innerRadius, 0 );
2437 wxLogMessage( wxString::Format(
_(
"Ignoring a circle since Eagle layer '%s' (%d) was not mapped" ),
2453 aFootprint->
Add( gr );
2456 switch( (
int) layer )
2498 pad->SetPosition( padpos );
2507 pad->SetDrillSize( sz );
2531 pad->SetLayer( layer );
2537 pad->SetLayerSet( front );
2538 else if( layer ==
B_Cu )
2539 pad->SetLayerSet( back );
2541 int minPadSize = std::min( padSize.
x, padSize.
y );
2545 (
int) ( minPadSize *
m_rules->srRoundness ),
2546 m_rules->srMaxRoundness * 2 );
2550 double roundRatio = (double) roundRadius / minPadSize / 2.0;
2554 roundRatio = std::fmax( *e.
roundness / 200.0, roundRatio );
2567 (
int) (
m_rules->mvCreamFrame * minPadSize ),
2574 pad->SetLayerSet(
pad->GetLayerSet().set(
F_Mask,
false ) );
2575 else if( layer ==
B_Cu )
2576 pad->SetLayerSet(
pad->GetLayerSet().set(
B_Mask,
false ) );
2583 pad->SetLayerSet(
pad->GetLayerSet().set(
F_Paste,
false ) );
2584 else if( layer ==
B_Cu )
2585 pad->SetLayerSet(
pad->GetLayerSet().set(
B_Paste,
false ) );
2600 (
int) (
m_rules->mvStopFrame * std::min( padSize.
x, padSize.
y ) ),
2608 wxCHECK( footprint, );
2618 footprint->SetParent(
nullptr );
2634 m_xpath->push(
"classes.class",
"number" );
2636 std::vector<ECLASS> eClasses;
2637 wxXmlNode* classNode = aClasses->GetChildren();
2643 ECLASS eClass( classNode );
2644 std::shared_ptr<NETCLASS> netclass;
2646 if( eClass.
name.CmpNoCase( wxT(
"default" ) ) == 0 )
2656 netclass->SetTrackWidth( INT_MAX );
2657 netclass->SetViaDiameter( INT_MAX );
2658 netclass->SetViaDrill( INT_MAX );
2660 eClasses.emplace_back( eClass );
2664 auto clearanceToDefaultIt = eClass.
clearanceMap.find( wxT(
"0" ) );
2666 if( clearanceToDefaultIt != eClass.
clearanceMap.end() )
2668 netclass->SetClearance( clearanceToDefaultIt->second.ToPcbUnits() );
2672 classNode = classNode->GetNext();
2677 for(
ECLASS& eClass : eClasses )
2679 for(
const auto& [className, pt] : eClass.clearanceMap )
2682 if( className == wxT(
"0" ) )
2688 rule.Printf( wxT(
"(rule \"class %s:%s\"\n"
2689 " (condition \"A.NetClass == '%s' && B.NetClass == '%s'\")\n"
2690 " (constraint clearance (min %smm)))\n" ),
2717 m_xpath->push(
"signals.signal",
"name" );
2720 wxXmlNode* net = aSignals->GetChildren();
2726 bool sawPad =
false;
2730 const wxString& netName =
escapeName( net->GetAttribute(
"name" ) );
2732 std::shared_ptr<NETCLASS> netclass;
2734 if( net->HasAttribute(
"class" ) )
2736 auto netclassIt =
m_classMap.find( net->GetAttribute(
"class" ) );
2742 netclass = netclassIt->second;
2748 m_xpath->Value( netName.c_str() );
2751 wxXmlNode* netItem = net->GetChildren();
2756 const wxString& itemName = netItem->GetName();
2758 if( itemName == wxT(
"wire" ) )
2775 if( netclass && width < netclass->GetTrackWidth() )
2776 netclass->SetTrackWidth( width );
2786 double radiusA = ( mid -
center ).EuclideanNorm();
2787 double radiusB = ( otherMid -
center ).EuclideanNorm();
2790 std::swap( mid, otherMid );
2823 else if( itemName == wxT(
"via" ) )
2835 && layer_front_most != layer_back_most )
2849 double annulus = drillz *
m_rules->rvViaOuter;
2851 kidiam =
KiROUND( drillz + 2 * annulus );
2855 via->SetDrill( drillz );
2861 if( !v.
diam || via_width <= via->GetDrill() )
2863 double annular_width = ( via_width -
via->GetDrill() ) / 2.0;
2873 if( netclass && kidiam < netclass->GetViaDiameter() )
2874 netclass->SetViaDiameter( kidiam );
2879 if( netclass && drillz < netclass->GetViaDrill() )
2880 netclass->SetViaDrill( drillz );
2885 if( layer_front_most ==
F_Cu && layer_back_most ==
B_Cu )
2889 else if( layer_front_most ==
F_Cu || layer_back_most ==
B_Cu )
2900 via->SetLayerPair( layer_front_most, layer_back_most );
2901 via->SetPosition( pos );
2904 via->SetNetCode( netCode );
2910 else if( itemName == wxT(
"contactref" ) )
2912 m_xpath->push(
"contactref" );
2915 const wxString& reference = netItem->GetAttribute(
"element" );
2916 const wxString&
pad = netItem->GetAttribute(
"pad" );
2926 else if( itemName == wxT(
"polygon" ) )
2933 zones.push_back( zone );
2935 if( !zone->GetIsRuleArea() )
2936 zone->SetNetCode( netCode );
2942 netItem = netItem->GetNext();
2945 if( zones.size() && !sawPad )
2949 for(
ZONE* zone : zones )
2959 net = net->GetNext();
2967 const std::vector<INPUT_LAYER_DESC>& aInputLayerDescriptionVector )
2969 std::map<wxString, PCB_LAYER_ID> layer_map;
2974 layer_map.emplace( layer.Name, layerId );
2983 std::vector<INPUT_LAYER_DESC> inputDescs;
2985 for (
const std::pair<const int, ELAYER>& layerPair :
m_eagleLayers )
2987 const ELAYER& eLayer = layerPair.second;
2998 inputDescs.push_back( layerDesc );
3019 bool aIsLibraryCache )
const
3028 if( copperLayer >= 0 )
3029 copperLayers[copperLayer] =
true;
3036 bool required =
false;
3037 LSET permittedLayers;
3039 permittedLayers.
set();
3042 switch( aEagleLayer )
3140 if( aIsLibraryCache )
3148 return {
PCB_LAYER_ID( kiLayer ), permittedLayers, required };
3154 static const wxString
unknown(
"unknown" );
3162 static const int unknown = -1;
3175 if(
auto it =
m_props->find(
"page_width" ); it !=
m_props->end() )
3176 page_width = it->second;
3178 if(
auto it =
m_props->find(
"page_height" ); it !=
m_props->end() )
3179 page_height = it->second;
3181 if( !page_width.
empty() && !page_height.
empty() )
3185 int w = atoi( page_width.
c_str() );
3186 int h = atoi( page_height.
c_str() );
3188 int desired_x = ( w - bbbox.
GetWidth() ) / 2;
3189 int desired_y = ( h - bbbox.
GetHeight() ) / 2;
3200 if( aPath.IsEmpty() )
3201 return wxDateTime::Now().GetValue().GetValue();
3203 wxFileName fn( aPath );
3205 if( fn.IsFileReadable() && fn.GetModificationTime().IsValid() )
3206 return fn.GetModificationTime().GetValue().GetValue();
3235 string filename = (
const char*) aLibPath.char_str( wxConvFile );
3238 wxFileName fn( filename );
3239 wxFFileInputStream stream( fn.GetFullPath() );
3240 wxXmlDocument xmlDocument;
3242 if( !stream.IsOk() || !xmlDocument.Load( stream ) )
3243 THROW_IO_ERROR( wxString::Format(
_(
"Unable to read file '%s'." ), fn.GetFullPath() ) );
3245 doc = xmlDocument.GetRoot();
3247 wxXmlNode* drawing =
MapChildren( doc )[
"drawing"];
3253 m_xpath->push(
"eagle.drawing.layers" );
3254 wxXmlNode* layers = drawingChildren[
"layers"];
3259 m_xpath->push(
"eagle.drawing.library" );
3260 wxXmlNode*
library = drawingChildren[
"library"];
3294 bool aBestEfforts,
const std::map<std::string, UTF8>* aProperties )
3298 init( aProperties );
3306 errorMsg = ioe.
What();
3313 aFootprintNames.Add(
name );
3315 if( !errorMsg.IsEmpty() && !aBestEfforts )
3321 bool aKeepUUID,
const std::map<std::string, UTF8>* aProperties )
3323 init( aProperties );
3332 copy->SetParent(
nullptr );
3339 int minLayerCount = 2;
3341 std::map<wxString, PCB_LAYER_ID>::const_iterator it;
3352 if( ( ordinal + 2 ) > minLayerCount )
3353 minLayerCount = ordinal + 2;
3359 if( ( minLayerCount % 2 ) != 0 )
3362 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