Read netclasses when importing Eagle projects.
Also creates a DRU file with the various netclass-to-netclass clearance rules from the Eagle clearance matrix. Fixes https://gitlab.com/kicad/code/kicad/issues/1774
This commit is contained in:
parent
aa85bb27fa
commit
f66654247a
|
@ -278,8 +278,9 @@ wxPoint ConvertArcCenter( const wxPoint& aStart, const wxPoint& aEnd, double aAn
|
|||
|
||||
if( !std::isnormal( dlen ) || !std::isnormal( aAngle ) )
|
||||
{
|
||||
THROW_IO_ERROR(
|
||||
wxString::Format( _( "Invalid Arc with radius %f and angle %f" ), dlen, aAngle ) );
|
||||
THROW_IO_ERROR( wxString::Format( _( "Invalid Arc with radius %f and angle %f" ),
|
||||
dlen,
|
||||
aAngle ) );
|
||||
}
|
||||
|
||||
double dist = dlen / ( 2 * tan( DEG2RAD( aAngle ) / 2 ) );
|
||||
|
@ -919,15 +920,14 @@ EPART::EPART( wxXmlNode* aPart )
|
|||
technology = parseOptionalAttribute<wxString>( aPart, "technology" );
|
||||
value = parseOptionalAttribute<wxString>( aPart, "value" );
|
||||
|
||||
for( auto child = aPart->GetChildren(); child; child = child->GetNext() )
|
||||
for( wxXmlNode* child = aPart->GetChildren(); child; child = child->GetNext() )
|
||||
{
|
||||
|
||||
if( child->GetName() == "attribute" )
|
||||
{
|
||||
std::string aname, avalue;
|
||||
for( auto x = child->GetAttributes(); x; x = x->GetNext() )
|
||||
{
|
||||
|
||||
for( wxXmlAttribute* x = child->GetAttributes(); x; x = x->GetNext() )
|
||||
{
|
||||
if( x->GetName() == "name" )
|
||||
aname = x->GetValue();
|
||||
else if( x->GetName() == "value" )
|
||||
|
@ -940,9 +940,9 @@ EPART::EPART( wxXmlNode* aPart )
|
|||
else if( child->GetName() == "variant" )
|
||||
{
|
||||
std::string aname, avalue;
|
||||
for( auto x = child->GetAttributes(); x; x = x->GetNext() )
|
||||
{
|
||||
|
||||
for( wxXmlAttribute* x = child->GetAttributes(); x; x = x->GetNext() )
|
||||
{
|
||||
if( x->GetName() == "name" )
|
||||
aname = x->GetValue();
|
||||
else if( x->GetName() == "value" )
|
||||
|
@ -1077,7 +1077,7 @@ EDEVICE_SET::EDEVICE_SET( wxXmlNode* aDeviceSet )
|
|||
>
|
||||
*/
|
||||
|
||||
name = parseRequiredAttribute<wxString>(aDeviceSet, "name");
|
||||
name = parseRequiredAttribute<wxString>( aDeviceSet, "name" );
|
||||
prefix = parseOptionalAttribute<wxString>( aDeviceSet, "prefix" );
|
||||
uservalue = parseOptionalAttribute<bool>( aDeviceSet, "uservalue" );
|
||||
|
||||
|
@ -1102,3 +1102,21 @@ EDEVICE_SET::EDEVICE_SET( wxXmlNode* aDeviceSet )
|
|||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
ECLASS::ECLASS( wxXmlNode* aClass )
|
||||
{
|
||||
number = parseRequiredAttribute<wxString>( aClass, "number" );
|
||||
name = parseRequiredAttribute<wxString>( aClass, "name" );
|
||||
|
||||
for( wxXmlNode* child = aClass->GetChildren(); child; child = child->GetNext() )
|
||||
{
|
||||
if( child->GetName() == "clearance" )
|
||||
{
|
||||
wxString to = parseRequiredAttribute<wxString>( child, "class" );
|
||||
ECOORD value = parseRequiredAttribute<ECOORD>( child, "value" );
|
||||
|
||||
clearanceMap[to] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1054,4 +1054,14 @@ struct EDEVICE_SET
|
|||
};
|
||||
|
||||
|
||||
struct ECLASS
|
||||
{
|
||||
wxString number;
|
||||
wxString name;
|
||||
std::map<wxString, ECOORD> clearanceMap;
|
||||
|
||||
ECLASS( wxXmlNode* aClass );
|
||||
};
|
||||
|
||||
|
||||
#endif // _EAGLE_PARSER_H_
|
||||
|
|
|
@ -68,7 +68,7 @@ Load() TODO's
|
|||
#include <trigo.h>
|
||||
#include <math/util.h> // for KiROUND
|
||||
#include <progress_reporter.h>
|
||||
|
||||
#include <project.h>
|
||||
#include <board.h>
|
||||
#include <board_design_settings.h>
|
||||
#include <footprint.h>
|
||||
|
@ -402,13 +402,34 @@ BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
|
|||
designSettings.m_ViasMinAnnularWidth = m_min_annulus;
|
||||
|
||||
if( m_rules->mdWireWire )
|
||||
{
|
||||
NETCLASS* defaultNetclass = designSettings.GetDefault();
|
||||
int clearance = KiROUND( m_rules->mdWireWire );
|
||||
designSettings.m_MinClearance = KiROUND( m_rules->mdWireWire );
|
||||
|
||||
if( clearance < defaultNetclass->GetClearance() )
|
||||
defaultNetclass->SetClearance( clearance );
|
||||
}
|
||||
NETCLASS defaults( "dummy" );
|
||||
|
||||
auto finishNetclass =
|
||||
[&]( NETCLASSPTR netclass )
|
||||
{
|
||||
if( netclass->GetTrackWidth() == INT_MAX )
|
||||
netclass->SetTrackWidth( defaults.GetTrackWidth() );
|
||||
|
||||
if( netclass->GetViaDiameter() == INT_MAX )
|
||||
netclass->SetViaDiameter( defaults.GetViaDiameter() );
|
||||
|
||||
if( netclass->GetViaDrill() == INT_MAX )
|
||||
netclass->SetViaDrill( defaults.GetViaDrill() );
|
||||
};
|
||||
|
||||
finishNetclass( designSettings.GetNetClasses().GetDefault() );
|
||||
|
||||
for( const std::pair<const wxString, NETCLASSPTR>& entry : designSettings.GetNetClasses() )
|
||||
finishNetclass( entry.second );
|
||||
|
||||
m_board->m_LegacyNetclassesLoaded = true;
|
||||
m_board->m_LegacyDesignSettingsLoaded = true;
|
||||
|
||||
fn.SetExt( "kicad_dru" );
|
||||
wxFile rulesFile( fn.GetFullPath(), wxFile::write );
|
||||
rulesFile.Write( m_customRules );
|
||||
|
||||
// should be empty, else missing m_xpath->pop()
|
||||
wxASSERT( m_xpath->Contents().size() == 0 );
|
||||
|
@ -507,6 +528,7 @@ void EAGLE_PLUGIN::loadAllSections( wxXmlNode* aDoc )
|
|||
wxXmlNode* designrules = boardChildren["designrules"];
|
||||
wxXmlNode* layers = drawingChildren["layers"];
|
||||
wxXmlNode* plain = boardChildren["plain"];
|
||||
wxXmlNode* classes = boardChildren["classes"];
|
||||
wxXmlNode* signals = boardChildren["signals"];
|
||||
wxXmlNode* libs = boardChildren["libraries"];
|
||||
wxXmlNode* elems = boardChildren["elements"];
|
||||
|
@ -555,6 +577,7 @@ void EAGLE_PLUGIN::loadAllSections( wxXmlNode* aDoc )
|
|||
m_xpath->push( "board" );
|
||||
|
||||
loadPlain( plain );
|
||||
loadClasses( classes );
|
||||
loadSignals( signals );
|
||||
loadLibraries( libs );
|
||||
loadElements( elems );
|
||||
|
@ -2382,14 +2405,74 @@ void EAGLE_PLUGIN::deleteTemplates()
|
|||
}
|
||||
|
||||
|
||||
void EAGLE_PLUGIN::loadClasses( wxXmlNode* aClasses )
|
||||
{
|
||||
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
||||
|
||||
m_xpath->push( "classes.class", "number" );
|
||||
|
||||
std::vector<ECLASS> eClasses;
|
||||
wxXmlNode* classNode = aClasses->GetChildren();
|
||||
|
||||
while( classNode )
|
||||
{
|
||||
checkpoint();
|
||||
|
||||
ECLASS eClass( classNode );
|
||||
NETCLASSPTR netclass;
|
||||
|
||||
if( eClass.name.CmpNoCase( "default" ) == 0 )
|
||||
{
|
||||
netclass = bds.GetNetClasses().GetDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
netclass.reset( new NETCLASS( eClass.name ) );
|
||||
m_board->GetDesignSettings().GetNetClasses().Add( netclass );
|
||||
}
|
||||
|
||||
netclass->SetTrackWidth( INT_MAX );
|
||||
netclass->SetViaDiameter( INT_MAX );
|
||||
netclass->SetViaDrill( INT_MAX );
|
||||
|
||||
eClasses.emplace_back( eClass );
|
||||
m_classMap[ eClass.number ] = netclass;
|
||||
|
||||
// Get next class
|
||||
classNode = classNode->GetNext();
|
||||
}
|
||||
|
||||
m_customRules = "(version 1)";
|
||||
|
||||
for( ECLASS& eClass : eClasses )
|
||||
{
|
||||
for( std::pair<const wxString&, ECOORD> entry : eClass.clearanceMap )
|
||||
{
|
||||
wxString rule;
|
||||
rule.Printf( "(rule \"class %s:%s\"\n"
|
||||
" (condition \"A.NetClass == '%s' && B.NetClass == '%s'\")\n"
|
||||
" (constraint clearance (min %smm)))\n",
|
||||
eClass.number,
|
||||
entry.first,
|
||||
eClass.name,
|
||||
m_classMap[ entry.first ]->GetName(),
|
||||
StringFromValue( EDA_UNITS::MILLIMETRES, entry.second.ToPcbUnits() ) );
|
||||
|
||||
m_customRules += "\n" + rule;
|
||||
}
|
||||
}
|
||||
|
||||
m_xpath->pop(); // "classes.class"
|
||||
}
|
||||
|
||||
|
||||
void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
|
||||
{
|
||||
ZONES zones; // per net
|
||||
int netCode = 1;
|
||||
|
||||
m_xpath->push( "signals.signal", "name" );
|
||||
|
||||
int netCode = 1;
|
||||
|
||||
// Get the first signal and iterate
|
||||
wxXmlNode* net = aSignals->GetChildren();
|
||||
|
||||
|
@ -2402,7 +2485,18 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
|
|||
zones.clear();
|
||||
|
||||
const wxString& netName = escapeName( net->GetAttribute( "name" ) );
|
||||
m_board->Add( new NETINFO_ITEM( m_board, netName, netCode ) );
|
||||
NETINFO_ITEM* netInfo = new NETINFO_ITEM( m_board, netName, netCode );
|
||||
NETCLASSPTR netclass;
|
||||
|
||||
if( net->HasAttribute( "class" ) )
|
||||
{
|
||||
netclass = m_classMap[ net->GetAttribute( "class" ) ];
|
||||
|
||||
netclass->Add( netName );
|
||||
netInfo->SetNetClass( netclass );
|
||||
}
|
||||
|
||||
m_board->Add( netInfo );
|
||||
|
||||
m_xpath->Value( netName.c_str() );
|
||||
|
||||
|
@ -2435,6 +2529,9 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
|
|||
if( width < m_min_trace )
|
||||
m_min_trace = width;
|
||||
|
||||
if( netclass && width < netclass->GetTrackWidth() )
|
||||
netclass->SetTrackWidth( width );
|
||||
|
||||
if( w.curve )
|
||||
{
|
||||
center = ConvertArcCenter( wxPoint( kicad_x( w.x1 ), kicad_y( w.y1 ) ),
|
||||
|
@ -2538,9 +2635,15 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
|
|||
if( kidiam < m_min_via )
|
||||
m_min_via = kidiam;
|
||||
|
||||
if( netclass && kidiam < netclass->GetViaDiameter() )
|
||||
netclass->SetViaDiameter( kidiam );
|
||||
|
||||
if( drillz < m_min_hole )
|
||||
m_min_hole = drillz;
|
||||
|
||||
if( netclass && drillz < netclass->GetViaDrill() )
|
||||
netclass->SetViaDrill( drillz );
|
||||
|
||||
if( ( kidiam - drillz ) / 2 < m_min_annulus )
|
||||
m_min_annulus = ( kidiam - drillz ) / 2;
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#ifndef EAGLE_PLUGIN_H_
|
||||
#define EAGLE_PLUGIN_H_
|
||||
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
|
@ -25,9 +22,13 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef EAGLE_PLUGIN_H
|
||||
#define EAGLE_PLUGIN_H
|
||||
|
||||
#include <convert_to_biu.h>
|
||||
#include <io_mgr.h>
|
||||
#include <layer_ids.h>
|
||||
#include <netclass.h>
|
||||
#include <plugins/eagle/eagle_parser.h>
|
||||
#include <plugins/common/plugin_common_layer_mapping.h>
|
||||
|
||||
|
@ -218,6 +219,7 @@ private:
|
|||
void loadDesignRules( wxXmlNode* aDesignRules );
|
||||
void loadLayerDefs( wxXmlNode* aLayers );
|
||||
void loadPlain( wxXmlNode* aPlain );
|
||||
void loadClasses( wxXmlNode* aClasses );
|
||||
void loadSignals( wxXmlNode* aSignals );
|
||||
|
||||
/**
|
||||
|
@ -286,6 +288,9 @@ private:
|
|||
std::map<wxString, int> m_eagleLayersIds; ///< Eagle layer ids stored by layer name
|
||||
std::map<wxString, PCB_LAYER_ID> m_layer_map; ///< Map of Eagle layers to KiCad layers
|
||||
|
||||
std::map<wxString, NETCLASSPTR> m_classMap; ///< Eagle class number to KiCad netclass
|
||||
wxString m_customRules;
|
||||
|
||||
ERULES* m_rules; ///< Eagle design rules.
|
||||
XPATH* m_xpath; ///< keeps track of what we are working on within
|
||||
///< XML document during a Load().
|
||||
|
@ -299,8 +304,8 @@ private:
|
|||
///< lookup key is either libname.packagename or simply
|
||||
///< packagename if FootprintLoad() or FootprintEnumberate()
|
||||
|
||||
const PROPERTIES* m_props; ///< passed via Save() or Load(), no ownership, may be NULL.
|
||||
BOARD* m_board; ///< which BOARD is being worked on, no ownership here
|
||||
const PROPERTIES* m_props; ///< passed via Save() or Load(), no ownership, may be NULL.
|
||||
BOARD* m_board; ///< which BOARD is being worked on, no ownership here
|
||||
|
||||
PROGRESS_REPORTER* m_progressReporter; ///< optional; may be nullptr
|
||||
unsigned m_doneCount;
|
||||
|
@ -316,4 +321,4 @@ private:
|
|||
wxDateTime m_mod_time;
|
||||
};
|
||||
|
||||
#endif // EAGLE_PLUGIN_H_
|
||||
#endif // EAGLE_PLUGIN_H
|
||||
|
|
Loading…
Reference in New Issue