From a71c669543335a15fcdd92f79150b634f7b9bf9d Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Thu, 24 Nov 2022 19:42:41 +0100 Subject: [PATCH] Altium importer: try to import elliptical arcs rather to skip them. Some schematics use elliptical arcs to describe usual arcs. --- .../sch_plugins/altium/altium_parser_sch.cpp | 17 ++-- .../sch_plugins/altium/altium_parser_sch.h | 12 +-- .../sch_plugins/altium/sch_altium_plugin.cpp | 85 ++++++++++--------- 3 files changed, 64 insertions(+), 50 deletions(-) diff --git a/eeschema/sch_plugins/altium/altium_parser_sch.cpp b/eeschema/sch_plugins/altium/altium_parser_sch.cpp index 18dfe2c384..fe294ebc5a 100644 --- a/eeschema/sch_plugins/altium/altium_parser_sch.cpp +++ b/eeschema/sch_plugins/altium/altium_parser_sch.cpp @@ -392,20 +392,25 @@ ASCH_ROUND_RECTANGLE::ASCH_ROUND_RECTANGLE( const std::map& ASCH_ARC::ASCH_ARC( const std::map& aProps ) { - wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::ARC ); + m_IsElliptical = ReadRecord( aProps ) == ALTIUM_SCH_RECORD::ELLIPTICAL_ARC; + wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::ARC || m_IsElliptical ); ownerindex = ReadOwnerIndex( aProps ); ownerpartid = ReadOwnerPartId( aProps ); ownerpartdisplaymode = ALTIUM_PARSER::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 ); - center = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ), + m_Center = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ), -ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) ); - radius = ReadKiCadUnitFrac( aProps, "RADIUS" ); + m_Radius = ReadKiCadUnitFrac( aProps, "RADIUS" ); + m_SecondaryRadius = m_Radius; - startAngle = ALTIUM_PARSER::ReadDouble( aProps, "STARTANGLE", 0 ); - endAngle = ALTIUM_PARSER::ReadDouble( aProps, "ENDANGLE", 0 ); + if( m_IsElliptical ) + m_SecondaryRadius = ReadKiCadUnitFrac( aProps, "SECONDARYRADIUS" ); - lineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" ); + m_StartAngle = ALTIUM_PARSER::ReadDouble( aProps, "STARTANGLE", 0 ); + m_EndAngle = ALTIUM_PARSER::ReadDouble( aProps, "ENDANGLE", 0 ); + + m_LineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" ); } diff --git a/eeschema/sch_plugins/altium/altium_parser_sch.h b/eeschema/sch_plugins/altium/altium_parser_sch.h index a2f5fe425d..646805dad2 100644 --- a/eeschema/sch_plugins/altium/altium_parser_sch.h +++ b/eeschema/sch_plugins/altium/altium_parser_sch.h @@ -397,12 +397,14 @@ struct ASCH_ARC int ownerpartid; int ownerpartdisplaymode; - VECTOR2I center; - int radius; - double startAngle; - double endAngle; + bool m_IsElliptical; + VECTOR2I m_Center; + int m_Radius; + int m_SecondaryRadius; + double m_StartAngle; + double m_EndAngle; - int lineWidth; + int m_LineWidth; explicit ASCH_ARC( const std::map& aProps ); }; diff --git a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp index af23b94f04..dc9dd2ac8c 100644 --- a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp +++ b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp @@ -583,8 +583,6 @@ void SCH_ALTIUM_PLUGIN::ParseFileHeader( const ALTIUM_COMPOUND_FILE& aAltiumSchF break; case ALTIUM_SCH_RECORD::ELLIPTICAL_ARC: - break; - case ALTIUM_SCH_RECORD::ARC: ParseArc( properties ); break; @@ -810,7 +808,7 @@ void SCH_ALTIUM_PLUGIN::ParseComponent( int aIndex, symbol->SetPosition( elem.location + m_sheetOffset ); // TODO: keep it simple for now, and only set position. - //component->SetOrientation( elem.orientation ); + // component->SetOrientation( elem.orientation ); symbol->SetLibId( libId ); symbol->SetUnit( std::max( 0, elem.currentpartid ) ); @@ -1521,36 +1519,47 @@ void SCH_ALTIUM_PLUGIN::ParseRoundRectangle( const std::map& void SCH_ALTIUM_PLUGIN::ParseArc( const std::map& aProperties ) { + // The Arc can be ALTIUM_SCH_RECORD::ELLIPTICAL_ARC or ALTIUM_SCH_RECORD::ARC + // Elliptical arcs are not handled in kicad. So use an arc instead + // TODO: handle elliptical arc better. + ASCH_ARC elem( aProperties ); SCH_SCREEN* screen = getCurrentScreen(); wxCHECK( screen, /* void */ ); + int arc_radius = elem.m_Radius; + + // Try to approxiammate this ellipse by an arc. use the biggest of radius and secondary radius + // One can of course use another recipe + if( elem.m_IsElliptical ) + arc_radius = std::max( elem.m_Radius, elem.m_SecondaryRadius ); + if( elem.ownerpartid == ALTIUM_COMPONENT_NONE ) { - if( elem.startAngle == 0 && ( elem.endAngle == 0 || elem.endAngle == 360 ) ) + if( elem.m_StartAngle == 0 && ( elem.m_EndAngle == 0 || elem.m_EndAngle == 360 ) ) { SCH_SHAPE* circle = new SCH_SHAPE( SHAPE_T::CIRCLE ); - circle->SetPosition( elem.center + m_sheetOffset ); - circle->SetEnd( circle->GetPosition() + VECTOR2I( elem.radius, 0 ) ); - circle->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); + circle->SetPosition( elem.m_Center + m_sheetOffset ); + circle->SetEnd( circle->GetPosition() + VECTOR2I( arc_radius, 0 ) ); + circle->SetStroke( STROKE_PARAMS( elem.m_LineWidth, PLOT_DASH_TYPE::SOLID ) ); screen->Append( circle ); } else { SCH_SHAPE* arc = new SCH_SHAPE( SHAPE_T::ARC ); - EDA_ANGLE includedAngle( elem.endAngle - elem.startAngle, DEGREES_T ); - EDA_ANGLE startAngle( elem.endAngle, DEGREES_T ); - VECTOR2I startOffset( KiROUND( elem.radius * startAngle.Cos() ), - -KiROUND( elem.radius * startAngle.Sin() ) ); + EDA_ANGLE includedAngle( elem.m_EndAngle - elem.m_StartAngle, DEGREES_T ); + EDA_ANGLE startAngle( elem.m_EndAngle, DEGREES_T ); + VECTOR2I startOffset( KiROUND( arc_radius * startAngle.Cos() ), + -KiROUND( arc_radius * startAngle.Sin() ) ); - arc->SetCenter( elem.center + m_sheetOffset ); - arc->SetStart( elem.center + startOffset + m_sheetOffset ); + arc->SetCenter( elem.m_Center + m_sheetOffset ); + arc->SetStart( elem.m_Center + startOffset + m_sheetOffset ); arc->SetArcAngleAndEnd( includedAngle.Normalize(), true ); - arc->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); + arc->SetStroke( STROKE_PARAMS( elem.m_LineWidth, PLOT_DASH_TYPE::SOLID ) ); screen->Append( arc ); } @@ -1573,16 +1582,16 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map& aPropertie SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); - if( elem.startAngle == 0 && ( elem.endAngle == 0 || elem.endAngle == 360 ) ) + if( elem.m_StartAngle == 0 && ( elem.m_EndAngle == 0 || elem.m_EndAngle == 360 ) ) { LIB_SHAPE* circle = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::CIRCLE ); libSymbolIt->second->AddDrawItem( circle ); circle->SetUnit( std::max( 0, elem.ownerpartid ) ); - circle->SetPosition( GetRelativePosition( elem.center + m_sheetOffset, symbol ) ); - circle->SetEnd( circle->GetPosition() + VECTOR2I( elem.radius, 0 ) ); - circle->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); + circle->SetPosition( GetRelativePosition( elem.m_Center + m_sheetOffset, symbol ) ); + circle->SetEnd( circle->GetPosition() + VECTOR2I( arc_radius, 0 ) ); + circle->SetStroke( STROKE_PARAMS( elem.m_LineWidth, PLOT_DASH_TYPE::SOLID ) ); } else { @@ -1590,19 +1599,19 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map& aPropertie libSymbolIt->second->AddDrawItem( arc ); arc->SetUnit( std::max( 0, elem.ownerpartid ) ); - arc->SetCenter( GetRelativePosition( elem.center + m_sheetOffset, symbol ) ); + arc->SetCenter( GetRelativePosition( elem.m_Center + m_sheetOffset, symbol ) ); - VECTOR2I arcStart( elem.radius, 0 ); - RotatePoint( arcStart, -EDA_ANGLE( elem.startAngle, DEGREES_T ) ); + VECTOR2I arcStart( arc_radius, 0 ); + RotatePoint( arcStart, -EDA_ANGLE( elem.m_StartAngle, DEGREES_T ) ); arcStart += arc->GetCenter(); arc->SetStart( arcStart ); - VECTOR2I arcEnd( elem.radius, 0 ); - RotatePoint( arcEnd, -EDA_ANGLE( elem.endAngle, DEGREES_T ) ); + VECTOR2I arcEnd( arc_radius, 0 ); + RotatePoint( arcEnd, -EDA_ANGLE( elem.m_EndAngle, DEGREES_T ) ); arcEnd += arc->GetCenter(); arc->SetEnd( arcEnd ); - arc->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); + arc->SetStroke( STROKE_PARAMS( elem.m_LineWidth, PLOT_DASH_TYPE::SOLID ) ); } } } @@ -2463,11 +2472,13 @@ void SCH_ALTIUM_PLUGIN::ParsePort( const ASCH_PORT& aElem ) SCH_LABEL_BASE* label; // TODO: detect correct label type depending on sheet settings, etc. - //{ - // label = new SCH_HIERLABEL( elem.location + m_sheetOffset, elem.name ); - //} - + #if 0 // Set to 1 to use SCH_HIERLABEL label, 0 to use SCH_GLOBALLABEL + { + label = new SCH_HIERLABEL label, 0 to use ( position, aElem.Name ); + } + #else label = new SCH_GLOBALLABEL( position, aElem.Name ); + #endif switch( aElem.IOtype ) { @@ -2516,7 +2527,9 @@ void SCH_ALTIUM_PLUGIN::ParsePort( const ASCH_PORT& aElem ) label->AutoplaceFields( screen, false ); // Default "Sheet References" field should be hidden, at least for now - label->GetFields()[0].SetVisible( false ); + if( label->GetFields().size() > 0 ) + label->GetFields()[0].SetVisible( false ); + label->SetFlags( IS_NEW ); screen->Append( label ); @@ -2832,20 +2845,14 @@ void SCH_ALTIUM_PLUGIN::ParseDesignator( const std::map& aPr bool emptyRef = elem.text.IsEmpty(); symbol->SetRef( &m_sheetPath, emptyRef ? "#GRAPHIC" : elem.text ); - SCH_FIELD* field = symbol->GetField( VALUE_FIELD ); - - #if 0 // I am not sure value and ref should be invisible just because emptyRef is true // I have examples with this criteria fully incorrect. - if ( emptyRef ) - field->SetVisible( false ); + bool visible = !emptyRef; - field = symbol->GetField( REFERENCE_FIELD ); - - if ( emptyRef ) - field->SetVisible( false ); - #endif + symbol->GetField( VALUE_FIELD )->SetVisible( visible ); + symbol->GetField( REFERENCE_FIELD )->SetVisible( visible ); + SCH_FIELD* field = symbol->GetField( REFERENCE_FIELD ); field->SetPosition( elem.location + m_sheetOffset ); SetTextPositioning( field, elem.justification, elem.orientation ); }