← Back to team overview

kicad-developers team mailing list archive

[PATCH] eagle importer fixes

 

Most of these fixes are from Nickoe, but I added a few fixes to zones and
he asked me to send it to the list.

It fixes at least this bug:
https://bugs.launchpad.net/kicad/+bug/1399737

There are also a handful of fixes for zones like correct filling priority,
clearance, hatching, and thermal relief properties. This patch also fixes
issues where the importer was stripping out white space which was screwing
up a lot of stuff.

Please credit Nickoe if/when this gets committed.

Thanks!
Jon
From 4bb568398dd0f607523dd493508048a7aad6500a Mon Sep 17 00:00:00 2001
From: Jon Neal <reportingsjr@xxxxxxxxx>
Date: Sat, 3 Oct 2015 15:27:18 -0400
Subject: [PATCH] Fixes for eagle importing zones and a few fixme comments for
 later.

---
 pcbnew/eagle_plugin.cpp | 95 ++++++++++++++++++++++++++++++++-----------------
 1 file changed, 63 insertions(+), 32 deletions(-)

diff --git a/pcbnew/eagle_plugin.cpp b/pcbnew/eagle_plugin.cpp
index 6ae725f..90a909b 100644
--- a/pcbnew/eagle_plugin.cpp
+++ b/pcbnew/eagle_plugin.cpp
@@ -785,6 +785,13 @@ struct EPOLYGON
     int         layer;
     opt_double  spacing;
 
+    // KiCad priority is opposite of Eagle rank, that is:
+    //  - Eagle Low rank drawn first
+    //  - KiCad high priority drawn first
+    // So since Eagle has an upper limit we define this, used for the cases
+    // where no rank is specified.
+    static const int    max_priority = 6;
+
     enum {      // for pour
         SOLID,
         HATCH,
@@ -819,6 +826,7 @@ EPOLYGON::EPOLYGON( CPTREE& aPolygon )
     width   = attribs.get<double>( "width" );
     layer   = attribs.get<int>( "layer" );
     spacing = attribs.get_optional<double>( "spacing" );
+    isolate = attribs.get_optional<double>( "isolate" );
 
     opt_string s = attribs.get_optional<string>( "pour" );
     if( s )
@@ -1029,7 +1037,6 @@ void ERULES::parse( CPTREE& aRules )
             rlMinPadTop = parseEagle( attribs.get<string>( "value" ) );
         else if( name == "rlMaxPadTop" )
             rlMaxPadTop = parseEagle( attribs.get<string>( "value" ) );
-
         else if( name == "rvViaOuter" )
             rvViaOuter = attribs.get<double>( "value" );
         else if( name == "rlMinViaOuter" )
@@ -1146,7 +1153,7 @@ BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,  const
         // and is not necessarily utf8.
         string filename = (const char*) aFileName.char_str( wxConvFile );
 
-        read_xml( filename, doc, xml_parser::trim_whitespace | xml_parser::no_comments );
+        read_xml( filename, doc, xml_parser::no_comments );
 
         m_min_trace    = INT_MAX;
         m_min_via      = INT_MAX;
@@ -1385,7 +1392,6 @@ void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics )
 
             wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) );
             wxPoint end(   kicad_x( w.x2 ), kicad_y( w.y2 ) );
-            int     width = kicad( w.width );
 
             if( layer != UNDEFINED_LAYER )
             {
@@ -1409,11 +1415,10 @@ void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics )
 
                 dseg->SetTimeStamp( timeStamp( gr->second ) );
                 dseg->SetLayer( layer );
-                dseg->SetWidth( width );
+                dseg->SetWidth( Millimeter2iu( DEFAULT_PCB_EDGE_THICKNESS ) );
             }
             m_xpath->pop();
         }
-
         else if( gr->first == "text" )
         {
 #if defined(DEBUG)
@@ -1455,10 +1460,8 @@ void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics )
 
                     if( degrees == 90 || t.rot->spin )
                         pcbtxt->SetOrientation( sign * t.rot->degrees * 10 );
-
                     else if( degrees == 180 )
                         align = ETEXT::TOP_RIGHT;
-
                     else if( degrees == 270 )
                     {
                         pcbtxt->SetOrientation( sign * 90 * 10 );
@@ -1511,7 +1514,6 @@ void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics )
             }
             m_xpath->pop();
         }
-
         else if( gr->first == "circle" )
         {
             m_xpath->push( "circle" );
@@ -1533,11 +1535,10 @@ void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics )
             }
             m_xpath->pop();
         }
-
-        // This seems to be a simplified rectangular [copper] zone, cannot find any
-        // net related info on it from the DTD.
         else if( gr->first == "rectangle" )
         {
+            // This seems to be a simplified rectangular [copper] zone, cannot find any
+            // net related info on it from the DTD.
             m_xpath->push( "rectangle" );
 
             ERECT       r( gr->second );
@@ -1568,7 +1569,6 @@ void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics )
 
             m_xpath->pop();
         }
-
         else if( gr->first == "hole" )
         {
             m_xpath->push( "hole" );
@@ -1611,7 +1611,6 @@ void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics )
             pad->SetLayerSet( LSET::AllCuMask() );
             m_xpath->pop();
         }
-
         else if( gr->first == "frame" )
         {
             // picture this
@@ -1879,21 +1878,18 @@ void EAGLE_PLUGIN::orientModuleText( MODULE* m, const EELEMENT& e,
             orient = degrees - m->GetOrientation() / 10;
             txt->SetOrientation( sign * orient * 10 );
         }
-
         else if( degrees == 180 )
         {
             orient = 0 - m->GetOrientation() / 10;
             txt->SetOrientation( sign * orient * 10 );
             align = ETEXT::TOP_RIGHT;
         }
-
         else if( degrees == 270 )
         {
             orient = 90 - m->GetOrientation() / 10;
             align = ETEXT::TOP_RIGHT;
             txt->SetOrientation( sign * orient * 10 );
         }
-
         else
         {
             orient = 90 + degrees - m->GetOrientation() / 10;
@@ -1916,7 +1912,6 @@ void EAGLE_PLUGIN::orientModuleText( MODULE* m, const EELEMENT& e,
             ;
         }
     }
-
     else    // the text is per the original package, sans <attribute>
     {
         double degrees = ( txt->GetOrientation() + m->GetOrientation() ) / 10;
@@ -1930,11 +1925,8 @@ void EAGLE_PLUGIN::orientModuleText( MODULE* m, const EELEMENT& e,
             txt->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
         }
     }
-
-    txt->SetLocalCoord();
 }
 
-
 MODULE* EAGLE_PLUGIN::makeModule( CPTREE& aPackage, const string& aPkgName ) const
 {
     std::auto_ptr<MODULE>   m( new MODULE( m_board ) );
@@ -1989,6 +1981,8 @@ void EAGLE_PLUGIN::packageWire( MODULE* aModule, CPTREE& aTree ) const
         wxPoint end(   kicad_x( w.x2 ), kicad_y( w.y2 ) );
         int     width = kicad( w.width );
 
+        // FIXME: the cap attribute is ignored because kicad can't create lines
+        //        with flat ends.
         EDGE_MODULE* dwg;
         if( !w.curve )
         {
@@ -2117,6 +2111,7 @@ void EAGLE_PLUGIN::packageText( MODULE* aModule, CPTREE& aTree ) const
         txt = &aModule->Value();
     else
     {
+        // FIXME: graphical text items are rotated for some reason.
         txt = new TEXTE_MODULE( aModule );
         aModule->GraphicalItems().PushBack( txt );
     }
@@ -2594,26 +2589,42 @@ void EAGLE_PLUGIN::loadSignals( CPTREE& aSignals )
                     }
 
                     zone->Outline()->CloseLastContour();
-
-                    zone->Outline()->SetHatch( outline_hatch,
-                                               Mils2iu( zone->Outline()->GetDefaultHatchPitchMils() ),
-                                               true );
+                    
+                    // If pour is set the zone should be hatched,
+                    // set the hatch size from the spacing variable.
+                    if( p.pour )
+                    {
+                        zone->Outline()->SetHatch( outline_hatch,
+                                                   *p.spacing,
+                                                   true );
+                    }
 
                     // clearances, etc.
                     zone->SetArcSegmentCount( 32 );     // @todo: should be a constructor default?
                     zone->SetMinThickness( kicad( p.width ) );
-
-                    if( p.spacing )
-                        zone->SetZoneClearance( kicad( *p.spacing ) );
-
-                    if( p.rank )
-                        zone->SetPriority( *p.rank );
+                    
+                    // FIXME: KiCad zones have very rounded corners compared to eagle.
+                    //        This means that isolation amounts that work well in eagle
+                    //        tend to make copper intrude in soldermask free areas around pads.
+                    if( p.isolate )
+                    {
+                        zone->SetZoneClearance( kicad( *p.isolate ) );
+                    }
 
                     // missing == yes per DTD.
                     bool thermals = !p.thermals || *p.thermals;
                     zone->SetPadConnection( thermals ? PAD_ZONE_CONN_THERMAL : PAD_ZONE_CONN_FULL );
+                    if( thermals )
+                    {
+                        // FIXME: eagle calculates dimensions for thermal spokes
+                        //        based on what the zone is connecting to.
+                        //        (i.e. width of spoke is half of the smaller side of an smd pad)
+                        //        This is a basic workaround
+                        zone->SetThermalReliefGap( kicad( p.width + 0.05 ) );
+                        zone->SetThermalReliefCopperBridge( kicad( p.width + 0.05 ) );
+                    }
 
-                    int rank = p.rank ? *p.rank : 0;
+                    int rank = p.rank ? *p.rank : p.max_priority;
                     zone->SetPriority( rank );
                 }
 
@@ -2717,6 +2728,26 @@ LAYER_ID EAGLE_PLUGIN::kicad_layer( int aEagleLayer ) const
 
     else
     {
+/*
+#define FIRST_NON_COPPER_LAYER  16
+#define B_Adhes                 16
+#define F_Adhes                 17
+#define B_Paste                 18
+#define F_Paste                 19
+#define B_SilkS                 20
+#define F_SilkS                 21
+#define B_Mask                  22
+#define F_Mask                  23
+#define Dwgs_User               24
+#define Cmts_User               25
+#define Eco1_User               26
+#define Eco2_User               27
+#define Edge_Cuts               28
+#define LAST_NON_COPPER_LAYER   28
+#define UNUSED_LAYER_29         29
+#define UNUSED_LAYER_30         30
+#define UNUSED_LAYER_31         31
+*/
         // translate non-copper eagle layer to pcbnew layer
         switch( aEagleLayer )
         {
@@ -2844,7 +2875,7 @@ void EAGLE_PLUGIN::cacheLib( const wxString& aLibPath )
             // and is not necessarily utf8.
             string filename = (const char*) aLibPath.char_str( wxConvFile );
 
-            read_xml( filename, doc, xml_parser::trim_whitespace | xml_parser::no_comments );
+            read_xml( filename, doc, xml_parser::no_comments );
 
             // clear the cu map and then rebuild it.
             clear_cu_map();
-- 
2.4.3


Follow ups