diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index fe06fb1ae6..fcb51db4d1 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -1340,7 +1340,7 @@ public: void ShowTargetOptionsDialog( PCB_TARGET* aTarget, wxDC* DC ); // 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 Delete_Segment_Edge( DRAWSEGMENT* Segment, wxDC* DC ); void Delete_Drawings_All_Layer( int aLayer ); diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index a65ac9f05e..6d43a35483 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -124,6 +124,10 @@ const wxPoint DRAWSEGMENT::GetArcEnd() const // m_Start is the arc centre endPoint = m_End; // m_End = start point of arc RotatePoint( &endPoint, m_Start, -m_Angle ); + break; + + default: + ; } return endPoint; // after rotation, the end of the arc. @@ -387,15 +391,15 @@ EDA_RECT DRAWSEGMENT::GetBoundingBox() const switch( m_Shape ) { - case S_SEGMENT: - bbox.SetEnd( m_End ); - break; + case S_SEGMENT: + bbox.SetEnd( m_End ); + break; - case S_CIRCLE: - bbox.Inflate( GetRadius() ); - break; + case S_CIRCLE: + bbox.Inflate( GetRadius() ); + break; - case S_ARC: + case S_ARC: { bbox.Merge( m_End ); wxPoint end = m_End; @@ -404,7 +408,7 @@ EDA_RECT DRAWSEGMENT::GetBoundingBox() const } break; - case S_POLYGON: + case S_POLYGON: { wxPoint p_end; MODULE* module = GetParentModule(); @@ -429,8 +433,11 @@ EDA_RECT DRAWSEGMENT::GetBoundingBox() const } bbox.SetEnd( p_end ); - break; } + break; + + default: + ; } bbox.Inflate( ((m_Width+1) / 2) + 1 ); @@ -449,30 +456,30 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aPosition ) { case S_CIRCLE: case S_ARC: - { - int radius = GetRadius(); - int dist = (int) hypot( (double) relPos.x, (double) relPos.y ); - - if( abs( radius - dist ) <= ( m_Width / 2 ) ) { - if( m_Shape == S_CIRCLE ) + int radius = GetRadius(); + int dist = (int) hypot( (double) relPos.x, (double) relPos.y ); + + if( abs( radius - dist ) <= ( m_Width / 2 ) ) + { + if( m_Shape == S_CIRCLE ) + return true; + + wxPoint startVec = wxPoint( m_End.x - m_Start.x, m_End.y - m_Start.y ); + wxPoint endVec = m_End - m_Start; + RotatePoint( &endVec, -m_Angle ); + + // Check dot products + if( (long long)relPos.x*startVec.x + (long long)relPos.y*startVec.y < 0 ) + return false; + + if( (long long)relPos.x*endVec.x + (long long)relPos.y*endVec.y < 0 ) + return false; + return true; - - wxPoint startVec = wxPoint( m_End.x - m_Start.x, m_End.y - m_Start.y ); - wxPoint endVec = m_End - m_Start; - RotatePoint( &endVec, -m_Angle ); - - // Check dot products - if( (long long)relPos.x*startVec.x + (long long)relPos.y*startVec.y < 0 ) - return false; - - if( (long long)relPos.x*endVec.x + (long long)relPos.y*endVec.y < 0 ) - return false; - - return true; + } } - } - break; + break; case S_CURVE: for( unsigned int i= 1; i < m_BezierPoints.size(); i++) @@ -499,7 +506,7 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect ) const { switch( m_Shape ) { - case S_CIRCLE: + case S_CIRCLE: { int radius = GetRadius(); @@ -512,14 +519,17 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect ) const } break; - case S_ARC: - case S_SEGMENT: - if( aRect.Contains( GetStart() ) ) - return true; + case S_ARC: + case S_SEGMENT: + if( aRect.Contains( GetStart() ) ) + return true; - if( aRect.Contains( GetEnd() ) ) - return true; - break; + if( aRect.Contains( GetEnd() ) ) + return true; + break; + + default: + ; } return false; } diff --git a/pcbnew/class_drawsegment.h b/pcbnew/class_drawsegment.h index d44a63146c..e2f0a8f3f0 100644 --- a/pcbnew/class_drawsegment.h +++ b/pcbnew/class_drawsegment.h @@ -43,15 +43,15 @@ class MODULE; class DRAWSEGMENT : public BOARD_ITEM { protected: - int m_Width; ///< thickness of lines ... - wxPoint m_Start; ///< Line start point or Circle and Arc center - wxPoint m_End; ///< Line end point or circle and arc start point + int m_Width; ///< thickness of lines ... + wxPoint m_Start; ///< Line start point or Circle and Arc center + wxPoint m_End; ///< Line end point or circle and arc start point - int m_Shape; ///< Shape: line, Circle, Arc - int m_Type; ///< Used in complex associations ( Dimensions.. ) - double m_Angle; ///< Used only for Arcs: Arc angle in 1/10 deg - wxPoint m_BezierC1; ///< Bezier Control Point 1 - wxPoint m_BezierC2; ///< Bezier Control Point 2 + STROKE_T m_Shape; ///< Shape: line, Circle, Arc + int m_Type; ///< Used in complex associations ( Dimensions.. ) + double m_Angle; ///< Used only for Arcs: Arc angle in 1/10 deg + wxPoint m_BezierC1; ///< Bezier Control Point 1 + wxPoint m_BezierC2; ///< Bezier Control Point 2 std::vector m_BezierPoints; std::vector m_PolyPoints; @@ -80,11 +80,11 @@ public: void SetAngle( double aAngle ); // encapsulates the transition to degrees double GetAngle() const { return m_Angle; } - void SetType( int aType ) { m_Type = aType; } - int GetType() const { return m_Type; } + void SetType( int aType ) { m_Type = aType; } + int GetType() const { return m_Type; } - void SetShape( int aShape ) { m_Shape = aShape; } - int GetShape() const { return m_Shape; } + void SetShape( STROKE_T aShape ) { m_Shape = aShape; } + STROKE_T GetShape() const { return m_Shape; } void SetBezControl1( const wxPoint& aPoint ) { m_BezierC1 = aPoint; } const wxPoint& GetBezControl1() const { return m_BezierC1; } @@ -92,8 +92,8 @@ public: void SetBezControl2( const wxPoint& aPoint ) { m_BezierC2 = aPoint; } const wxPoint& GetBezControl2() const { return m_BezierC2; } - void SetPosition( const wxPoint& aPos ) { m_Start = aPos; } // override - const wxPoint& GetPosition() const { return m_Start; } // override + void SetPosition( const wxPoint& aPos ) { m_Start = aPos; } // override + const wxPoint& GetPosition() const { return m_Start; } // override /** * Function GetStart diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 130d0d2c21..2bb62abac1 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -294,6 +294,11 @@ public: m_Value->m_Text = aValue; } + /// read/write accessors: + TEXTE_MODULE& Value() { return *m_Value; } + TEXTE_MODULE& Reference() { return *m_Reference; } + + /** * Function FindPadByName * returns a D_PAD* with a matching name. Note that names may not be diff --git a/pcbnew/class_text_mod.h b/pcbnew/class_text_mod.h index 68c6b0c461..55fcbc9c18 100644 --- a/pcbnew/class_text_mod.h +++ b/pcbnew/class_text_mod.h @@ -88,14 +88,14 @@ public: } /// @deprecated it seems - void SetType( int aType ) { m_Type = aType; } - int GetType() const { return m_Type; } + void SetType( int aType ) { m_Type = aType; } + int GetType() const { return m_Type; } void SetVisible( bool isVisible ) { m_NoShow = !isVisible; } - bool IsVisible() const { return !m_NoShow; } + bool IsVisible() const { return !m_NoShow; } - void SetPos0( const wxPoint& aPos ) { m_Pos0 = aPos; } - const wxPoint& GetPos0() const { return m_Pos0; } + void SetPos0( const wxPoint& aPos ) { m_Pos0 = aPos; } + const wxPoint& GetPos0() const { return m_Pos0; } void Copy( TEXTE_MODULE* source ); // copy structure diff --git a/pcbnew/eagle_plugin.cpp b/pcbnew/eagle_plugin.cpp index 24e9df6325..7e0338e9be 100644 --- a/pcbnew/eagle_plugin.cpp +++ b/pcbnew/eagle_plugin.cpp @@ -59,6 +59,8 @@ our error message. #include #include #include +#include + #include #include #include @@ -70,17 +72,75 @@ using namespace boost::property_tree; typedef EAGLE_PLUGIN::BIU BIU; typedef PTREE::const_assoc_iterator CA_ITER; typedef PTREE::const_iterator CITER; +typedef std::pair CA_ITER_RANGE; typedef MODULE_MAP::iterator MODULE_ITER; typedef MODULE_MAP::const_iterator MODULE_CITER; +typedef boost::optional opt_string; +typedef boost::optional opt_int; +typedef boost::optional opt_double; +typedef boost::optional 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 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 ) { - // 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; - return key; } @@ -164,7 +224,7 @@ void EAGLE_PLUGIN::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* a void EAGLE_PLUGIN::init( PROPERTIES* aProperties ) { - m_modules.clear(); + m_templates.clear(); m_board = NULL; m_props = aProperties; @@ -251,27 +311,88 @@ void EAGLE_PLUGIN::loadAllSections( CPTREE& aEagleBoard, const std::string& aXpa std::string xpath; { - xpath = aXpath + '.' + "libraries"; - CPTREE& libs = aEagleBoard.get_child( "libraries" ); - loadModules( libs, xpath ); + xpath = aXpath + '.' + "plain"; + CPTREE& plain = aEagleBoard.get_child( "plain" ); + loadPlain( plain, xpath ); + } + + { + xpath = aXpath + '.' + "libraries"; + CPTREE& libs = aEagleBoard.get_child( "libraries" ); + 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"; CPTREE& signals = aEagleBoard.get_child( "signals" ); loadNetsAndTracks( signals, xpath ); } - ; } -void EAGLE_PLUGIN::loadModules( CPTREE& aLibs, const std::string& aXpath ) +void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics, const std::string& aXpath ) { - m_modules.clear(); + 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" ) ) + { + } + } +} + + +void EAGLE_PLUGIN::loadLibraries( CPTREE& aLibs, const std::string& aXpath ) +{ for( CITER library = aLibs.begin(); library != aLibs.end(); ++library ) { const std::string& lib_name = library->second.get( ".name" ); @@ -291,8 +412,8 @@ void EAGLE_PLUGIN::loadModules( CPTREE& aLibs, const std::string& aXpath ) MODULE* m = makeModule( package->second, pack_name ); - // add the templating MODULE to the MODULE template factory "m_modules" - std::pair r = m_modules.insert( key, m ); + // add the templating MODULE to the MODULE template factory "m_templates" + std::pair r = m_templates.insert( key, m ); if( !r.second ) { @@ -301,8 +422,8 @@ void EAGLE_PLUGIN::loadModules( CPTREE& aLibs, const std::string& aXpath ) wxString emsg = wxString::Format( _( " name:'%s' duplicated in eagle :'%s'" ), - GetChars( lib ), - GetChars( pkg ) + GetChars( pkg ), + GetChars( lib ) ); THROW_IO_ERROR( emsg ); } @@ -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( "" ); + + /* + + a '*' means zero or more times + + + + */ + + std::string name = attrs.get( "name" ); + std::string library = attrs.get( "library" ); + std::string package = attrs.get( "package" ); + std::string value = attrs.get( "value" ); + + double x = attrs.get( "x" ); + double y = attrs.get( "y" ); + + opt_string rot = attrs.get_optional( "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( "" ); + EWIRE w; w.x1 = attribs.get( "x1" ); w.y1 = attribs.get( "y1" ); @@ -323,18 +567,101 @@ EWIRE EAGLE_PLUGIN::wire( CPTREE aWire ) const w.y2 = attribs.get( "y2" ); w.width = attribs.get( "width" ); w.layer = attribs.get( "layer" ); - return w; } +ECIRCLE EAGLE_PLUGIN::ecircle( CPTREE& aCircle ) const +{ + CPTREE& attribs = aCircle.get_child( "" ); + ECIRCLE c; + + c.x = attribs.get( "x" ); + c.y = attribs.get( "y" ); + c.radius = attribs.get( "radius" ); + c.width = attribs.get( "width" ); + c.layer = attribs.get( "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( "" ); + EATTR a; + + /* + + or context -- + constant %Bool; "no" -- only in context -- + > + */ + + a.name = attribs.get( "name" ); // #REQUIRED + a.value = attribs.get_optional( "value" ); + + a.x = attribs.get_optional( "x" ); + a.y = attribs.get_optional( "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( "size" ); + a.ratio = attribs.get_optional( "ratio" ); + + opt_string rot = attribs.get_optional( "rot" ); + if( rot ) + { + a.erot = erot( *rot ); + } + + opt_string display = attribs.get_optional( "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 { std::auto_ptr m( new MODULE( NULL ) ); m->SetLibRef( FROM_UTF8( aPkgName.c_str() ) ); - boost::optional description = aPackage.get_optional( "description" ); + opt_string description = aPackage.get_optional( "description" ); if( description ) m->SetDescription( FROM_UTF8( description->c_str() ) ); @@ -373,16 +700,16 @@ MODULE* EAGLE_PLUGIN::makeModule( CPTREE& aPackage, const std::string& aPkgName void EAGLE_PLUGIN::packageWire( MODULE* aModule, CPTREE aTree ) const { - EWIRE w = wire( aTree ); - - int layer = kicad_layer( w.layer ); - wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) ); - wxPoint end( kicad_x( w.x2 ), kicad_y( w.x2 ) ); - int width = kicad( w.width ); - EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_SEGMENT ); aModule->m_Drawings.PushBack( dwg ); + EWIRE w = ewire( aTree ); + + wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) ); + wxPoint end( kicad_x( w.x2 ), kicad_y( w.x2 ) ); + int layer = kicad_layer( w.layer ); + int width = kicad( w.width ); + dwg->SetStart0( start ); dwg->SetEnd0( end ); dwg->SetLayer( layer ); @@ -392,7 +719,95 @@ void EAGLE_PLUGIN::packageWire( 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( "" ); + + /* from /doc/eagle.dtd + + + + */ + + 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( "x" ); + double y = attrs.get( "y" ); + double drill = attrs.get( "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( "diameter" ); + opt_string shape = attrs.get_optional( "shape" ); + opt_string rot = attrs.get_optional( "rot" ); + opt_string stop = attrs.get_optional( "stop" ); + opt_string thermals = attrs.get_optional( "thermals" ); + opt_string first = attrs.get_optional( "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" + { + // + + 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. } @@ -428,7 +843,82 @@ void EAGLE_PLUGIN::packageHole( 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( "" ); + + /* from /doc/eagle.dtd + + + */ + + 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( "x" ); + double y = attrs.get( "y" ); + double dx = attrs.get( "dx" ); + double dy = attrs.get( "dy" ); + int layer = attrs.get( "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( "roundness" ); + opt_string rot = attrs.get_optional( "rot" ); + opt_string stop = attrs.get_optional( "stop" ); + opt_string thermals = attrs.get_optional( "thermals" ); + opt_string cream = attrs.get_optional( "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. } @@ -487,11 +977,10 @@ void EAGLE_PLUGIN::loadNetsAndTracks( CPTREE& aSignals, const std::string& aXpat m_board->AppendNet( new NETINFO_ITEM( m_board, netName, netCode ) ); - std::pair 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 ) { - EWIRE w = wire( wit->second ); + EWIRE w = ewire( wit->second ); TRACK* t = new TRACK( m_board ); @@ -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 ) { - return aLayer; + int ret; + + switch( aLayer ) // translate eagle layer to pcbnew layer + { + 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; } diff --git a/pcbnew/eagle_plugin.h b/pcbnew/eagle_plugin.h index 852b0c3f72..b7a05d314e 100644 --- a/pcbnew/eagle_plugin.h +++ b/pcbnew/eagle_plugin.h @@ -55,15 +55,10 @@ namespace boost { typedef boost::property_tree::ptree PTREE; typedef const PTREE CPTREE; -struct EWIRE ///< Eagle wire -{ - double x1; - double y1; - double x2; - double y2; - double width; - int layer; -}; +struct EWIRE; +struct EROT; +struct EATTR; +struct ECIRCLE; /** @@ -104,26 +99,26 @@ public: EAGLE_PLUGIN(); ~EAGLE_PLUGIN(); - private: - MODULE_MAP m_modules; ///< is a factory by use of MODULE copy constructor, - ///< lookup is based on libname.packagename + MODULE_MAP m_templates; ///< is part of a MODULE factory that operates + ///< using copy construction. + ///< lookup key is libname.packagename - PROPERTIES* m_props; ///< passed via Save() or Load(), no ownership, may be NULL. + PROPERTIES* m_props; ///< passed via Save() or Load(), no ownership, may be NULL. - BOARD* m_board; ///< which BOARD, no ownership here - double mm_per_biu; ///< how many mm in each BIU - double biu_per_mm; ///< how many bius in a mm + BOARD* m_board; ///< which BOARD, no ownership here + double mm_per_biu; ///< how many mm in each BIU + double biu_per_mm; ///< how many bius in a mm /// initialize PLUGIN like a constructor would, and futz with fresh BOARD if needed. void init( PROPERTIES* aProperties ); int kicad( double d ) const; - int kicad_y( double y ) const { return kicad( y ); } + int kicad_y( double y ) const { return -kicad( y ); } int kicad_x( double x ) const { return kicad( x ); } - int kicad_layer( int aLayer ) const; + static int kicad_layer( int aLayer ); double eagle( BIU d ) const { return mm_per_biu * d; } double eagle_x( BIU x ) const { return eagle( x ); } @@ -202,16 +197,32 @@ private: void loadAllSections( CPTREE& aEagleBoard, const std::string& aXpath, bool aAppendToMe ); + void loadPlain( CPTREE& aPlain, const std::string& aXpath ); + void loadNetsAndTracks( CPTREE& aSignals, const std::string& aXpath ); - void loadModules( CPTREE& aLibs, const std::string& aXpath ); + void loadLibraries( CPTREE& aLibs, const std::string& aXpath ); + + void loadElements( CPTREE& aElements, const std::string& aXpath ); /** - * Function wire + * Function ewire * converts a 's xml attributes to binary without additional conversion. - * @return EWIRE - an Eagle object in binary. + * @param aResult is an EWIRE to fill in with the data converted to binary. */ - EWIRE wire( CPTREE aWire ) const; + EWIRE ewire( CPTREE& aWire ) const; + + ECIRCLE ecircle( CPTREE& aCircle ) const; + + EROT erot( const std::string& aRot ) const; + + /** + * Function eattr + * parses an Eagle "attribute" element. Note that an attribute element + * is different than an XML element attribute. The attribute element is a + * full XML node in and of itself, and has attributes of its own. Blame Eagle. + */ + EATTR eattr( CPTREE& aAttribute ) const; /** * Function fmtDEG diff --git a/pcbnew/edgemod.cpp b/pcbnew/edgemod.cpp index f1d7b5beb9..ac959dec6d 100644 --- a/pcbnew/edgemod.cpp +++ b/pcbnew/edgemod.cpp @@ -310,7 +310,7 @@ static void Abort_Move_ModuleOutline( EDA_DRAW_PANEL* Panel, wxDC* DC ) EDGE_MODULE* FOOTPRINT_EDIT_FRAME::Begin_Edge_Module( EDGE_MODULE* aEdge, wxDC* DC, - int type_edge ) + STROKE_T type_edge ) { MODULE* module = GetBoard()->m_Modules; int angle = 0; diff --git a/pcbnew/editedge.cpp b/pcbnew/editedge.cpp index b834b4e659..66a5171ac2 100644 --- a/pcbnew/editedge.cpp +++ b/pcbnew/editedge.cpp @@ -231,7 +231,7 @@ static void Abort_EditEdge( EDA_DRAW_PANEL* Panel, wxDC* DC ) /* Initialize the drawing of a segment of type other than trace. */ -DRAWSEGMENT* PCB_EDIT_FRAME::Begin_DrawSegment( DRAWSEGMENT* Segment, int shape, wxDC* DC ) +DRAWSEGMENT* PCB_EDIT_FRAME::Begin_DrawSegment( DRAWSEGMENT* Segment, STROKE_T shape, wxDC* DC ) { int s_large; DRAWSEGMENT* DrawItem; diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp index c74b983099..fe6211c6a3 100644 --- a/pcbnew/legacy_plugin.cpp +++ b/pcbnew/legacy_plugin.cpp @@ -1238,7 +1238,7 @@ void LEGACY_PLUGIN::loadPAD( MODULE* aModule ) pos.y = biuParse( data ); pad->SetPos0( pos ); - pad->SetPosition( pos ); + // pad->SetPosition( pos ); set at function return } else if( TESTLINE( "Le" ) ) @@ -1291,7 +1291,10 @@ void LEGACY_PLUGIN::loadPAD( MODULE* aModule ) else if( TESTLINE( "$EndPAD" ) ) { - wxPoint padpos = pad->GetPosition(); + // 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 = pad->GetPos0(); RotatePoint( &padpos, aModule->GetOrientation() ); @@ -1634,7 +1637,7 @@ void LEGACY_PLUGIN::loadPCB_LINE() if( width < 0 ) width = 0; - dseg->SetShape( shape ); + dseg->SetShape( STROKE_T( shape ) ); dseg->SetWidth( width ); dseg->SetStart( wxPoint( start_x, start_y ) ); dseg->SetEnd( wxPoint( end_x, end_y ) ); diff --git a/pcbnew/modedit_onclick.cpp b/pcbnew/modedit_onclick.cpp index eb9e3b8d70..3a343f3523 100644 --- a/pcbnew/modedit_onclick.cpp +++ b/pcbnew/modedit_onclick.cpp @@ -81,7 +81,7 @@ void FOOTPRINT_EDIT_FRAME::OnLeftClick( wxDC* DC, const wxPoint& MousePos ) case ID_MODEDIT_LINE_TOOL: if( !item || item->GetFlags() == 0 ) { - int shape = S_SEGMENT; + STROKE_T shape = S_SEGMENT; if( GetToolId() == ID_MODEDIT_CIRCLE_TOOL ) shape = S_CIRCLE; @@ -107,7 +107,7 @@ void FOOTPRINT_EDIT_FRAME::OnLeftClick( wxDC* DC, const wxPoint& MousePos ) } else if( ( (EDGE_MODULE*) item )->GetShape() == S_SEGMENT ) { - SetCurItem( Begin_Edge_Module( (EDGE_MODULE*) item, DC, 0 ) ); + SetCurItem( Begin_Edge_Module( (EDGE_MODULE*) item, DC, S_SEGMENT ) ); } else { diff --git a/pcbnew/module_editor_frame.h b/pcbnew/module_editor_frame.h index dc79ce4fb5..b81a7aad77 100644 --- a/pcbnew/module_editor_frame.h +++ b/pcbnew/module_editor_frame.h @@ -319,7 +319,7 @@ public: * @param type_edge = S_SEGMENT,S_ARC .. * @return the new created edge. */ - EDGE_MODULE* Begin_Edge_Module( EDGE_MODULE* Edge, wxDC* DC, int type_edge ); + EDGE_MODULE* Begin_Edge_Module( EDGE_MODULE* Edge, wxDC* DC, STROKE_T type_edge ); /** * Function End_Edge_Module diff --git a/pcbnew/onleftclick.cpp b/pcbnew/onleftclick.cpp index 644b11ca64..8749239c11 100644 --- a/pcbnew/onleftclick.cpp +++ b/pcbnew/onleftclick.cpp @@ -229,37 +229,37 @@ void PCB_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) case ID_PCB_CIRCLE_BUTT: case ID_PCB_ARC_BUTT: case ID_PCB_ADD_LINE_BUTT: - { - int shape = S_SEGMENT; - - if( GetToolId() == ID_PCB_CIRCLE_BUTT ) - shape = S_CIRCLE; - - if( GetToolId() == ID_PCB_ARC_BUTT ) - shape = S_ARC; - - if( getActiveLayer() <= LAST_COPPER_LAYER ) { - DisplayError( this, _( "Graphic not authorized on Copper layers" ) ); - break; - } + STROKE_T shape = S_SEGMENT; - if( (DrawStruct == NULL) || (DrawStruct->GetFlags() == 0) ) - { - DrawStruct = (BOARD_ITEM*) Begin_DrawSegment( NULL, shape, aDC ); - SetCurItem( DrawStruct ); - m_canvas->SetAutoPanRequest( true ); - } - else if( DrawStruct - && (DrawStruct->Type() == PCB_LINE_T) - && DrawStruct->IsNew() ) - { - DrawStruct = (BOARD_ITEM*) Begin_DrawSegment( (DRAWSEGMENT*) DrawStruct, shape, aDC ); - SetCurItem( DrawStruct ); - m_canvas->SetAutoPanRequest( true ); + if( GetToolId() == ID_PCB_CIRCLE_BUTT ) + shape = S_CIRCLE; + + if( GetToolId() == ID_PCB_ARC_BUTT ) + shape = S_ARC; + + if( getActiveLayer() <= LAST_COPPER_LAYER ) + { + DisplayError( this, _( "Graphic not authorized on Copper layers" ) ); + break; + } + + if( (DrawStruct == NULL) || (DrawStruct->GetFlags() == 0) ) + { + DrawStruct = (BOARD_ITEM*) Begin_DrawSegment( NULL, shape, aDC ); + SetCurItem( DrawStruct ); + m_canvas->SetAutoPanRequest( true ); + } + else if( DrawStruct + && (DrawStruct->Type() == PCB_LINE_T) + && DrawStruct->IsNew() ) + { + DrawStruct = (BOARD_ITEM*) Begin_DrawSegment( (DRAWSEGMENT*) DrawStruct, shape, aDC ); + SetCurItem( DrawStruct ); + m_canvas->SetAutoPanRequest( true ); + } } break; - } case ID_TRACK_BUTT: if( getActiveLayer() > LAST_COPPER_LAYER )