Loading include/wxPcbStruct.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -1340,7 +1340,7 @@ public: void ShowTargetOptionsDialog( PCB_TARGET* aTarget, wxDC* DC ); void ShowTargetOptionsDialog( PCB_TARGET* aTarget, wxDC* DC ); // Graphic segments type DRAWSEGMENT handling: // Graphic segments type DRAWSEGMENT handling: DRAWSEGMENT* Begin_DrawSegment( DRAWSEGMENT* Segment, int shape, wxDC* DC ); DRAWSEGMENT* Begin_DrawSegment( DRAWSEGMENT* Segment, STROKE_T shape, wxDC* DC ); void End_Edge( DRAWSEGMENT* Segment, wxDC* DC ); void End_Edge( DRAWSEGMENT* Segment, wxDC* DC ); void Delete_Segment_Edge( DRAWSEGMENT* Segment, wxDC* DC ); void Delete_Segment_Edge( DRAWSEGMENT* Segment, wxDC* DC ); void Delete_Drawings_All_Layer( int aLayer ); void Delete_Drawings_All_Layer( int aLayer ); Loading pcbnew/class_drawsegment.cpp +45 −35 Original line number Original line Diff line number Diff line Loading @@ -124,6 +124,10 @@ const wxPoint DRAWSEGMENT::GetArcEnd() const // m_Start is the arc centre // m_Start is the arc centre endPoint = m_End; // m_End = start point of arc endPoint = m_End; // m_End = start point of arc RotatePoint( &endPoint, m_Start, -m_Angle ); RotatePoint( &endPoint, m_Start, -m_Angle ); break; default: ; } } return endPoint; // after rotation, the end of the arc. return endPoint; // after rotation, the end of the arc. Loading Loading @@ -429,8 +433,11 @@ EDA_RECT DRAWSEGMENT::GetBoundingBox() const } } bbox.SetEnd( p_end ); bbox.SetEnd( p_end ); break; } } break; default: ; } } bbox.Inflate( ((m_Width+1) / 2) + 1 ); bbox.Inflate( ((m_Width+1) / 2) + 1 ); Loading Loading @@ -520,6 +527,9 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect ) const if( aRect.Contains( GetEnd() ) ) if( aRect.Contains( GetEnd() ) ) return true; return true; break; break; default: ; } } return false; return false; } } Loading pcbnew/class_drawsegment.h +14 −14 Original line number Original line Diff line number Diff line Loading @@ -47,7 +47,7 @@ protected: wxPoint m_Start; ///< Line start point or Circle and Arc center wxPoint m_Start; ///< Line start point or Circle and Arc center wxPoint m_End; ///< Line end point or circle and arc start point wxPoint m_End; ///< Line end point or circle and arc start point int m_Shape; ///< Shape: line, Circle, Arc STROKE_T m_Shape; ///< Shape: line, Circle, Arc int m_Type; ///< Used in complex associations ( Dimensions.. ) int m_Type; ///< Used in complex associations ( Dimensions.. ) double m_Angle; ///< Used only for Arcs: Arc angle in 1/10 deg double m_Angle; ///< Used only for Arcs: Arc angle in 1/10 deg wxPoint m_BezierC1; ///< Bezier Control Point 1 wxPoint m_BezierC1; ///< Bezier Control Point 1 Loading Loading @@ -83,8 +83,8 @@ public: void SetType( int aType ) { m_Type = aType; } void SetType( int aType ) { m_Type = aType; } int GetType() const { return m_Type; } int GetType() const { return m_Type; } void SetShape( int aShape ) { m_Shape = aShape; } void SetShape( STROKE_T aShape ) { m_Shape = aShape; } int GetShape() const { return m_Shape; } STROKE_T GetShape() const { return m_Shape; } void SetBezControl1( const wxPoint& aPoint ) { m_BezierC1 = aPoint; } void SetBezControl1( const wxPoint& aPoint ) { m_BezierC1 = aPoint; } const wxPoint& GetBezControl1() const { return m_BezierC1; } const wxPoint& GetBezControl1() const { return m_BezierC1; } Loading pcbnew/class_module.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -294,6 +294,11 @@ public: m_Value->m_Text = aValue; m_Value->m_Text = aValue; } } /// read/write accessors: TEXTE_MODULE& Value() { return *m_Value; } TEXTE_MODULE& Reference() { return *m_Reference; } /** /** * Function FindPadByName * Function FindPadByName * returns a D_PAD* with a matching name. Note that names may not be * returns a D_PAD* with a matching name. Note that names may not be Loading pcbnew/eagle_plugin.cpp +556 −27 Original line number Original line Diff line number Diff line Loading @@ -59,6 +59,8 @@ our error message. #include <common.h> #include <common.h> #include <macros.h> #include <macros.h> #include <fctsys.h> #include <fctsys.h> #include <trigo.h> #include <class_board.h> #include <class_board.h> #include <class_module.h> #include <class_module.h> #include <class_track.h> #include <class_track.h> Loading @@ -70,17 +72,75 @@ using namespace boost::property_tree; typedef EAGLE_PLUGIN::BIU BIU; typedef EAGLE_PLUGIN::BIU BIU; typedef PTREE::const_assoc_iterator CA_ITER; typedef PTREE::const_assoc_iterator CA_ITER; typedef PTREE::const_iterator CITER; typedef PTREE::const_iterator CITER; typedef std::pair<CA_ITER, CA_ITER> CA_ITER_RANGE; typedef MODULE_MAP::iterator MODULE_ITER; typedef MODULE_MAP::iterator MODULE_ITER; typedef MODULE_MAP::const_iterator MODULE_CITER; typedef MODULE_MAP::const_iterator MODULE_CITER; typedef boost::optional<std::string> opt_string; typedef boost::optional<int> opt_int; typedef boost::optional<double> opt_double; typedef boost::optional<CPTREE&> opt_cptree; /// Eagle wire struct EWIRE { double x1; double y1; double x2; double y2; double width; int layer; }; /// Eagle circle struct ECIRCLE { double x; double y; double radius; double width; int layer; }; /// Eagle rotation struct EROT { bool mirror; bool spin; double degrees; }; typedef boost::optional<EROT> opt_erot; /// Eagle "attribute" XML element, no foolin'. struct EATTR { std::string name; opt_string value; opt_double x; opt_double y; opt_double size; // opt_int layer; opt_double ratio; opt_erot erot; opt_int display; enum { // for 'display' field above Off, VALUE, NAME, BOTH, }; }; /// Assemble a MODULE factory key as a simple concatonation of library name and /// package name, using '\x02' as a separator. static inline std::string makePkgKey( const std::string& aLibName, const std::string& aPkgName ) static inline std::string makePkgKey( const std::string& aLibName, const std::string& aPkgName ) { { // The MODULE factory key is a simple concatonation of library name and // package name, using '\x02' as a separator. std::string key = aLibName + '\x02' + aPkgName; std::string key = aLibName + '\x02' + aPkgName; return key; return key; } } Loading Loading @@ -164,7 +224,7 @@ void EAGLE_PLUGIN::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* a void EAGLE_PLUGIN::init( PROPERTIES* aProperties ) void EAGLE_PLUGIN::init( PROPERTIES* aProperties ) { { m_modules.clear(); m_templates.clear(); m_board = NULL; m_board = NULL; m_props = aProperties; m_props = aProperties; Loading Loading @@ -250,28 +310,89 @@ void EAGLE_PLUGIN::loadAllSections( CPTREE& aEagleBoard, const std::string& aXpa { { std::string xpath; std::string xpath; { xpath = aXpath + '.' + "plain"; CPTREE& plain = aEagleBoard.get_child( "plain" ); loadPlain( plain, xpath ); } { { xpath = aXpath + '.' + "libraries"; xpath = aXpath + '.' + "libraries"; CPTREE& libs = aEagleBoard.get_child( "libraries" ); CPTREE& libs = aEagleBoard.get_child( "libraries" ); loadModules( libs, xpath ); loadLibraries( libs, xpath ); } { xpath = aXpath + '.' + "elements"; CPTREE& elems = aEagleBoard.get_child( "elements" ); loadElements( elems, xpath ); } } // assume that MODULE_MAP is already loaded. { { xpath = aXpath + '.' + "signals"; xpath = aXpath + '.' + "signals"; CPTREE& signals = aEagleBoard.get_child( "signals" ); CPTREE& signals = aEagleBoard.get_child( "signals" ); loadNetsAndTracks( signals, xpath ); loadNetsAndTracks( signals, xpath ); } } ; ; } } void EAGLE_PLUGIN::loadModules( CPTREE& aLibs, const std::string& aXpath ) void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics, const std::string& aXpath ) { time_t now = time( NULL ); // (polygon | wire | text | circle | rectangle | frame | hole)* for( CITER gr = aGraphics.begin(); gr != aGraphics.end(); ++gr ) { if( !gr->first.compare( "wire" ) ) { EWIRE w = ewire( gr->second ); DRAWSEGMENT* dseg = new DRAWSEGMENT( m_board ); m_board->Add( dseg, ADD_APPEND ); dseg->SetTimeStamp( now ); dseg->SetLayer( kicad_layer( w.layer ) ); dseg->SetStart( wxPoint( kicad_x( w.x1 ), kicad_y( w.y1 ) ) ); dseg->SetEnd( wxPoint( kicad_x( w.x2 ), kicad_y( w.y2 ) ) ); dseg->SetWidth( kicad( w.width ) ); } else if( !gr->first.compare( "text" ) ) { } else if( !gr->first.compare( "circle" ) ) { ECIRCLE c = ecircle( gr->second ); DRAWSEGMENT* dseg = new DRAWSEGMENT( m_board ); m_board->Add( dseg, ADD_APPEND ); dseg->SetShape( S_CIRCLE ); dseg->SetTimeStamp( now ); dseg->SetLayer( kicad_layer( c.layer ) ); dseg->SetStart( wxPoint( kicad_x( c.x ), kicad_y( c.y ) ) ); dseg->SetEnd( wxPoint( kicad_x( c.x + c.radius ), kicad_y( c.y ) ) ); dseg->SetWidth( kicad( c.width ) ); } else if( !gr->first.compare( "rectangle" ) ) { } else if( !gr->first.compare( "hole" ) ) { } else if( !gr->first.compare( "frame" ) ) { } else if( !gr->first.compare( "polygon" ) ) { { m_modules.clear(); } } } void EAGLE_PLUGIN::loadLibraries( CPTREE& aLibs, const std::string& aXpath ) { for( CITER library = aLibs.begin(); library != aLibs.end(); ++library ) for( CITER library = aLibs.begin(); library != aLibs.end(); ++library ) { { const std::string& lib_name = library->second.get<std::string>( "<xmlattr>.name" ); const std::string& lib_name = library->second.get<std::string>( "<xmlattr>.name" ); Loading @@ -291,8 +412,8 @@ void EAGLE_PLUGIN::loadModules( CPTREE& aLibs, const std::string& aXpath ) MODULE* m = makeModule( package->second, pack_name ); MODULE* m = makeModule( package->second, pack_name ); // add the templating MODULE to the MODULE template factory "m_modules" // add the templating MODULE to the MODULE template factory "m_templates" std::pair<MODULE_ITER, bool> r = m_modules.insert( key, m ); std::pair<MODULE_ITER, bool> r = m_templates.insert( key, m ); if( !r.second ) if( !r.second ) { { Loading @@ -301,8 +422,8 @@ void EAGLE_PLUGIN::loadModules( CPTREE& aLibs, const std::string& aXpath ) wxString emsg = wxString::Format( wxString emsg = wxString::Format( _( "<package> name:'%s' duplicated in eagle <library>:'%s'" ), _( "<package> name:'%s' duplicated in eagle <library>:'%s'" ), GetChars( lib ), GetChars( pkg ), GetChars( pkg ) GetChars( lib ) ); ); THROW_IO_ERROR( emsg ); THROW_IO_ERROR( emsg ); } } Loading @@ -311,11 +432,134 @@ void EAGLE_PLUGIN::loadModules( CPTREE& aLibs, const std::string& aXpath ) } } EWIRE EAGLE_PLUGIN::wire( CPTREE aWire ) const void EAGLE_PLUGIN::loadElements( CPTREE& aElements, const std::string& aXpath ) { { EWIRE w; for( CITER it = aElements.begin(); it != aElements.end(); ++it ) { if( it->first.compare( "element" ) ) continue; CPTREE& attrs = it->second.get_child( "<xmlattr>" ); /* a '*' means zero or more times <!ELEMENT element (attribute*, variant*)> <!ATTLIST element name %String; #REQUIRED library %String; #REQUIRED package %String; #REQUIRED value %String; #REQUIRED x %Coord; #REQUIRED y %Coord; #REQUIRED locked %Bool; "no" smashed %Bool; "no" rot %Rotation; "R0" > */ std::string name = attrs.get<std::string>( "name" ); std::string library = attrs.get<std::string>( "library" ); std::string package = attrs.get<std::string>( "package" ); std::string value = attrs.get<std::string>( "value" ); double x = attrs.get<double>( "x" ); double y = attrs.get<double>( "y" ); opt_string rot = attrs.get_optional<std::string>( "rot" ); std::string key = makePkgKey( library, package ); MODULE_CITER mi = m_templates.find( key ); if( mi == m_templates.end() ) { wxString emsg = wxString::Format( _( "No '%s' package in library '%s'" ), GetChars( FROM_UTF8( package.c_str() ) ), GetChars( FROM_UTF8( library.c_str() ) ) ); THROW_IO_ERROR( emsg ); } // copy constructor to clone the template MODULE* m = new MODULE( *mi->second ); m->SetPosition( wxPoint( kicad_x( x ), kicad_y( y ) ) ); m->SetReference( FROM_UTF8( name.c_str() ) ); m->SetValue( FROM_UTF8( value.c_str() ) ); // m->Value().SetVisible( false ); // VALUE and NAME can have something like our text "effects" overrides // in SWEET and new schematic. Eagle calls these XML elements "attribute". // There can be one for NAME and/or VALUE both. CA_ITER_RANGE attributes = it->second.equal_range( "attribute" ); for( CA_ITER ait = attributes.first; ait != attributes.second; ++ait ) { double ratio = 6; EATTR a = eattr( ait->second ); TEXTE_MODULE* t; if( !a.name.compare( "NAME" ) ) t = &m->Reference(); else // "VALUE" or else our understanding of file format is incomplete. t = &m->Value(); if( a.value ) { t->SetText( FROM_UTF8( a.value->c_str() ) ); } if( a.x && a.y ) // boost::optional { wxPoint pos( kicad_x( *a.x ), kicad_y( *a.y ) ); wxPoint pos0 = pos - m->GetPosition(); t->SetPosition( pos ); t->SetPos0( pos0 ); } if( a.ratio ) ratio = *a.ratio; if( a.size ) { double z = *a.size; int h = kicad( z ); int w = (h * 8)/10; int lw = int( h * ratio / 100.0 ); t->SetSize( wxSize( w, h ) ); t->SetThickness( lw ); } if( a.erot ) { t->SetOrientation( a.erot->degrees * 10 ); } } if( rot ) { EROT r = erot( *rot ); m->SetOrientation( r.degrees * 10 ); if( r.mirror ) { // m->Flip(); } } m_board->Add( m ); } } EWIRE EAGLE_PLUGIN::ewire( CPTREE& aWire ) const { CPTREE& attribs = aWire.get_child( "<xmlattr>" ); CPTREE& attribs = aWire.get_child( "<xmlattr>" ); EWIRE w; w.x1 = attribs.get<double>( "x1" ); w.x1 = attribs.get<double>( "x1" ); w.y1 = attribs.get<double>( "y1" ); w.y1 = attribs.get<double>( "y1" ); Loading @@ -323,18 +567,101 @@ EWIRE EAGLE_PLUGIN::wire( CPTREE aWire ) const w.y2 = attribs.get<double>( "y2" ); w.y2 = attribs.get<double>( "y2" ); w.width = attribs.get<double>( "width" ); w.width = attribs.get<double>( "width" ); w.layer = attribs.get<int>( "layer" ); w.layer = attribs.get<int>( "layer" ); return w; return w; } } ECIRCLE EAGLE_PLUGIN::ecircle( CPTREE& aCircle ) const { CPTREE& attribs = aCircle.get_child( "<xmlattr>" ); ECIRCLE c; c.x = attribs.get<double>( "x" ); c.y = attribs.get<double>( "y" ); c.radius = attribs.get<double>( "radius" ); c.width = attribs.get<double>( "width" ); c.layer = attribs.get<int>( "layer" ); return c; } EROT EAGLE_PLUGIN::erot( const std::string& aRot ) const { EROT rot; rot.spin = aRot[0] == 'S'; rot.mirror = aRot[0] == 'M'; rot.degrees = strtod( aRot.c_str() + 1 + int( rot.spin || rot.mirror ), NULL ); return rot; } EATTR EAGLE_PLUGIN::eattr( CPTREE& aAttribute ) const { CPTREE& attribs = aAttribute.get_child( "<xmlattr>" ); EATTR a; /* <!ELEMENT attribute EMPTY> <!ATTLIST attribute name %String; #REQUIRED value %String; #IMPLIED x %Coord; #IMPLIED y %Coord; #IMPLIED size %Dimension; #IMPLIED layer %Layer; #IMPLIED font %TextFont; #IMPLIED ratio %Int; #IMPLIED rot %Rotation; "R0" display %AttributeDisplay; "value" -- only in <element> or <instance> context -- constant %Bool; "no" -- only in <device> context -- > */ a.name = attribs.get<std::string>( "name" ); // #REQUIRED a.value = attribs.get_optional<std::string>( "value" ); a.x = attribs.get_optional<double>( "x" ); a.y = attribs.get_optional<double>( "y" ); // KiCad cannot currently put a TEXTE_MODULE on a different layer than the MODULE // Eagle can it seems. Skip layer. a.size = attribs.get_optional<double>( "size" ); a.ratio = attribs.get_optional<double>( "ratio" ); opt_string rot = attribs.get_optional<std::string>( "rot" ); if( rot ) { a.erot = erot( *rot ); } opt_string display = attribs.get_optional<std::string>( "display" ); if( display ) { // (off | value | name | both) if( !display->compare( "off" ) ) a.display = EATTR::Off; else if( !display->compare( "value" ) ) a.display = EATTR::VALUE; else if( !display->compare( "name" ) ) a.display = EATTR::NAME; else if( !display->compare( "both" ) ) a.display = EATTR::BOTH; } return a; } MODULE* EAGLE_PLUGIN::makeModule( CPTREE& aPackage, const std::string& aPkgName ) const MODULE* EAGLE_PLUGIN::makeModule( CPTREE& aPackage, const std::string& aPkgName ) const { { std::auto_ptr<MODULE> m( new MODULE( NULL ) ); std::auto_ptr<MODULE> m( new MODULE( NULL ) ); m->SetLibRef( FROM_UTF8( aPkgName.c_str() ) ); m->SetLibRef( FROM_UTF8( aPkgName.c_str() ) ); boost::optional<std::string> description = aPackage.get_optional<std::string>( "description" ); opt_string description = aPackage.get_optional<std::string>( "description" ); if( description ) if( description ) m->SetDescription( FROM_UTF8( description->c_str() ) ); m->SetDescription( FROM_UTF8( description->c_str() ) ); Loading Loading @@ -373,16 +700,16 @@ MODULE* EAGLE_PLUGIN::makeModule( CPTREE& aPackage, const std::string& aPkgName void EAGLE_PLUGIN::packageWire( MODULE* aModule, CPTREE aTree ) const void EAGLE_PLUGIN::packageWire( MODULE* aModule, CPTREE aTree ) const { { EWIRE w = wire( aTree ); EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_SEGMENT ); aModule->m_Drawings.PushBack( dwg ); EWIRE w = ewire( aTree ); int layer = kicad_layer( w.layer ); wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) ); wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) ); wxPoint end( kicad_x( w.x2 ), kicad_y( w.x2 ) ); wxPoint end( kicad_x( w.x2 ), kicad_y( w.x2 ) ); int layer = kicad_layer( w.layer ); int width = kicad( w.width ); int width = kicad( w.width ); EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_SEGMENT ); aModule->m_Drawings.PushBack( dwg ); dwg->SetStart0( start ); dwg->SetStart0( start ); dwg->SetEnd0( end ); dwg->SetEnd0( end ); dwg->SetLayer( layer ); dwg->SetLayer( layer ); Loading @@ -392,7 +719,95 @@ void EAGLE_PLUGIN::packageWire( MODULE* aModule, CPTREE aTree ) const void EAGLE_PLUGIN::packagePad( MODULE* aModule, CPTREE aTree ) const void EAGLE_PLUGIN::packagePad( MODULE* aModule, CPTREE aTree ) const { { // pay for this tree traversal only once CPTREE attrs = aTree.get_child( "<xmlattr>" ); CPTREE attrs = aTree.get_child( "<xmlattr>" ); /* from <ealge>/doc/eagle.dtd <!ELEMENT pad EMPTY> <!ATTLIST pad name %String; #REQUIRED x %Coord; #REQUIRED y %Coord; #REQUIRED drill %Dimension; #REQUIRED diameter %Dimension; "0" shape %PadShape; "round" rot %Rotation; "R0" stop %Bool; "yes" thermals %Bool; "yes" first %Bool; "no" > */ D_PAD* pad = new D_PAD( aModule ); aModule->m_Pads.PushBack( pad ); // the DTD says these must be present, throw exception if not found double x = attrs.get<double>( "x" ); double y = attrs.get<double>( "y" ); double drill = attrs.get<double>( "drill" ); // pad's "Position" is not relative to the module's, // whereas Pos0 is relative to the module's but is the unrotated coordinate. wxPoint padpos( kicad_x( x ), kicad_y( y ) ); pad->SetPos0( padpos ); RotatePoint( &padpos, aModule->GetOrientation() ); pad->SetPosition( padpos + aModule->GetPosition() ); pad->SetDrillSize( wxSize( kicad( drill ), kicad( drill ) ) ); pad->SetLayerMask( 0x00C0FFFF ); // should tell it to go through all layers // Optional according to DTD. opt_double diameter = attrs.get_optional<double>( "diameter" ); opt_string shape = attrs.get_optional<std::string>( "shape" ); opt_string rot = attrs.get_optional<std::string>( "rot" ); opt_string stop = attrs.get_optional<std::string>( "stop" ); opt_string thermals = attrs.get_optional<std::string>( "thermals" ); opt_string first = attrs.get_optional<std::string>( "first" ); if( diameter ) { int kidiam = kicad( *diameter ); pad->SetSize( wxSize( kidiam, kidiam ) ); } if( shape ) // if not shape, our default is circle and that matches their default "round" { // <!ENTITY % PadShape "(square | round | octagon | long | offset)"> if( !shape->compare( "round" ) ) wxASSERT( pad->GetShape()==PAD_CIRCLE ); // verify set in D_PAD constructor else if( !shape->compare( "octagon" ) ) { wxASSERT( pad->GetShape()==PAD_CIRCLE ); // verify set in D_PAD constructor // @todo no KiCad octagonal pad shape, use PAD_CIRCLE for now. // pad->SetShape( PAD_OCTAGON ); } else if( !shape->compare( "long" ) ) { pad->SetShape( PAD_OVAL ); } else if( !shape->compare( "square" ) ) { pad->SetShape( PAD_RECT ); } } if( rot ) { EROT r = erot( *rot ); pad->SetOrientation( r.degrees * 10 ); } // don't know what stop and thermals should look like now. } } Loading Loading @@ -428,7 +843,82 @@ void EAGLE_PLUGIN::packageHole( MODULE* aModule, CPTREE aTree ) const void EAGLE_PLUGIN::packageSMD( MODULE* aModule, CPTREE aTree ) const void EAGLE_PLUGIN::packageSMD( MODULE* aModule, CPTREE aTree ) const { { // pay for this tree traversal only once CPTREE attrs = aTree.get_child( "<xmlattr>" ); CPTREE attrs = aTree.get_child( "<xmlattr>" ); /* from <ealge>/doc/eagle.dtd <!ATTLIST smd name %String; #REQUIRED x %Coord; #REQUIRED y %Coord; #REQUIRED dx %Dimension; #REQUIRED dy %Dimension; #REQUIRED layer %Layer; #REQUIRED roundness %Int; "0" rot %Rotation; "R0" stop %Bool; "yes" thermals %Bool; "yes" cream %Bool; "yes" > */ D_PAD* pad = new D_PAD( aModule ); aModule->m_Pads.PushBack( pad ); pad->SetShape( PAD_RECT ); pad->SetAttribute( PAD_SMD ); // the DTD says these must be present, throw exception if not found double x = attrs.get<double>( "x" ); double y = attrs.get<double>( "y" ); double dx = attrs.get<double>( "dx" ); double dy = attrs.get<double>( "dy" ); int layer = attrs.get<int>( "layer" ); // pad's "Position" is not relative to the module's, // whereas Pos0 is relative to the module's but is the unrotated coordinate. wxPoint padpos( kicad_x( x ), kicad_y( y ) ); pad->SetPos0( padpos ); RotatePoint( &padpos, aModule->GetOrientation() ); pad->SetPosition( padpos + aModule->GetPosition() ); pad->SetSize( wxSize( kicad( dx ), kicad( dy ) ) ); pad->SetLayer( kicad_layer( layer ) ); pad->SetLayerMask( 0x00888000 ); // these are optional according to DTD, and the weak XML parser does not // provide defaults from a DTD. opt_double roundness = attrs.get_optional<double>( "roundness" ); opt_string rot = attrs.get_optional<std::string>( "rot" ); opt_string stop = attrs.get_optional<std::string>( "stop" ); opt_string thermals = attrs.get_optional<std::string>( "thermals" ); opt_string cream = attrs.get_optional<std::string>( "cream" ); if( roundness ) // set set shape to PAD_RECT above, in case roundness is not present { if( *roundness >= 75 ) // roundness goes from 0-100% { if( dy == dx ) pad->SetShape( PAD_ROUND ); else pad->SetShape( PAD_OVAL ); } } if( rot ) { EROT r = erot( *rot ); pad->SetOrientation( r.degrees * 10 ); } // don't know what stop, thermals, and cream should look like now. } } Loading Loading @@ -487,11 +977,10 @@ void EAGLE_PLUGIN::loadNetsAndTracks( CPTREE& aSignals, const std::string& aXpat m_board->AppendNet( new NETINFO_ITEM( m_board, netName, netCode ) ); m_board->AppendNet( new NETINFO_ITEM( m_board, netName, netCode ) ); std::pair<CA_ITER, CA_ITER> wires = nit->second.equal_range( "wire" ); CA_ITER_RANGE wires = nit->second.equal_range( "wire" ); for( CA_ITER wit = wires.first; wit != wires.second; ++wit ) for( CA_ITER wit = wires.first; wit != wires.second; ++wit ) { { EWIRE w = wire( wit->second ); EWIRE w = ewire( wit->second ); TRACK* t = new TRACK( m_board ); TRACK* t = new TRACK( m_board ); Loading @@ -512,9 +1001,49 @@ void EAGLE_PLUGIN::loadNetsAndTracks( CPTREE& aSignals, const std::string& aXpat } } int EAGLE_PLUGIN::kicad_layer( int aLayer ) const int EAGLE_PLUGIN::kicad_layer( int aLayer ) { int ret; switch( aLayer ) // translate eagle layer to pcbnew layer { { return aLayer; case 1: ret = 15; break; // Top copper case 2: ret = 14; break; case 3: ret = 13; break; case 4: ret = 12; break; case 5: ret = 11; break; case 6: ret = 10; break; case 7: ret = 9; break; case 8: ret = 8; break; case 9: ret = 7; break; case 10: ret = 6; break; case 11: ret = 5; break; case 12: ret = 4; break; case 13: ret = 3; break; case 14: ret = 2; break; case 15: ret = 1; break; case 16: ret = 0; break; // Bottom Copper case 20: ret = 28; break; // Edge Layer case 21: ret = 21; break; // Top Silk Screen case 22: ret = 20; break; // Bottom Silk Screen case 25: ret = 25; break; // Misc Comment Layers case 26: ret = 25; break; case 27: ret = 26; break; case 28: ret = 26; break; case 29: ret = 23; break; case 30: ret = 22; break; case 31: ret = 19; break; case 32: ret = 18; break; case 35: ret = 17; break; case 36: ret = 16; break; case 51: ret = 26; break; case 52: ret = 27; break; case 95: ret = 26; break; case 96: ret = 27; break; default: ret = -1; break; // our eagle understanding is incomplete } return ret; } } Loading Loading
include/wxPcbStruct.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -1340,7 +1340,7 @@ public: void ShowTargetOptionsDialog( PCB_TARGET* aTarget, wxDC* DC ); void ShowTargetOptionsDialog( PCB_TARGET* aTarget, wxDC* DC ); // Graphic segments type DRAWSEGMENT handling: // Graphic segments type DRAWSEGMENT handling: DRAWSEGMENT* Begin_DrawSegment( DRAWSEGMENT* Segment, int shape, wxDC* DC ); DRAWSEGMENT* Begin_DrawSegment( DRAWSEGMENT* Segment, STROKE_T shape, wxDC* DC ); void End_Edge( DRAWSEGMENT* Segment, wxDC* DC ); void End_Edge( DRAWSEGMENT* Segment, wxDC* DC ); void Delete_Segment_Edge( DRAWSEGMENT* Segment, wxDC* DC ); void Delete_Segment_Edge( DRAWSEGMENT* Segment, wxDC* DC ); void Delete_Drawings_All_Layer( int aLayer ); void Delete_Drawings_All_Layer( int aLayer ); Loading
pcbnew/class_drawsegment.cpp +45 −35 Original line number Original line Diff line number Diff line Loading @@ -124,6 +124,10 @@ const wxPoint DRAWSEGMENT::GetArcEnd() const // m_Start is the arc centre // m_Start is the arc centre endPoint = m_End; // m_End = start point of arc endPoint = m_End; // m_End = start point of arc RotatePoint( &endPoint, m_Start, -m_Angle ); RotatePoint( &endPoint, m_Start, -m_Angle ); break; default: ; } } return endPoint; // after rotation, the end of the arc. return endPoint; // after rotation, the end of the arc. Loading Loading @@ -429,8 +433,11 @@ EDA_RECT DRAWSEGMENT::GetBoundingBox() const } } bbox.SetEnd( p_end ); bbox.SetEnd( p_end ); break; } } break; default: ; } } bbox.Inflate( ((m_Width+1) / 2) + 1 ); bbox.Inflate( ((m_Width+1) / 2) + 1 ); Loading Loading @@ -520,6 +527,9 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect ) const if( aRect.Contains( GetEnd() ) ) if( aRect.Contains( GetEnd() ) ) return true; return true; break; break; default: ; } } return false; return false; } } Loading
pcbnew/class_drawsegment.h +14 −14 Original line number Original line Diff line number Diff line Loading @@ -47,7 +47,7 @@ protected: wxPoint m_Start; ///< Line start point or Circle and Arc center wxPoint m_Start; ///< Line start point or Circle and Arc center wxPoint m_End; ///< Line end point or circle and arc start point wxPoint m_End; ///< Line end point or circle and arc start point int m_Shape; ///< Shape: line, Circle, Arc STROKE_T m_Shape; ///< Shape: line, Circle, Arc int m_Type; ///< Used in complex associations ( Dimensions.. ) int m_Type; ///< Used in complex associations ( Dimensions.. ) double m_Angle; ///< Used only for Arcs: Arc angle in 1/10 deg double m_Angle; ///< Used only for Arcs: Arc angle in 1/10 deg wxPoint m_BezierC1; ///< Bezier Control Point 1 wxPoint m_BezierC1; ///< Bezier Control Point 1 Loading Loading @@ -83,8 +83,8 @@ public: void SetType( int aType ) { m_Type = aType; } void SetType( int aType ) { m_Type = aType; } int GetType() const { return m_Type; } int GetType() const { return m_Type; } void SetShape( int aShape ) { m_Shape = aShape; } void SetShape( STROKE_T aShape ) { m_Shape = aShape; } int GetShape() const { return m_Shape; } STROKE_T GetShape() const { return m_Shape; } void SetBezControl1( const wxPoint& aPoint ) { m_BezierC1 = aPoint; } void SetBezControl1( const wxPoint& aPoint ) { m_BezierC1 = aPoint; } const wxPoint& GetBezControl1() const { return m_BezierC1; } const wxPoint& GetBezControl1() const { return m_BezierC1; } Loading
pcbnew/class_module.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -294,6 +294,11 @@ public: m_Value->m_Text = aValue; m_Value->m_Text = aValue; } } /// read/write accessors: TEXTE_MODULE& Value() { return *m_Value; } TEXTE_MODULE& Reference() { return *m_Reference; } /** /** * Function FindPadByName * Function FindPadByName * returns a D_PAD* with a matching name. Note that names may not be * returns a D_PAD* with a matching name. Note that names may not be Loading
pcbnew/eagle_plugin.cpp +556 −27 Original line number Original line Diff line number Diff line Loading @@ -59,6 +59,8 @@ our error message. #include <common.h> #include <common.h> #include <macros.h> #include <macros.h> #include <fctsys.h> #include <fctsys.h> #include <trigo.h> #include <class_board.h> #include <class_board.h> #include <class_module.h> #include <class_module.h> #include <class_track.h> #include <class_track.h> Loading @@ -70,17 +72,75 @@ using namespace boost::property_tree; typedef EAGLE_PLUGIN::BIU BIU; typedef EAGLE_PLUGIN::BIU BIU; typedef PTREE::const_assoc_iterator CA_ITER; typedef PTREE::const_assoc_iterator CA_ITER; typedef PTREE::const_iterator CITER; typedef PTREE::const_iterator CITER; typedef std::pair<CA_ITER, CA_ITER> CA_ITER_RANGE; typedef MODULE_MAP::iterator MODULE_ITER; typedef MODULE_MAP::iterator MODULE_ITER; typedef MODULE_MAP::const_iterator MODULE_CITER; typedef MODULE_MAP::const_iterator MODULE_CITER; typedef boost::optional<std::string> opt_string; typedef boost::optional<int> opt_int; typedef boost::optional<double> opt_double; typedef boost::optional<CPTREE&> opt_cptree; /// Eagle wire struct EWIRE { double x1; double y1; double x2; double y2; double width; int layer; }; /// Eagle circle struct ECIRCLE { double x; double y; double radius; double width; int layer; }; /// Eagle rotation struct EROT { bool mirror; bool spin; double degrees; }; typedef boost::optional<EROT> opt_erot; /// Eagle "attribute" XML element, no foolin'. struct EATTR { std::string name; opt_string value; opt_double x; opt_double y; opt_double size; // opt_int layer; opt_double ratio; opt_erot erot; opt_int display; enum { // for 'display' field above Off, VALUE, NAME, BOTH, }; }; /// Assemble a MODULE factory key as a simple concatonation of library name and /// package name, using '\x02' as a separator. static inline std::string makePkgKey( const std::string& aLibName, const std::string& aPkgName ) static inline std::string makePkgKey( const std::string& aLibName, const std::string& aPkgName ) { { // The MODULE factory key is a simple concatonation of library name and // package name, using '\x02' as a separator. std::string key = aLibName + '\x02' + aPkgName; std::string key = aLibName + '\x02' + aPkgName; return key; return key; } } Loading Loading @@ -164,7 +224,7 @@ void EAGLE_PLUGIN::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* a void EAGLE_PLUGIN::init( PROPERTIES* aProperties ) void EAGLE_PLUGIN::init( PROPERTIES* aProperties ) { { m_modules.clear(); m_templates.clear(); m_board = NULL; m_board = NULL; m_props = aProperties; m_props = aProperties; Loading Loading @@ -250,28 +310,89 @@ void EAGLE_PLUGIN::loadAllSections( CPTREE& aEagleBoard, const std::string& aXpa { { std::string xpath; std::string xpath; { xpath = aXpath + '.' + "plain"; CPTREE& plain = aEagleBoard.get_child( "plain" ); loadPlain( plain, xpath ); } { { xpath = aXpath + '.' + "libraries"; xpath = aXpath + '.' + "libraries"; CPTREE& libs = aEagleBoard.get_child( "libraries" ); CPTREE& libs = aEagleBoard.get_child( "libraries" ); loadModules( libs, xpath ); loadLibraries( libs, xpath ); } { xpath = aXpath + '.' + "elements"; CPTREE& elems = aEagleBoard.get_child( "elements" ); loadElements( elems, xpath ); } } // assume that MODULE_MAP is already loaded. { { xpath = aXpath + '.' + "signals"; xpath = aXpath + '.' + "signals"; CPTREE& signals = aEagleBoard.get_child( "signals" ); CPTREE& signals = aEagleBoard.get_child( "signals" ); loadNetsAndTracks( signals, xpath ); loadNetsAndTracks( signals, xpath ); } } ; ; } } void EAGLE_PLUGIN::loadModules( CPTREE& aLibs, const std::string& aXpath ) void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics, const std::string& aXpath ) { time_t now = time( NULL ); // (polygon | wire | text | circle | rectangle | frame | hole)* for( CITER gr = aGraphics.begin(); gr != aGraphics.end(); ++gr ) { if( !gr->first.compare( "wire" ) ) { EWIRE w = ewire( gr->second ); DRAWSEGMENT* dseg = new DRAWSEGMENT( m_board ); m_board->Add( dseg, ADD_APPEND ); dseg->SetTimeStamp( now ); dseg->SetLayer( kicad_layer( w.layer ) ); dseg->SetStart( wxPoint( kicad_x( w.x1 ), kicad_y( w.y1 ) ) ); dseg->SetEnd( wxPoint( kicad_x( w.x2 ), kicad_y( w.y2 ) ) ); dseg->SetWidth( kicad( w.width ) ); } else if( !gr->first.compare( "text" ) ) { } else if( !gr->first.compare( "circle" ) ) { ECIRCLE c = ecircle( gr->second ); DRAWSEGMENT* dseg = new DRAWSEGMENT( m_board ); m_board->Add( dseg, ADD_APPEND ); dseg->SetShape( S_CIRCLE ); dseg->SetTimeStamp( now ); dseg->SetLayer( kicad_layer( c.layer ) ); dseg->SetStart( wxPoint( kicad_x( c.x ), kicad_y( c.y ) ) ); dseg->SetEnd( wxPoint( kicad_x( c.x + c.radius ), kicad_y( c.y ) ) ); dseg->SetWidth( kicad( c.width ) ); } else if( !gr->first.compare( "rectangle" ) ) { } else if( !gr->first.compare( "hole" ) ) { } else if( !gr->first.compare( "frame" ) ) { } else if( !gr->first.compare( "polygon" ) ) { { m_modules.clear(); } } } void EAGLE_PLUGIN::loadLibraries( CPTREE& aLibs, const std::string& aXpath ) { for( CITER library = aLibs.begin(); library != aLibs.end(); ++library ) for( CITER library = aLibs.begin(); library != aLibs.end(); ++library ) { { const std::string& lib_name = library->second.get<std::string>( "<xmlattr>.name" ); const std::string& lib_name = library->second.get<std::string>( "<xmlattr>.name" ); Loading @@ -291,8 +412,8 @@ void EAGLE_PLUGIN::loadModules( CPTREE& aLibs, const std::string& aXpath ) MODULE* m = makeModule( package->second, pack_name ); MODULE* m = makeModule( package->second, pack_name ); // add the templating MODULE to the MODULE template factory "m_modules" // add the templating MODULE to the MODULE template factory "m_templates" std::pair<MODULE_ITER, bool> r = m_modules.insert( key, m ); std::pair<MODULE_ITER, bool> r = m_templates.insert( key, m ); if( !r.second ) if( !r.second ) { { Loading @@ -301,8 +422,8 @@ void EAGLE_PLUGIN::loadModules( CPTREE& aLibs, const std::string& aXpath ) wxString emsg = wxString::Format( wxString emsg = wxString::Format( _( "<package> name:'%s' duplicated in eagle <library>:'%s'" ), _( "<package> name:'%s' duplicated in eagle <library>:'%s'" ), GetChars( lib ), GetChars( pkg ), GetChars( pkg ) GetChars( lib ) ); ); THROW_IO_ERROR( emsg ); THROW_IO_ERROR( emsg ); } } Loading @@ -311,11 +432,134 @@ void EAGLE_PLUGIN::loadModules( CPTREE& aLibs, const std::string& aXpath ) } } EWIRE EAGLE_PLUGIN::wire( CPTREE aWire ) const void EAGLE_PLUGIN::loadElements( CPTREE& aElements, const std::string& aXpath ) { { EWIRE w; for( CITER it = aElements.begin(); it != aElements.end(); ++it ) { if( it->first.compare( "element" ) ) continue; CPTREE& attrs = it->second.get_child( "<xmlattr>" ); /* a '*' means zero or more times <!ELEMENT element (attribute*, variant*)> <!ATTLIST element name %String; #REQUIRED library %String; #REQUIRED package %String; #REQUIRED value %String; #REQUIRED x %Coord; #REQUIRED y %Coord; #REQUIRED locked %Bool; "no" smashed %Bool; "no" rot %Rotation; "R0" > */ std::string name = attrs.get<std::string>( "name" ); std::string library = attrs.get<std::string>( "library" ); std::string package = attrs.get<std::string>( "package" ); std::string value = attrs.get<std::string>( "value" ); double x = attrs.get<double>( "x" ); double y = attrs.get<double>( "y" ); opt_string rot = attrs.get_optional<std::string>( "rot" ); std::string key = makePkgKey( library, package ); MODULE_CITER mi = m_templates.find( key ); if( mi == m_templates.end() ) { wxString emsg = wxString::Format( _( "No '%s' package in library '%s'" ), GetChars( FROM_UTF8( package.c_str() ) ), GetChars( FROM_UTF8( library.c_str() ) ) ); THROW_IO_ERROR( emsg ); } // copy constructor to clone the template MODULE* m = new MODULE( *mi->second ); m->SetPosition( wxPoint( kicad_x( x ), kicad_y( y ) ) ); m->SetReference( FROM_UTF8( name.c_str() ) ); m->SetValue( FROM_UTF8( value.c_str() ) ); // m->Value().SetVisible( false ); // VALUE and NAME can have something like our text "effects" overrides // in SWEET and new schematic. Eagle calls these XML elements "attribute". // There can be one for NAME and/or VALUE both. CA_ITER_RANGE attributes = it->second.equal_range( "attribute" ); for( CA_ITER ait = attributes.first; ait != attributes.second; ++ait ) { double ratio = 6; EATTR a = eattr( ait->second ); TEXTE_MODULE* t; if( !a.name.compare( "NAME" ) ) t = &m->Reference(); else // "VALUE" or else our understanding of file format is incomplete. t = &m->Value(); if( a.value ) { t->SetText( FROM_UTF8( a.value->c_str() ) ); } if( a.x && a.y ) // boost::optional { wxPoint pos( kicad_x( *a.x ), kicad_y( *a.y ) ); wxPoint pos0 = pos - m->GetPosition(); t->SetPosition( pos ); t->SetPos0( pos0 ); } if( a.ratio ) ratio = *a.ratio; if( a.size ) { double z = *a.size; int h = kicad( z ); int w = (h * 8)/10; int lw = int( h * ratio / 100.0 ); t->SetSize( wxSize( w, h ) ); t->SetThickness( lw ); } if( a.erot ) { t->SetOrientation( a.erot->degrees * 10 ); } } if( rot ) { EROT r = erot( *rot ); m->SetOrientation( r.degrees * 10 ); if( r.mirror ) { // m->Flip(); } } m_board->Add( m ); } } EWIRE EAGLE_PLUGIN::ewire( CPTREE& aWire ) const { CPTREE& attribs = aWire.get_child( "<xmlattr>" ); CPTREE& attribs = aWire.get_child( "<xmlattr>" ); EWIRE w; w.x1 = attribs.get<double>( "x1" ); w.x1 = attribs.get<double>( "x1" ); w.y1 = attribs.get<double>( "y1" ); w.y1 = attribs.get<double>( "y1" ); Loading @@ -323,18 +567,101 @@ EWIRE EAGLE_PLUGIN::wire( CPTREE aWire ) const w.y2 = attribs.get<double>( "y2" ); w.y2 = attribs.get<double>( "y2" ); w.width = attribs.get<double>( "width" ); w.width = attribs.get<double>( "width" ); w.layer = attribs.get<int>( "layer" ); w.layer = attribs.get<int>( "layer" ); return w; return w; } } ECIRCLE EAGLE_PLUGIN::ecircle( CPTREE& aCircle ) const { CPTREE& attribs = aCircle.get_child( "<xmlattr>" ); ECIRCLE c; c.x = attribs.get<double>( "x" ); c.y = attribs.get<double>( "y" ); c.radius = attribs.get<double>( "radius" ); c.width = attribs.get<double>( "width" ); c.layer = attribs.get<int>( "layer" ); return c; } EROT EAGLE_PLUGIN::erot( const std::string& aRot ) const { EROT rot; rot.spin = aRot[0] == 'S'; rot.mirror = aRot[0] == 'M'; rot.degrees = strtod( aRot.c_str() + 1 + int( rot.spin || rot.mirror ), NULL ); return rot; } EATTR EAGLE_PLUGIN::eattr( CPTREE& aAttribute ) const { CPTREE& attribs = aAttribute.get_child( "<xmlattr>" ); EATTR a; /* <!ELEMENT attribute EMPTY> <!ATTLIST attribute name %String; #REQUIRED value %String; #IMPLIED x %Coord; #IMPLIED y %Coord; #IMPLIED size %Dimension; #IMPLIED layer %Layer; #IMPLIED font %TextFont; #IMPLIED ratio %Int; #IMPLIED rot %Rotation; "R0" display %AttributeDisplay; "value" -- only in <element> or <instance> context -- constant %Bool; "no" -- only in <device> context -- > */ a.name = attribs.get<std::string>( "name" ); // #REQUIRED a.value = attribs.get_optional<std::string>( "value" ); a.x = attribs.get_optional<double>( "x" ); a.y = attribs.get_optional<double>( "y" ); // KiCad cannot currently put a TEXTE_MODULE on a different layer than the MODULE // Eagle can it seems. Skip layer. a.size = attribs.get_optional<double>( "size" ); a.ratio = attribs.get_optional<double>( "ratio" ); opt_string rot = attribs.get_optional<std::string>( "rot" ); if( rot ) { a.erot = erot( *rot ); } opt_string display = attribs.get_optional<std::string>( "display" ); if( display ) { // (off | value | name | both) if( !display->compare( "off" ) ) a.display = EATTR::Off; else if( !display->compare( "value" ) ) a.display = EATTR::VALUE; else if( !display->compare( "name" ) ) a.display = EATTR::NAME; else if( !display->compare( "both" ) ) a.display = EATTR::BOTH; } return a; } MODULE* EAGLE_PLUGIN::makeModule( CPTREE& aPackage, const std::string& aPkgName ) const MODULE* EAGLE_PLUGIN::makeModule( CPTREE& aPackage, const std::string& aPkgName ) const { { std::auto_ptr<MODULE> m( new MODULE( NULL ) ); std::auto_ptr<MODULE> m( new MODULE( NULL ) ); m->SetLibRef( FROM_UTF8( aPkgName.c_str() ) ); m->SetLibRef( FROM_UTF8( aPkgName.c_str() ) ); boost::optional<std::string> description = aPackage.get_optional<std::string>( "description" ); opt_string description = aPackage.get_optional<std::string>( "description" ); if( description ) if( description ) m->SetDescription( FROM_UTF8( description->c_str() ) ); m->SetDescription( FROM_UTF8( description->c_str() ) ); Loading Loading @@ -373,16 +700,16 @@ MODULE* EAGLE_PLUGIN::makeModule( CPTREE& aPackage, const std::string& aPkgName void EAGLE_PLUGIN::packageWire( MODULE* aModule, CPTREE aTree ) const void EAGLE_PLUGIN::packageWire( MODULE* aModule, CPTREE aTree ) const { { EWIRE w = wire( aTree ); EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_SEGMENT ); aModule->m_Drawings.PushBack( dwg ); EWIRE w = ewire( aTree ); int layer = kicad_layer( w.layer ); wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) ); wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) ); wxPoint end( kicad_x( w.x2 ), kicad_y( w.x2 ) ); wxPoint end( kicad_x( w.x2 ), kicad_y( w.x2 ) ); int layer = kicad_layer( w.layer ); int width = kicad( w.width ); int width = kicad( w.width ); EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_SEGMENT ); aModule->m_Drawings.PushBack( dwg ); dwg->SetStart0( start ); dwg->SetStart0( start ); dwg->SetEnd0( end ); dwg->SetEnd0( end ); dwg->SetLayer( layer ); dwg->SetLayer( layer ); Loading @@ -392,7 +719,95 @@ void EAGLE_PLUGIN::packageWire( MODULE* aModule, CPTREE aTree ) const void EAGLE_PLUGIN::packagePad( MODULE* aModule, CPTREE aTree ) const void EAGLE_PLUGIN::packagePad( MODULE* aModule, CPTREE aTree ) const { { // pay for this tree traversal only once CPTREE attrs = aTree.get_child( "<xmlattr>" ); CPTREE attrs = aTree.get_child( "<xmlattr>" ); /* from <ealge>/doc/eagle.dtd <!ELEMENT pad EMPTY> <!ATTLIST pad name %String; #REQUIRED x %Coord; #REQUIRED y %Coord; #REQUIRED drill %Dimension; #REQUIRED diameter %Dimension; "0" shape %PadShape; "round" rot %Rotation; "R0" stop %Bool; "yes" thermals %Bool; "yes" first %Bool; "no" > */ D_PAD* pad = new D_PAD( aModule ); aModule->m_Pads.PushBack( pad ); // the DTD says these must be present, throw exception if not found double x = attrs.get<double>( "x" ); double y = attrs.get<double>( "y" ); double drill = attrs.get<double>( "drill" ); // pad's "Position" is not relative to the module's, // whereas Pos0 is relative to the module's but is the unrotated coordinate. wxPoint padpos( kicad_x( x ), kicad_y( y ) ); pad->SetPos0( padpos ); RotatePoint( &padpos, aModule->GetOrientation() ); pad->SetPosition( padpos + aModule->GetPosition() ); pad->SetDrillSize( wxSize( kicad( drill ), kicad( drill ) ) ); pad->SetLayerMask( 0x00C0FFFF ); // should tell it to go through all layers // Optional according to DTD. opt_double diameter = attrs.get_optional<double>( "diameter" ); opt_string shape = attrs.get_optional<std::string>( "shape" ); opt_string rot = attrs.get_optional<std::string>( "rot" ); opt_string stop = attrs.get_optional<std::string>( "stop" ); opt_string thermals = attrs.get_optional<std::string>( "thermals" ); opt_string first = attrs.get_optional<std::string>( "first" ); if( diameter ) { int kidiam = kicad( *diameter ); pad->SetSize( wxSize( kidiam, kidiam ) ); } if( shape ) // if not shape, our default is circle and that matches their default "round" { // <!ENTITY % PadShape "(square | round | octagon | long | offset)"> if( !shape->compare( "round" ) ) wxASSERT( pad->GetShape()==PAD_CIRCLE ); // verify set in D_PAD constructor else if( !shape->compare( "octagon" ) ) { wxASSERT( pad->GetShape()==PAD_CIRCLE ); // verify set in D_PAD constructor // @todo no KiCad octagonal pad shape, use PAD_CIRCLE for now. // pad->SetShape( PAD_OCTAGON ); } else if( !shape->compare( "long" ) ) { pad->SetShape( PAD_OVAL ); } else if( !shape->compare( "square" ) ) { pad->SetShape( PAD_RECT ); } } if( rot ) { EROT r = erot( *rot ); pad->SetOrientation( r.degrees * 10 ); } // don't know what stop and thermals should look like now. } } Loading Loading @@ -428,7 +843,82 @@ void EAGLE_PLUGIN::packageHole( MODULE* aModule, CPTREE aTree ) const void EAGLE_PLUGIN::packageSMD( MODULE* aModule, CPTREE aTree ) const void EAGLE_PLUGIN::packageSMD( MODULE* aModule, CPTREE aTree ) const { { // pay for this tree traversal only once CPTREE attrs = aTree.get_child( "<xmlattr>" ); CPTREE attrs = aTree.get_child( "<xmlattr>" ); /* from <ealge>/doc/eagle.dtd <!ATTLIST smd name %String; #REQUIRED x %Coord; #REQUIRED y %Coord; #REQUIRED dx %Dimension; #REQUIRED dy %Dimension; #REQUIRED layer %Layer; #REQUIRED roundness %Int; "0" rot %Rotation; "R0" stop %Bool; "yes" thermals %Bool; "yes" cream %Bool; "yes" > */ D_PAD* pad = new D_PAD( aModule ); aModule->m_Pads.PushBack( pad ); pad->SetShape( PAD_RECT ); pad->SetAttribute( PAD_SMD ); // the DTD says these must be present, throw exception if not found double x = attrs.get<double>( "x" ); double y = attrs.get<double>( "y" ); double dx = attrs.get<double>( "dx" ); double dy = attrs.get<double>( "dy" ); int layer = attrs.get<int>( "layer" ); // pad's "Position" is not relative to the module's, // whereas Pos0 is relative to the module's but is the unrotated coordinate. wxPoint padpos( kicad_x( x ), kicad_y( y ) ); pad->SetPos0( padpos ); RotatePoint( &padpos, aModule->GetOrientation() ); pad->SetPosition( padpos + aModule->GetPosition() ); pad->SetSize( wxSize( kicad( dx ), kicad( dy ) ) ); pad->SetLayer( kicad_layer( layer ) ); pad->SetLayerMask( 0x00888000 ); // these are optional according to DTD, and the weak XML parser does not // provide defaults from a DTD. opt_double roundness = attrs.get_optional<double>( "roundness" ); opt_string rot = attrs.get_optional<std::string>( "rot" ); opt_string stop = attrs.get_optional<std::string>( "stop" ); opt_string thermals = attrs.get_optional<std::string>( "thermals" ); opt_string cream = attrs.get_optional<std::string>( "cream" ); if( roundness ) // set set shape to PAD_RECT above, in case roundness is not present { if( *roundness >= 75 ) // roundness goes from 0-100% { if( dy == dx ) pad->SetShape( PAD_ROUND ); else pad->SetShape( PAD_OVAL ); } } if( rot ) { EROT r = erot( *rot ); pad->SetOrientation( r.degrees * 10 ); } // don't know what stop, thermals, and cream should look like now. } } Loading Loading @@ -487,11 +977,10 @@ void EAGLE_PLUGIN::loadNetsAndTracks( CPTREE& aSignals, const std::string& aXpat m_board->AppendNet( new NETINFO_ITEM( m_board, netName, netCode ) ); m_board->AppendNet( new NETINFO_ITEM( m_board, netName, netCode ) ); std::pair<CA_ITER, CA_ITER> wires = nit->second.equal_range( "wire" ); CA_ITER_RANGE wires = nit->second.equal_range( "wire" ); for( CA_ITER wit = wires.first; wit != wires.second; ++wit ) for( CA_ITER wit = wires.first; wit != wires.second; ++wit ) { { EWIRE w = wire( wit->second ); EWIRE w = ewire( wit->second ); TRACK* t = new TRACK( m_board ); TRACK* t = new TRACK( m_board ); Loading @@ -512,9 +1001,49 @@ void EAGLE_PLUGIN::loadNetsAndTracks( CPTREE& aSignals, const std::string& aXpat } } int EAGLE_PLUGIN::kicad_layer( int aLayer ) const int EAGLE_PLUGIN::kicad_layer( int aLayer ) { int ret; switch( aLayer ) // translate eagle layer to pcbnew layer { { return aLayer; case 1: ret = 15; break; // Top copper case 2: ret = 14; break; case 3: ret = 13; break; case 4: ret = 12; break; case 5: ret = 11; break; case 6: ret = 10; break; case 7: ret = 9; break; case 8: ret = 8; break; case 9: ret = 7; break; case 10: ret = 6; break; case 11: ret = 5; break; case 12: ret = 4; break; case 13: ret = 3; break; case 14: ret = 2; break; case 15: ret = 1; break; case 16: ret = 0; break; // Bottom Copper case 20: ret = 28; break; // Edge Layer case 21: ret = 21; break; // Top Silk Screen case 22: ret = 20; break; // Bottom Silk Screen case 25: ret = 25; break; // Misc Comment Layers case 26: ret = 25; break; case 27: ret = 26; break; case 28: ret = 26; break; case 29: ret = 23; break; case 30: ret = 22; break; case 31: ret = 19; break; case 32: ret = 18; break; case 35: ret = 17; break; case 36: ret = 16; break; case 51: ret = 26; break; case 52: ret = 27; break; case 95: ret = 26; break; case 96: ret = 27; break; default: ret = -1; break; // our eagle understanding is incomplete } return ret; } } Loading