56#include <wx/xml/xml.h>
57#include <wx/filename.h>
59#include <wx/wfstream.h>
60#include <wx/txtstrm.h>
95 ECOORD coord( aDistance, unit );
106 T ret = std::max( aMin, aValue );
107 return std::min( aMax, ret );
113static wxString
makeKey(
const wxString& aFirst,
const wxString& aSecond )
115 wxString key = aFirst +
'\x02' + aSecond;
163 wxXmlNode* child = aRules->GetChildren();
169 if( child->GetName() == wxT(
"param" ) )
171 const wxString&
name = child->GetAttribute( wxT(
"name" ) );
172 const wxString& value = child->GetAttribute( wxT(
"value" ) );
174 if(
name == wxT(
"psElongationLong" ) )
176 else if(
name == wxT(
"psElongationOffset" ) )
178 else if(
name == wxT(
"mvStopFrame" ) )
180 else if(
name == wxT(
"mvCreamFrame" ) )
182 else if(
name == wxT(
"mlMinStopFrame" ) )
184 else if(
name == wxT(
"mlMaxStopFrame" ) )
186 else if(
name == wxT(
"mlMinCreamFrame" ) )
188 else if(
name == wxT(
"mlMaxCreamFrame" ) )
190 else if(
name == wxT(
"srRoundness" ) )
192 else if(
name == wxT(
"srMinRoundness" ) )
194 else if(
name == wxT(
"srMaxRoundness" ) )
196 else if(
name == wxT(
"psTop" ) )
197 psTop = wxAtoi( value );
198 else if(
name == wxT(
"psBottom" ) )
200 else if(
name == wxT(
"psFirst" ) )
202 else if(
name == wxT(
"rvPadTop" ) )
204 else if(
name == wxT(
"rlMinPadTop" ) )
206 else if(
name == wxT(
"rlMaxPadTop" ) )
208 else if(
name == wxT(
"rvViaOuter" ) )
210 else if(
name == wxT(
"rlMinViaOuter" ) )
212 else if(
name == wxT(
"rlMaxViaOuter" ) )
214 else if(
name == wxT(
"mdWireWire" ) )
218 child = child->GetNext();
225 m_xpath( new
XPATH() ),
226 m_progressReporter( nullptr ),
228 m_lastProgressCount( 0 ),
230 m_mod_time( wxDateTime::Now() )
232 using namespace std::placeholders;
275 wxFileInputStream input( aFileName );
280 wxTextInputStream
text( input );
282 for(
int i = 0; i < 4; i++ )
287 if(
text.ReadLine().Contains( wxS(
"<eagle" ) ) )
297 const unsigned PROGRESS_DELTA = 50;
319 return VECTOR2I( kz - aTextThickness, kz - aTextThickness );
338 unique_ptr<BOARD> deleter( aAppendToMe ?
nullptr :
m_board );
350 wxFileName fn = aFileName;
353 wxFFileInputStream stream( fn.GetFullPath() );
354 wxXmlDocument xmlDocument;
356 if( !stream.IsOk() || !xmlDocument.Load( stream ) )
359 fn.GetFullPath() ) );
362 doc = xmlDocument.GetRoot();
388 NETCLASS defaults( wxT(
"dummy" ) );
390 auto finishNetclass =
391 [&]( std::shared_ptr<NETCLASS> netclass )
397 if( netclass->GetTrackWidth() == INT_MAX )
400 if( netclass->GetViaDiameter() == INT_MAX )
403 if( netclass->GetViaDrill() == INT_MAX )
407 std::shared_ptr<NET_SETTINGS>& netSettings = bds.
m_NetSettings;
409 finishNetclass( netSettings->m_DefaultNetClass );
411 for(
const auto& [
name, netclass ] : netSettings->m_NetClasses )
412 finishNetclass( netclass );
417 fn.SetExt( wxT(
"kicad_dru" ) );
418 wxFile rulesFile( fn.GetFullPath(), wxFile::write );
426 wxString errmsg = exc.what();
428 errmsg += wxT(
"\n@ " );
446 std::vector<FOOTPRINT*> retval;
449 retval.push_back(
static_cast<FOOTPRINT*
>( footprint->Clone() ) );
485 wxXmlNode* drawing =
MapChildren( aDoc )[
"drawing"];
488 wxXmlNode* board = drawingChildren[
"board"];
491 auto count_children = [
this]( wxXmlNode* aNode )
495 wxXmlNode* child = aNode->GetChildren();
500 child = child->GetNext();
505 wxXmlNode* designrules = boardChildren[
"designrules"];
506 wxXmlNode* layers = drawingChildren[
"layers"];
507 wxXmlNode* plain = boardChildren[
"plain"];
508 wxXmlNode* classes = boardChildren[
"classes"];
509 wxXmlNode* signals = boardChildren[
"signals"];
510 wxXmlNode* libs = boardChildren[
"libraries"];
511 wxXmlNode* elems = boardChildren[
"elements"];
518 count_children( designrules );
519 count_children( layers );
520 count_children( plain );
521 count_children( signals );
522 count_children( elems );
527 libs = libs->GetNext();
531 libs = boardChildren[
"libraries"];
588 wxXmlNode* layerNode = aLayers->GetChildren();
595 ELAYER elayer( layerNode );
601 cu.push_back( elayer );
603 layerNode = layerNode->GetNext();
607 int ki_layer_count = 0;
609 for(
EITER it = cu.begin(); it != cu.end(); ++it, ++ki_layer_count )
611 if( ki_layer_count == 0 )
615 else if( ki_layer_count ==
int( cu.size()-1 ) )
622 m_cu_map[it->number] = ki_layer_count;
631 for(
EITER it = cu.begin(); it != cu.end(); ++it )
648#define DIMENSION_PRECISION DIM_PRECISION::X_XX
659 wxXmlNode* gr = aGraphics->GetChildren();
666 wxString grName = gr->GetName();
668 if( grName == wxT(
"wire" ) )
691 shape->
SetShape( SHAPE_T::SEGMENT );
711 else if( grName == wxT(
"text" ) )
742 if( degrees == 90 || t.
rot->
spin )
754 else if( degrees == 180 )
771 else if( degrees == 270 )
797 if( ( degrees > 0 ) && ( degrees < 90 ) )
801 else if( ( degrees > 90 ) && ( degrees < 180 ) )
806 else if( ( degrees > 180 ) && ( degrees < 270 ) )
811 else if( ( degrees > 270 ) && ( degrees < 360 ) )
870 else if( grName == wxT(
"circle" ) )
889 int outlineRadius = radius + ( width / 2 );
895 VECTOR2I rotatedPoint( outlineRadius, 0 );
903 int innerRadius = radius - ( width / 2 );
909 VECTOR2I rotatedPoint( innerRadius, 0 );
936 else if( grName == wxT(
"rectangle" ) )
956 const int outlineIdx = -1;
975 else if( grName == wxT(
"hole" ) )
991 else if( grName == wxT(
"frame" ) )
995 else if( grName == wxT(
"polygon" ) )
1001 else if( grName == wxT(
"dimension" ) )
1035 dimension->
SetEnd( pt2 );
1040 dimension->
SetUnits( EDA_UNITS::MILLIMETRES );
1070 int newY = ( pt1.
y + pt2.
y ) / 2;
1076 int newX = ( pt1.
x + pt2.
x ) / 2;
1087 dimension->
SetEnd( pt2 );
1091 dimension->
SetUnits( EDA_UNITS::MILLIMETRES );
1097 if(
abs( pt1.
x - pt2.
x ) < 50000 )
1099 int offset = pt3.
x - pt1.
x;
1106 else if(
abs( pt1.
y - pt2.
y ) < 50000 )
1108 int offset = pt3.
y - pt1.
y;
1141 wxString urn = aLib->GetAttribute(
"urn" );
1143 wxString urnOrdinal;
1145 if( !urn.IsEmpty() )
1147 urnOrdinal = urn.AfterLast(
':' );
1151 wxXmlNode* packages =
MapChildren( aLib )[
"packages"];
1163 wxXmlNode*
package = packages->GetChildren();
1169 m_xpath->push(
"package",
"name" );
1171 wxString pack_ref = package->GetAttribute(
"name" );
1173 if( !urnOrdinal.IsEmpty() )
1174 pack_ref += wxS(
"_" ) + urnOrdinal;
1178 m_xpath->Value( pack_ref.ToUTF8() );
1180 wxString key = aLibName ?
makeKey( *aLibName, pack_ref ) : pack_ref;
1182 FOOTPRINT* footprint = makeFootprint( package, pack_ref );
1185 auto r = m_templates.insert( { key, footprint } );
1189 wxString lib = aLibName ? *aLibName : m_lib_path;
1190 const wxString& pkg = pack_ref;
1192 wxString emsg = wxString::Format(
_(
"<package> '%s' duplicated in <library> '%s'" ),
1200 package = package->GetNext();
1212 m_xpath->push(
"libraries.library",
"name" );
1215 wxXmlNode*
library = aLibs->GetChildren();
1219 const wxString& lib_name =
library->GetAttribute(
"name" );
1221 m_xpath->Value( lib_name.c_str() );
1222 loadLibrary(
library, &lib_name );
1235 m_xpath->push(
"elements.element",
"name" );
1239 bool refanceNamePresetInPackageLayout;
1240 bool valueNamePresetInPackageLayout;
1243 wxXmlNode* element = aElements->GetChildren();
1249 if( element->GetName() != wxT(
"element" ) )
1252 element = element->GetNext();
1259 EATTR* nameAttr =
nullptr;
1260 EATTR* valueAttr =
nullptr;
1262 m_xpath->Value( e.
name.c_str() );
1264 wxString packageName = e.
package;
1269 packageName = e.
package + wxS(
"_" ) + libOrdinal.AfterLast(
':' );
1273 auto it = m_templates.find( pkg_key );
1275 if( it == m_templates.end() )
1277 wxString emsg = wxString::Format(
_(
"No '%s' package in library '%s'." ),
1284 m_board->
Add( footprint, ADD_MODE::APPEND );
1292 if( ni != m_pads_to_nets.end() )
1294 const ENET* enet = &ni->second;
1299 refanceNamePresetInPackageLayout =
true;
1300 valueNamePresetInPackageLayout =
true;
1307 refanceNamePresetInPackageLayout =
false;
1311 if( footprint->
GetValue().size() == 0 )
1314 valueNamePresetInPackageLayout =
false;
1317 wxString reference = e.
name;
1323 if( reference.find_first_not_of(
"0123456789" ) != 0 )
1324 reference.Prepend(
"UNK" );
1328 if( reference.find_first_not_of(
"#" ) != 0 )
1329 reference.Prepend(
"UNK" );
1332 if( reference.find_last_not_of(
"0123456789" ) == (reference.Length()-1) )
1333 reference.Append(
"0" );
1341 if( valueNamePresetInPackageLayout )
1344 if( refanceNamePresetInPackageLayout )
1354 m_xpath->push(
"attribute",
"name" );
1364 wxXmlNode* attribute = element->GetChildren();
1368 if( attribute->GetName() != wxT(
"attribute" ) )
1370 attribute = attribute->GetNext();
1374 EATTR a( attribute );
1376 if( a.
name == wxT(
"NAME" ) )
1389 nameAttr->
name = reference;
1391 if( refanceNamePresetInPackageLayout )
1398 if( refanceNamePresetInPackageLayout )
1407 if( refanceNamePresetInPackageLayout )
1410 nameAttr->
name = nameAttr->
name + wxT(
" = " ) + e.
name;
1421 if( refanceNamePresetInPackageLayout )
1431 else if( a.
name == wxT(
"VALUE" ) )
1445 if( valueNamePresetInPackageLayout )
1451 if( valueNamePresetInPackageLayout )
1454 footprint->
SetValue( wxT(
"VALUE" ) );
1458 if( valueNamePresetInPackageLayout )
1472 if( valueNamePresetInPackageLayout )
1484 attribute = attribute->GetNext();
1490 orientFootprintAndText( footprint, e, nameAttr, valueAttr );
1493 element = element->GetNext();
1510 wxLogMessage( wxString::Format(
_(
"Ignoring a polygon since Eagle layer '%s' (%d) "
1517 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( m_board );
1520 zone->SetLayer( layer );
1522 setKeepoutSettingsToZone( zone.get(), p.
layer );
1525 wxXmlNode* vertex = aPolyNode->GetChildren();
1526 std::vector<EVERTEX> vertices;
1534 if( vertex->GetName() == wxT(
"vertex" ) )
1535 vertices.emplace_back( vertex );
1537 vertex = vertex->GetNext();
1543 zone->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::ALWAYS );
1545 zone->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::NEVER );
1547 vertices.push_back( vertices[0] );
1552 for(
size_t i = 0; i < vertices.size() - 1; i++ )
1566 double end_angle = atan2( kicad_y(
v2.
y ) - center.
y, kicad_x(
v2.
x ) - center.
x );
1567 double radius = sqrt( pow( center.
x - kicad_x(
v1.
x ), 2 )
1568 + pow( center.
y - kicad_y(
v1.
y ), 2 ) );
1572 double delta_angle = angle / segCount;
1574 for(
double a = end_angle + angle; fabs( a - end_angle ) > fabs( delta_angle );
1578 KiROUND( radius * sin( a ) ) + center.
y );
1593 wxLogMessage( wxString::Format(
1594 _(
"Skipping a polygon on layer '%s' (%d): outline count is not 1" ),
1600 zone->AddPolygon( polygon.
COutline( 0 ) );
1605 zone->SetIsRuleArea(
true );
1606 zone->SetDoNotAllowVias(
false );
1607 zone->SetDoNotAllowTracks(
false );
1608 zone->SetDoNotAllowPads(
false );
1609 zone->SetDoNotAllowFootprints(
false );
1610 zone->SetDoNotAllowCopperPour(
true );
1611 zone->SetHatchStyle( ZONE_BORDER_DISPLAY_STYLE::NO_HATCH );
1617 zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
1620 zone->SetHatchOrientation(
ANGLE_0 );
1631 zone->SetLocalClearance( 1 );
1635 zone->SetPadConnection( thermals ? ZONE_CONNECTION::THERMAL : ZONE_CONNECTION::FULL );
1648 zone->SetAssignedPriority( rank );
1650 ZONE* zonePtr = zone.release();
1651 m_board->Add( zonePtr, ADD_MODE::APPEND );
1658 const EATTR* aNameAttr,
const EATTR* aValueAttr )
1673 orientFPText( aFootprint, e, &aFootprint->
Reference(), aNameAttr );
1674 orientFPText( aFootprint, e, &aFootprint->
Value(), aValueAttr );
1679 const EATTR* aAttr )
1685 const EATTR& a = *aAttr;
1694 VECTOR2I pos( kicad_x( *a.
x ), kicad_y( *a.
y ) );
1706 int textThickness =
KiROUND( fontz.
y * ratio / 100 );
1711 fontz = kicad_fontsize( *a.
size, textThickness );
1737 if( degrees == 90 || degrees == 0 || spin )
1741 else if( degrees == 180 )
1746 else if( degrees == 270 )
1815 if( ( !aFPText->
IsMirrored() && (
abs( degrees ) == 180 ||
abs( degrees ) == 270 ) )
1816 || ( aFPText->
IsMirrored() && ( degrees == 360 ) ) )
1828 std::unique_ptr<FOOTPRINT> m = std::make_unique<FOOTPRINT>( m_board );
1831 fpID.
Parse( aPkgName,
true );
1835 wxXmlNode* packageItem = aPackage->GetChildren();
1840 m.get()->Value().SetLayer( layer );
1842 while( packageItem )
1844 const wxString& itemName = packageItem->GetName();
1846 if( itemName == wxT(
"description" ) )
1849 m->SetLibDescription( descr );
1851 else if( itemName == wxT(
"wire" ) )
1852 packageWire( m.get(), packageItem );
1853 else if( itemName == wxT(
"pad" ) )
1854 packagePad( m.get(), packageItem );
1855 else if( itemName == wxT(
"text" ) )
1856 packageText( m.get(), packageItem );
1857 else if( itemName == wxT(
"rectangle" ) )
1858 packageRectangle( m.get(), packageItem );
1859 else if( itemName == wxT(
"polygon" ) )
1860 packagePolygon( m.get(), packageItem );
1861 else if( itemName == wxT(
"circle" ) )
1862 packageCircle( m.get(), packageItem );
1863 else if( itemName == wxT(
"hole" ) )
1864 packageHole( m.get(), packageItem,
false );
1865 else if( itemName == wxT(
"smd" ) )
1866 packageSMD( m.get(), packageItem );
1868 packageItem = packageItem->GetNext();
1885 wxLogMessage( wxString::Format(
_(
"Ignoring a wire since Eagle layer '%s' (%d) "
1924 dwg =
new PCB_SHAPE( aFootprint, SHAPE_T::SEGMENT );
1931 dwg =
new PCB_SHAPE( aFootprint, SHAPE_T::ARC );
1944 aFootprint->
Add( dwg );
1955 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
1956 transferPad( e,
pad.get() );
1959 shape = m_rules->psFirst;
1961 shape = m_rules->psTop;
1963 shape = m_rules->psBottom;
1965 pad->SetDrillSize(
VECTOR2I( eagleDrillz, eagleDrillz ) );
1968 if( eagleDrillz < m_min_hole )
1969 m_min_hole = eagleDrillz;
1983 pad->SetShape( PAD_SHAPE::CIRCLE );
1987 pad->SetShape( PAD_SHAPE::CHAMFERED_RECT );
1989 pad->SetChamferRectRatio( 1 - M_SQRT1_2 );
1993 pad->SetShape( PAD_SHAPE::OVAL );
1997 pad->SetShape( PAD_SHAPE::RECTANGLE );
2001 pad->SetShape( PAD_SHAPE::OVAL );
2017 double drillz =
pad->GetDrillSize().x;
2018 double annulus = drillz * m_rules->rvPadTop;
2019 annulus =
eagleClamp( m_rules->rlMinPadTop, annulus, m_rules->rlMaxPadTop );
2020 int diameter =
KiROUND( drillz + 2 * annulus );
2024 if(
pad->GetShape() == PAD_SHAPE::OVAL )
2028 sz.
x = ( sz.
x * ( 100 + m_rules->psElongationLong ) ) / 100;
2033 int offset =
KiROUND( ( sz.
x - sz.
y ) / 2.0 );
2044 if(
pad->GetSizeX() > 0 &&
pad->GetSizeY() > 0 )
2046 aFootprint->
Add(
pad.release() );
2050 wxLogError(
_(
"Invalid zero-sized pad ignored in\nfile: %s" ), m_board->GetFileName() );
2062 wxLogMessage( wxString::Format(
_(
"Ignoring a text since Eagle layer '%s' (%d) "
2070 if( t.
text.Upper() == wxT(
">NAME" ) && aFootprint->
GetReference().IsEmpty() )
2074 textItem->
SetText( wxT(
"REF**" ) );
2076 else if( t.
text.Upper() == wxT(
">VALUE" ) && aFootprint->
GetValue().IsEmpty() )
2078 textItem = &aFootprint->
Value();
2084 textItem =
new PCB_TEXT( aFootprint );
2085 aFootprint->
Add( textItem );
2090 VECTOR2I pos( kicad_x( t.
x ), kicad_y( t.
y ) );
2113 if( degrees == 90 || t.
rot->
spin )
2117 else if( degrees == 180 )
2121 else if( degrees == 270 )
2185 ZONE* zone =
new ZONE( aFootprint );
2186 aFootprint->
Add( zone, ADD_MODE::APPEND );
2188 setKeepoutSettingsToZone( zone, r.
layer );
2190 const int outlineIdx = -1;
2198 VECTOR2I center( ( kicad_x( r.
x1 ) + kicad_x( r.
x2 ) ) / 2,
2199 ( kicad_y( r.
y1 ) + kicad_y( r.
y2 ) ) / 2 );
2212 wxLogMessage( wxString::Format(
_(
"Ignoring a rectangle since Eagle layer '%s' (%d) "
2220 aFootprint->
Add( dwg );
2226 std::vector<VECTOR2I> pts;
2231 pts.push_back( start );
2232 pts.emplace_back( kicad_x( r.
x2 ), kicad_y( r.
y1 ) );
2233 pts.emplace_back( kicad_x( r.
x2 ), kicad_y( r.
y2 ) );
2234 pts.push_back( end );
2251 std::vector<VECTOR2I> pts;
2254 wxXmlNode* vertex = aTree->GetChildren();
2255 std::vector<EVERTEX> vertices;
2263 if( vertex->GetName() == wxT(
"vertex" ) )
2264 vertices.emplace_back( vertex );
2266 vertex = vertex->GetNext();
2269 vertices.push_back( vertices[0] );
2271 for(
size_t i = 0; i < vertices.size() - 1; i++ )
2276 pts.emplace_back( kicad_x(
v1.
x ), kicad_y(
v1.
y ) );
2285 double end_angle = atan2( kicad_y(
v2.
y ) - center.
y, kicad_x(
v2.
x ) - center.
x );
2286 double radius = sqrt( pow( center.
x - kicad_x(
v1.
x ), 2 )
2287 + pow( center.
y - kicad_y(
v1.
y ), 2 ) );
2295 double delta = angle / segCount;
2297 for(
double a = end_angle + angle; fabs( a - end_angle ) > fabs(
delta ); a -=
delta )
2313 ZONE* zone =
new ZONE( aFootprint );
2314 aFootprint->
Add( zone, ADD_MODE::APPEND );
2316 setKeepoutSettingsToZone( zone, p.
layer );
2329 wxLogMessage( wxString::Format(
_(
"Ignoring a polygon since Eagle layer '%s' (%d) "
2337 aFootprint->
Add( dwg );
2363 ZONE* zone =
new ZONE( aFootprint );
2364 aFootprint->
Add( zone, ADD_MODE::APPEND );
2366 setKeepoutSettingsToZone( zone, e.
layer );
2369 VECTOR2I center( kicad_x( e.
x ), kicad_y( e.
y ) );
2370 int outlineRadius = radius + ( width / 2 );
2376 VECTOR2I rotatedPoint( outlineRadius, 0 );
2384 int innerRadius = radius - ( width / 2 );
2390 VECTOR2I rotatedPoint( innerRadius, 0 );
2405 wxLogMessage( wxString::Format(
_(
"Ignoring a circle since Eagle layer '%s' (%d) "
2417 radius = radius / 2;
2421 aFootprint->
Add( gr );
2424 switch( (
int) layer )
2453 pad->SetShape( PAD_SHAPE::CIRCLE );
2454 pad->SetAttribute( PAD_ATTRIB::NPTH );
2461 VECTOR2I padpos( kicad_x( e.
x ), kicad_y( e.
y ) );
2466 pad->SetPosition( padpos );
2475 pad->SetDrillSize( sz );
2492 transferPad( e,
pad );
2494 pad->SetShape( PAD_SHAPE::RECTANGLE );
2495 pad->SetAttribute( PAD_ATTRIB::SMD );
2498 pad->SetSize( padSize );
2499 pad->SetLayer( layer );
2505 pad->SetLayerSet( front );
2506 else if( layer ==
B_Cu )
2507 pad->SetLayerSet( back );
2509 int minPadSize = std::min( padSize.
x, padSize.
y );
2513 eagleClamp( m_rules->srMinRoundness * 2, (
int) ( minPadSize * m_rules->srRoundness ),
2514 m_rules->srMaxRoundness * 2 );
2518 double roundRatio = (double) roundRadius / minPadSize / 2.0;
2522 roundRatio = std::fmax( *e.
roundness / 200.0, roundRatio );
2524 pad->SetShape( PAD_SHAPE::ROUNDRECT );
2525 pad->SetRoundRectRadiusRatio( roundRatio );
2534 pad->SetLocalSolderPasteMargin( -
eagleClamp( m_rules->mlMinCreamFrame,
2535 (
int) ( m_rules->mvCreamFrame * minPadSize ),
2536 m_rules->mlMaxCreamFrame ) );
2542 pad->SetLayerSet(
pad->GetLayerSet().set(
F_Mask,
false ) );
2543 else if( layer ==
B_Cu )
2544 pad->SetLayerSet(
pad->GetLayerSet().set(
B_Mask,
false ) );
2551 pad->SetLayerSet(
pad->GetLayerSet().set(
F_Paste,
false ) );
2552 else if( layer ==
B_Cu )
2553 pad->SetLayerSet(
pad->GetLayerSet().set(
B_Paste,
false ) );
2562 VECTOR2I padPos( kicad_x( aEaglePad.
x ), kicad_y( aEaglePad.
y ) );
2569 (
int) ( m_rules->mvStopFrame * std::min( padSize.
x, padSize.
y ) ),
2570 m_rules->mlMaxStopFrame ) );
2577 wxCHECK( footprint, );
2585 for(
const auto& [
name, footprint ] : m_templates )
2587 footprint->SetParent(
nullptr );
2591 m_templates.clear();
2603 m_xpath->push(
"classes.class",
"number" );
2605 std::vector<ECLASS> eClasses;
2606 wxXmlNode* classNode = aClasses->GetChildren();
2612 ECLASS eClass( classNode );
2613 std::shared_ptr<NETCLASS> netclass;
2615 if( eClass.
name.CmpNoCase( wxT(
"default" ) ) == 0 )
2625 netclass->SetTrackWidth( INT_MAX );
2626 netclass->SetViaDiameter( INT_MAX );
2627 netclass->SetViaDrill( INT_MAX );
2629 eClasses.emplace_back( eClass );
2630 m_classMap[ eClass.
number ] = netclass;
2633 classNode = classNode->GetNext();
2636 m_customRules = wxT(
"(version 1)" );
2638 for(
ECLASS& eClass : eClasses )
2640 for( std::pair<const wxString&, ECOORD> entry : eClass.clearanceMap )
2642 if( m_classMap[ entry.first ] !=
nullptr )
2645 rule.Printf( wxT(
"(rule \"class %s:%s\"\n"
2646 " (condition \"A.NetClass == '%s' && B.NetClass == '%s'\")\n"
2647 " (constraint clearance (min %smm)))\n" ),
2651 m_classMap[ entry.first ]->GetName(),
2654 m_customRules += wxT(
"\n" ) + rule;
2672 m_xpath->push(
"signals.signal",
"name" );
2675 wxXmlNode* net = aSignals->GetChildren();
2681 bool sawPad =
false;
2685 const wxString& netName =
escapeName( net->GetAttribute(
"name" ) );
2687 std::shared_ptr<NETCLASS> netclass;
2689 if( net->HasAttribute(
"class" ) )
2691 auto netclassIt = m_classMap.find( net->GetAttribute(
"class" ) );
2693 if( netclassIt != m_classMap.end() )
2695 m_board->GetDesignSettings().m_NetSettings->m_NetClassPatternAssignments.push_back(
2696 { std::make_unique<EDA_COMBINED_MATCHER>( netName,
CTX_NETCLASS ),
2697 netclassIt->second->GetName() } );
2700 netclass = netclassIt->second;
2704 m_board->Add( netInfo );
2706 m_xpath->Value( netName.c_str() );
2709 wxXmlNode* netItem = net->GetChildren();
2714 const wxString& itemName = netItem->GetName();
2716 if( itemName == wxT(
"wire" ) )
2718 m_xpath->push(
"wire" );
2730 if( width < m_min_trace )
2731 m_min_trace = width;
2733 if( netclass && width < netclass->GetTrackWidth() )
2734 netclass->SetTrackWidth( width );
2739 double radius = sqrt( pow( center.
x - kicad_x( w.
x1 ), 2 ) +
2740 pow( center.
y - kicad_y( w.
y1 ), 2 ) );
2747 if(
abs( radiusA - radius ) >
abs( radiusB - radius ) )
2748 std::swap( mid, otherMid );
2759 m_board->Add( arc );
2771 m_board->Add( track );
2781 else if( itemName == wxT(
"via" ) )
2783 m_xpath->push(
"via" );
2793 && layer_front_most != layer_back_most )
2798 m_board->Add(
via );
2803 via->SetWidth( kidiam );
2807 double annulus = drillz * m_rules->rvViaOuter;
2808 annulus =
eagleClamp( m_rules->rlMinViaOuter, annulus,
2809 m_rules->rlMaxViaOuter );
2810 kidiam =
KiROUND( drillz + 2 * annulus );
2811 via->SetWidth( kidiam );
2814 via->SetDrill( drillz );
2818 if( !v.
diam ||
via->GetWidth() <=
via->GetDrill() )
2822 (
double) (
via->GetWidth() / 2 -
via->GetDrill() ),
2823 m_rules->rlMaxViaOuter );
2824 via->SetWidth( drillz + 2 * annulus );
2827 if( kidiam < m_min_via )
2830 if( netclass && kidiam < netclass->GetViaDiameter() )
2831 netclass->SetViaDiameter( kidiam );
2833 if( drillz < m_min_hole )
2834 m_min_hole = drillz;
2836 if( netclass && drillz < netclass->GetViaDrill() )
2837 netclass->SetViaDrill( drillz );
2839 if( ( kidiam - drillz ) / 2 < m_min_annulus )
2840 m_min_annulus = ( kidiam - drillz ) / 2;
2842 if( layer_front_most ==
F_Cu && layer_back_most ==
B_Cu )
2844 via->SetViaType( VIATYPE::THROUGH );
2851 via->SetViaType( VIATYPE::MICROVIA );
2855 via->SetViaType( VIATYPE::BLIND_BURIED );
2858 VECTOR2I pos( kicad_x( v.
x ), kicad_y( v.
y ) );
2860 via->SetLayerPair( layer_front_most, layer_back_most );
2861 via->SetPosition( pos );
2864 via->SetNetCode( netCode );
2870 else if( itemName == wxT(
"contactref" ) )
2872 m_xpath->push(
"contactref" );
2875 const wxString& reference = netItem->GetAttribute(
"element" );
2876 const wxString&
pad = netItem->GetAttribute(
"pad" );
2879 m_pads_to_nets[ key ] =
ENET( netCode, netName );
2886 else if( itemName == wxT(
"polygon" ) )
2888 m_xpath->push(
"polygon" );
2889 auto* zone = loadPolygon( netItem );
2893 zones.push_back( zone );
2895 if( !zone->GetIsRuleArea() )
2896 zone->SetNetCode( netCode );
2902 netItem = netItem->GetNext();
2905 if( zones.size() && !sawPad )
2909 for(
ZONE* zone : zones )
2920 net = net->GetNext();
2928 const std::vector<INPUT_LAYER_DESC>& aInputLayerDescriptionVector )
2930 std::map<wxString, PCB_LAYER_ID> layer_map;
2934 PCB_LAYER_ID layerId = std::get<0>( defaultKicadLayer( eagle_layer_id( layer.Name ) ) );
2935 layer_map.emplace( layer.Name, layerId );
2944 std::vector<INPUT_LAYER_DESC> inputDescs;
2946 for (
const std::pair<const int, ELAYER>& layerPair : m_eagleLayers )
2948 const ELAYER& eLayer = layerPair.second;
2952 defaultKicadLayer( eLayer.
number, aIsLibraryCache );
2959 inputDescs.push_back( layerDesc );
2962 if( m_progressReporter &&
dynamic_cast<wxWindow*
>( m_progressReporter ) )
2963 dynamic_cast<wxWindow*
>( m_progressReporter )->Hide();
2965 m_layer_map = m_layer_mapping_handler( inputDescs );
2967 if( m_progressReporter &&
dynamic_cast<wxWindow*
>( m_progressReporter ))
2968 dynamic_cast<wxWindow*
>( m_progressReporter )->Show();
2974 auto result = m_layer_map.find( eagle_layer_name( aEagleLayer ) );
2975 return result == m_layer_map.end() ?
UNDEFINED_LAYER : result->second;
2980 bool aIsLibraryCache )
const
2983 if( aEagleLayer >= 1 && aEagleLayer <
int(
arrayDim( m_cu_map ) ) )
2987 for(
int copperLayer : m_cu_map )
2989 if( copperLayer >= 0 )
2990 copperLayers[copperLayer] =
true;
2993 return {
PCB_LAYER_ID( m_cu_map[aEagleLayer] ), copperLayers,
true };
2997 bool required =
false;
2998 LSET permittedLayers;
3000 permittedLayers.set();
3003 switch( aEagleLayer )
3101 if( aIsLibraryCache )
3109 return {
PCB_LAYER_ID( kiLayer ), permittedLayers, required };
3115 static const wxString
unknown(
"unknown" );
3116 auto it = m_eagleLayers.find( aLayer );
3117 return it == m_eagleLayers.end() ?
unknown : it->second.name;
3123 static const int unknown = -1;
3124 auto it = m_eagleLayersIds.find( aLayerName );
3125 return it == m_eagleLayersIds.end() ?
unknown : it->second;
3136 if( m_props->Value(
"page_width", &page_width ) &&
3137 m_props->Value(
"page_height", &page_height ) )
3139 BOX2I bbbox = m_board->GetBoardEdgesBoundingBox();
3141 int w = atoi( page_width.
c_str() );
3142 int h = atoi( page_height.
c_str() );
3144 int desired_x = ( w - bbbox.
GetWidth() ) / 2;
3145 int desired_y = ( h - bbbox.
GetHeight() ) / 2;
3147 m_board->Move(
VECTOR2I( desired_x - bbbox.
GetX(), desired_y - bbbox.
GetY() ) );
3156 if( aPath.IsEmpty() )
3157 return wxDateTime::Now();
3159 wxFileName fn( aPath );
3161 if( fn.IsFileReadable() )
3162 return fn.GetModificationTime();
3164 return wxDateTime( 0.0 );
3172 wxDateTime modtime = getModificationTime( aLibPath );
3177 bool load = !m_mod_time.IsValid() || !modtime.IsValid() || m_mod_time != modtime;
3179 if( aLibPath != m_lib_path || load )
3189 m_lib_path = aLibPath;
3194 string filename = (
const char*) aLibPath.char_str( wxConvFile );
3197 wxFileName fn( filename );
3198 wxFFileInputStream stream( fn.GetFullPath() );
3199 wxXmlDocument xmlDocument;
3201 if( !stream.IsOk() || !xmlDocument.Load( stream ) )
3204 fn.GetFullPath() ) );
3207 doc = xmlDocument.GetRoot();
3209 wxXmlNode* drawing =
MapChildren( doc )[
"drawing"];
3215 m_xpath->push(
"eagle.drawing.layers" );
3216 wxXmlNode* layers = drawingChildren[
"layers"];
3217 loadLayerDefs( layers );
3218 mapEagleLayersToKicad(
true );
3221 m_xpath->push(
"eagle.drawing.library" );
3222 wxXmlNode*
library = drawingChildren[
"library"];
3224 loadLibrary(
library,
nullptr );
3227 m_mod_time = modtime;
3258 init( aProperties );
3262 cacheLib( aLibraryPath );
3266 errorMsg = ioe.
What();
3272 for(
const auto& [
name, footprint ] : m_templates )
3273 aFootprintNames.Add(
name );
3275 if( !errorMsg.IsEmpty() && !aBestEfforts )
3281 const wxString& aFootprintName,
bool aKeepUUID,
3284 init( aProperties );
3285 cacheLib( aLibraryPath );
3286 auto it = m_templates.find( aFootprintName );
3288 if( it == m_templates.end() )
3293 copy->SetParent(
nullptr );
3300 int minLayerCount = 2;
3302 std::map<wxString, PCB_LAYER_ID>::const_iterator it;
3304 for( it = m_layer_map.begin(); it != m_layer_map.end(); ++it )
3309 && ( layerId + 2 ) > minLayerCount )
3310 minLayerCount = layerId + 2;
3316 if( ( minLayerCount % 2 ) != 0 )
3319 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
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
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.
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
void SetFileName(const wxString &aFileName)
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
bool m_LegacyNetclassesLoaded
True if netclasses were loaded from the file.
void SetCopperLayerCount(int aCount)
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
size_type GetHeight() const
size_type GetWidth() const
void SetCenter(const VECTOR2I &aCenter)
SHAPE_POLY_SET & GetPolyShape()
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 VECTOR2I & GetTextPos() const
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)
virtual void SetVisible(bool aVisible)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
VECTOR2I GetTextSize() const
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
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 RegisterLayerMappingCallback(LAYER_MAPPING_HANDLER aLayerMappingHandler)
Register a different handler to be called when mapping of input layers to KiCad layers occurs.
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
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
LSET is a set of PCB_LAYER_IDs.
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
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 ...
T & Get()
Return a reference to the value of the attribute assuming it is available.
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() 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.
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 FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, bool aBestEfforts, const STRING_UTF8_MAP *aProperties=nullptr) override
Return a list of footprint names contained within the library at aLibraryPath.
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::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...
void loadLibraries(wxXmlNode *aLibs)
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
FOOTPRINT * FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, bool aKeepUUID=false, const STRING_UTF8_MAP *aProperties=nullptr) override
Load a footprint having aFootprintName from the aLibraryPath containing a library format that this PC...
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)
static wxDateTime getModificationTime(const wxString &aPath)
get a file's or dir's modification time.
int m_min_annulus
smallest via annulus we find on Load(), in BIU.
void loadLayerDefs(wxXmlNode *aLayers)
void init(const STRING_UTF8_MAP *aProperties)
initialize PLUGIN like a constructor would, and futz with fresh BOARD if needed.
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const STRING_UTF8_MAP *aProperties=nullptr, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
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
A base class that BOARD loading and saving plugins should derive from.
BOARD * m_board
The board BOARD being worked on, no ownership here.
const STRING_UTF8_MAP * m_props
Properties passed via Save() or Load(), no ownership, may be NULL.
virtual bool CanReadBoard(const wxString &aFileName) const
Checks if this PCB_IO can read the specified board file.
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 SetWidth(int aWidth)
void SetEnd(const VECTOR2I &aEnd)
void SetPosition(const VECTOR2I &aPos) override
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void Report(const wxString &aMessage)=0
Display aMessage in the progress bar dialog.
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
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
A name/value tuple with unique names and optional values.
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
Keep track of what we are working on within a PTREE.
void push(const char *aPathSegment, const char *aAttribute="")
wxString Contents()
return the contents of the XPATH as a single string
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.
void SetDoNotAllowCopperPour(bool aEnable)
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 SetDoNotAllowVias(bool aEnable)
void SetLayerSet(LSET aLayerSet) override
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)
static int GetDefaultHatchPitch()
NODE_MAP MapChildren(wxXmlNode *aCurrentNode)
Provide an easy access to the children of an XML node via their names.
wxString escapeName(const wxString &aNetName)
Interprets special characters in Eagle text and converts them to KiCAD notation.
wxString interpretText(const wxString &aText)
Translates Eagle special text reference to a KiCad variable reference.
VECTOR2I ConvertArcCenter(const VECTOR2I &aStart, const VECTOR2I &aEnd, double aAngle)
wxString convertDescription(wxString aDescr)
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
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
#define THROW_IO_ERROR(msg)
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
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)
Returns the string from aValue according to aUnits (inch, mm ...) for display.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
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.
long long int value
Unit used for the value field.
constexpr int mmToIU(double mm) const
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.
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.
VECTOR2I v2(1, 0)
Test suite for KiCad math code.
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)
double GetLineLength(const VECTOR2I &aPointA, const VECTOR2I &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
double EuclideanNorm(const VECTOR2I &vector)
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
#define ZONE_THICKNESS_MIN_VALUE_MM