Import Altium radial dimensions to KiCad radial dimensions.

(We converted them to KiCad leaders in 6.0 because we didn't have
radial dimensions yet.)

Fixes https://gitlab.com/kicad/code/kicad/issues/8789
This commit is contained in:
Jeff Young 2021-07-24 20:05:34 +01:00
parent 295a6408c3
commit 3c0e3610e2
2 changed files with 69 additions and 91 deletions

View File

@ -561,7 +561,7 @@ void ALTIUM_PCB::Parse( const CFB::CompoundFileReader& aReader,
// the dimension record. (Yes, there is a REFERENCE0OBJECTID, but it doesn't point to the // the dimension record. (Yes, there is a REFERENCE0OBJECTID, but it doesn't point to the
// dimensioned object.) We attempt to plug this gap by finding a colocated arc or circle // dimensioned object.) We attempt to plug this gap by finding a colocated arc or circle
// and using its radius. If there are more than one such arcs/circles, well, :shrug:. // and using its radius. If there are more than one such arcs/circles, well, :shrug:.
for( PCB_DIMENSION_BASE* dim : m_radialDimensions ) for( PCB_DIM_RADIAL* dim : m_radialDimensions )
{ {
int radius = 0; int radius = 0;
@ -599,17 +599,16 @@ void ALTIUM_PCB::Parse( const CFB::CompoundFileReader& aReader,
} }
} }
// Force a measured value, calculate the value text, and then stick it into the override // Move the radius point onto the circumference
// text (since leaders don't have calculated text).
dim->SetMeasuredValue( radius );
dim->SetText( dim->GetPrefix() + dim->GetValueText() + dim->GetSuffix() );
dim->SetPrefix( wxEmptyString );
dim->SetSuffix( wxEmptyString );
// Move the leader line start to the radius point
VECTOR2I radialLine = dim->GetEnd() - dim->GetStart(); VECTOR2I radialLine = dim->GetEnd() - dim->GetStart();
radialLine = radialLine.Resize( radius ); int totalLength = radialLine.EuclideanNorm();
dim->SetStart( dim->GetStart() + (wxPoint) radialLine );
// Enforce a minimum on the radialLine else we won't have enough precision to get the
// angle from it.
radialLine = radialLine.Resize( std::max( radius, 2 ) );
dim->SetEnd( dim->GetStart() + (wxPoint) radialLine );
dim->SetLeaderLength( totalLength - radius );
dim->Update();
} }
// center board // center board
@ -651,34 +650,32 @@ int ALTIUM_PCB::GetNetCode( uint16_t aId ) const
const ARULE6* ALTIUM_PCB::GetRule( ALTIUM_RULE_KIND aKind, const wxString& aName ) const const ARULE6* ALTIUM_PCB::GetRule( ALTIUM_RULE_KIND aKind, const wxString& aName ) const
{ {
const auto rules = m_rules.find( aKind ); const auto rules = m_rules.find( aKind );
if( rules == m_rules.end() ) if( rules == m_rules.end() )
{
return nullptr; return nullptr;
}
for( const ARULE6& rule : rules->second ) for( const ARULE6& rule : rules->second )
{ {
if( rule.name == aName ) if( rule.name == aName )
{
return &rule; return &rule;
} }
}
return nullptr; return nullptr;
} }
const ARULE6* ALTIUM_PCB::GetRuleDefault( ALTIUM_RULE_KIND aKind ) const const ARULE6* ALTIUM_PCB::GetRuleDefault( ALTIUM_RULE_KIND aKind ) const
{ {
const auto rules = m_rules.find( aKind ); const auto rules = m_rules.find( aKind );
if( rules == m_rules.end() ) if( rules == m_rules.end() )
{
return nullptr; return nullptr;
}
for( const ARULE6& rule : rules->second ) for( const ARULE6& rule : rules->second )
{ {
if( rule.scope1expr == "All" && rule.scope2expr == "All" ) if( rule.scope1expr == "All" && rule.scope2expr == "All" )
{
return &rule; return &rule;
} }
}
return nullptr; return nullptr;
} }
@ -713,18 +710,21 @@ void ALTIUM_PCB::ParseBoard6Data( const CFB::CompoundFileReader& aReader,
ABOARD6 elem( reader ); ABOARD6 elem( reader );
if( reader.GetRemainingBytes() != 0 ) if( reader.GetRemainingBytes() != 0 )
{
THROW_IO_ERROR( "Board6 stream is not fully parsed" ); THROW_IO_ERROR( "Board6 stream is not fully parsed" );
}
m_board->GetDesignSettings().SetAuxOrigin( elem.sheetpos ); m_board->GetDesignSettings().SetAuxOrigin( elem.sheetpos );
m_board->GetDesignSettings().SetGridOrigin( elem.sheetpos ); m_board->GetDesignSettings().SetGridOrigin( elem.sheetpos );
// read layercount from stackup, because LAYERSETSCOUNT is not always correct?! // read layercount from stackup, because LAYERSETSCOUNT is not always correct?!
size_t layercount = 0; size_t layercount = 0;
for( size_t i = static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER ); size_t layer = static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER );
i < elem.stackup.size() && i != 0; i = elem.stackup[i - 1].nextId, layercount++ )
; while( layer < elem.stackup.size() && layer != 0 )
{
layer = elem.stackup[ layer - 1 ].nextId;
layercount++;
}
size_t kicadLayercount = ( layercount % 2 == 0 ) ? layercount : layercount + 1; size_t kicadLayercount = ( layercount % 2 == 0 ) ? layercount : layercount + 1;
m_board->SetCopperLayerCount( kicadLayercount ); m_board->SetCopperLayerCount( kicadLayercount );
@ -872,10 +872,10 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector<ALTIUM_VERTICE>& aV
shape->SetShape( SHAPE_T::ARC ); shape->SetShape( SHAPE_T::ARC );
double includedAngle = cur->endangle - cur->startangle; double includedAngle = cur->endangle - cur->startangle;
double startradiant = DEG2RAD( cur->startangle ); double startAngle = DEG2RAD( cur->endangle );
wxPoint arcStartOffset = wxPoint( KiROUND( std::cos( startradiant ) * cur->radius ), wxPoint startOffset = wxPoint( KiROUND( std::cos( startAngle ) * cur->radius ),
-KiROUND( std::sin( startradiant ) * cur->radius ) ); -KiROUND( std::sin( startAngle ) * cur->radius ) );
wxPoint arcStart = cur->center + arcStartOffset; wxPoint arcStart = cur->center + startOffset;
shape->SetCenter( cur->center ); shape->SetCenter( cur->center );
shape->SetStart( arcStart ); shape->SetStart( arcStart );
@ -883,10 +883,10 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector<ALTIUM_VERTICE>& aV
if( !last->isRound ) if( !last->isRound )
{ {
double endradiant = DEG2RAD( cur->endangle ); double endAngle = DEG2RAD( cur->endangle );
wxPoint arcEndOffset = wxPoint( KiROUND( std::cos( endradiant ) * cur->radius ), wxPoint endOffset = wxPoint( KiROUND( std::cos( endAngle ) * cur->radius ),
-KiROUND( std::sin( endradiant ) * cur->radius ) ); -KiROUND( std::sin( endAngle ) * cur->radius ) );
wxPoint arcEnd = cur->center + arcEndOffset; wxPoint arcEnd = cur->center + endOffset;
PCB_SHAPE* shape2 = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT ); PCB_SHAPE* shape2 = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT );
m_board->Add( shape2, ADD_MODE::APPEND ); m_board->Add( shape2, ADD_MODE::APPEND );
@ -899,9 +899,9 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector<ALTIUM_VERTICE>& aV
double lineLengthEnd = GetLineLength( last->position, arcEnd ); double lineLengthEnd = GetLineLength( last->position, arcEnd );
if( lineLengthStart > lineLengthEnd ) if( lineLengthStart > lineLengthEnd )
shape2->SetEnd( cur->center + arcEndOffset ); shape2->SetEnd( cur->center + endOffset );
else else
shape2->SetEnd( cur->center + arcStartOffset ); shape2->SetEnd( cur->center + startOffset );
} }
} }
last = cur; last = cur;
@ -941,9 +941,7 @@ void ALTIUM_PCB::ParseClasses6Data( const CFB::CompoundFileReader& aReader,
} }
if( reader.GetRemainingBytes() != 0 ) if( reader.GetRemainingBytes() != 0 )
{
THROW_IO_ERROR( "Classes6 stream is not fully parsed" ); THROW_IO_ERROR( "Classes6 stream is not fully parsed" );
}
m_board->m_LegacyNetclassesLoaded = true; m_board->m_LegacyNetclassesLoaded = true;
} }
@ -989,10 +987,8 @@ void ALTIUM_PCB::ParseComponents6Data( const CFB::CompoundFileReader& aReader,
} }
if( reader.GetRemainingBytes() != 0 ) if( reader.GetRemainingBytes() != 0 )
{
THROW_IO_ERROR( "Components6 stream is not fully parsed" ); THROW_IO_ERROR( "Components6 stream is not fully parsed" );
} }
}
void ALTIUM_PCB::ParseComponentsBodies6Data( const CFB::CompoundFileReader& aReader, void ALTIUM_PCB::ParseComponentsBodies6Data( const CFB::CompoundFileReader& aReader,
@ -1170,10 +1166,7 @@ void ALTIUM_PCB::HelperParseDimensions6Radial(const ADIMENSION6 &aElem)
wxPoint referencePoint0 = aElem.referencePoint.at( 0 ); wxPoint referencePoint0 = aElem.referencePoint.at( 0 );
wxPoint referencePoint1 = aElem.referencePoint.at( 1 ); wxPoint referencePoint1 = aElem.referencePoint.at( 1 );
// PCB_DIM_RADIAL* dimension = new PCB_DIM_RADIAL( m_board );
// We don't have radial dimensions yet so fake it with a leader:
PCB_DIM_LEADER* dimension = new PCB_DIM_LEADER( m_board );
m_board->Add( dimension, ADD_MODE::APPEND ); m_board->Add( dimension, ADD_MODE::APPEND );
m_radialDimensions.push_back( dimension ); m_radialDimensions.push_back( dimension );
@ -1182,6 +1175,7 @@ void ALTIUM_PCB::HelperParseDimensions6Radial(const ADIMENSION6 &aElem)
dimension->SetStart( referencePoint0 ); dimension->SetStart( referencePoint0 );
dimension->SetEnd( aElem.xy1 ); dimension->SetEnd( aElem.xy1 );
dimension->SetLineThickness( aElem.linewidth ); dimension->SetLineThickness( aElem.linewidth );
dimension->SetKeepTextAligned( false );
dimension->SetPrefix( aElem.textprefix ); dimension->SetPrefix( aElem.textprefix );
@ -1910,6 +1904,34 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader,
if( m_progressReporter ) if( m_progressReporter )
m_progressReporter->Report( _( "Loading arcs..." ) ); m_progressReporter->Report( _( "Loading arcs..." ) );
auto setupShape =
[&]( AARC6& elem, PCB_LAYER_ID layer, PCB_SHAPE& shape )
{
shape.SetLayer( layer );
shape.SetStroke( STROKE_PARAMS( elem.width, PLOT_DASH_TYPE::SOLID ) );
if( elem.startangle == 0. && elem.endangle == 360. )
{
// TODO: other variants to define circle?
shape.SetShape( SHAPE_T::CIRCLE );
shape.SetStart( elem.center );
shape.SetEnd( elem.center - wxPoint( 0, elem.radius ) );
return;
}
shape.SetShape( SHAPE_T::ARC );
double includedAngle = elem.endangle - elem.startangle;
double startAngle = DEG2RAD( elem.endangle );
wxPoint startOffset = wxPoint( KiROUND( std::cos( startAngle ) * elem.radius ),
-KiROUND( std::sin( startAngle ) * elem.radius ) );
shape.SetCenter( elem.center );
shape.SetStart( elem.center + startOffset );
shape.SetArcAngleAndEnd( NormalizeAngleDegreesPos( includedAngle ) * 10.0, true );
};
ALTIUM_PARSER reader( aReader, aEntry ); ALTIUM_PARSER reader( aReader, aEntry );
while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ ) while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
@ -1929,27 +1951,7 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader,
if( elem.is_keepout || IsAltiumLayerAPlane( elem.layer ) ) if( elem.is_keepout || IsAltiumLayerAPlane( elem.layer ) )
{ {
PCB_SHAPE shape( nullptr ); // just a helper to get the graphic PCB_SHAPE shape( nullptr ); // just a helper to get the graphic
shape.SetStroke( STROKE_PARAMS( elem.width, PLOT_DASH_TYPE::SOLID ) ); setupShape( elem, klayer, shape );
if( elem.startangle == 0. && elem.endangle == 360. )
{ // TODO: other variants to define circle?
shape.SetShape( SHAPE_T::CIRCLE );
shape.SetStart( elem.center );
shape.SetEnd( elem.center - wxPoint( 0, elem.radius ) );
}
else
{
shape.SetShape( SHAPE_T::ARC );
double includedAngle = elem.endangle - elem.startangle;
double startradiant = DEG2RAD( elem.startangle );
wxPoint arcStartOffset = wxPoint( KiROUND( std::cos( startradiant ) * elem.radius ),
-KiROUND( std::sin( startradiant ) * elem.radius ) );
shape.SetCenter( elem.center );
shape.SetStart( elem.center + arcStartOffset );
shape.SetArcAngleAndEnd( -NormalizeAngleDegreesPos( includedAngle ) * 10.0, true );
}
ZONE* zone = new ZONE( m_board ); ZONE* zone = new ZONE( m_board );
m_board->Add( zone, ADD_MODE::APPEND ); m_board->Add( zone, ADD_MODE::APPEND );
@ -1969,8 +1971,6 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader,
} }
else else
{ {
PCB_LAYER_ID klayer = GetKicadLayer( elem.layer );
if( klayer == UNDEFINED_LAYER ) if( klayer == UNDEFINED_LAYER )
{ {
wxLogWarning( _( "Arc keepout found on an Altium layer (%d) with no KiCad " wxLogWarning( _( "Arc keepout found on an Altium layer (%d) with no KiCad "
@ -2034,38 +2034,16 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader,
else else
{ {
PCB_SHAPE* shape = HelperCreateAndAddShape( elem.component ); PCB_SHAPE* shape = HelperCreateAndAddShape( elem.component );
shape->SetStroke( STROKE_PARAMS( elem.width, PLOT_DASH_TYPE::SOLID ) );
shape->SetLayer( klayer );
if( elem.startangle == 0. && elem.endangle == 360. ) setupShape( elem, klayer, *shape );
{ // TODO: other variants to define circle?
shape->SetShape( SHAPE_T::CIRCLE );
shape->SetStart( elem.center );
shape->SetEnd( elem.center - wxPoint( 0, elem.radius ) );
}
else
{
shape->SetShape( SHAPE_T::ARC );
double includedAngle = elem.endangle - elem.startangle;
double startradiant = DEG2RAD( elem.startangle );
wxPoint arcStartOffset = wxPoint( KiROUND( std::cos( startradiant ) * elem.radius ),
-KiROUND( std::sin( startradiant ) * elem.radius ) );
shape->SetCenter( elem.center );
shape->SetStart( elem.center + arcStartOffset );
shape->SetArcAngleAndEnd( -NormalizeAngleDegreesPos( includedAngle ) * 10.0, true );
}
HelperShapeSetLocalCoord( shape, elem.component ); HelperShapeSetLocalCoord( shape, elem.component );
} }
} }
if( reader.GetRemainingBytes() != 0 ) if( reader.GetRemainingBytes() != 0 )
{
THROW_IO_ERROR( "Arcs6 stream is not fully parsed" ); THROW_IO_ERROR( "Arcs6 stream is not fully parsed" );
} }
}
void ALTIUM_PCB::ParsePads6Data( const CFB::CompoundFileReader& aReader, void ALTIUM_PCB::ParsePads6Data( const CFB::CompoundFileReader& aReader,

View File

@ -85,7 +85,7 @@ class BOARD;
class PCB_SHAPE; class PCB_SHAPE;
class FOOTPRINT; class FOOTPRINT;
class ZONE; class ZONE;
class PCB_DIMENSION_BASE; class PCB_DIM_RADIAL;
class PROGRESS_REPORTER; class PROGRESS_REPORTER;
@ -193,7 +193,7 @@ private:
BOARD* m_board; BOARD* m_board;
std::vector<FOOTPRINT*> m_components; std::vector<FOOTPRINT*> m_components;
std::vector<ZONE*> m_polygons; std::vector<ZONE*> m_polygons;
std::vector<PCB_DIMENSION_BASE*> m_radialDimensions; std::vector<PCB_DIM_RADIAL*> m_radialDimensions;
std::map<wxString, wxString> m_models; std::map<wxString, wxString> m_models;
std::map<uint32_t, wxString> m_unicodeStrings; std::map<uint32_t, wxString> m_unicodeStrings;
size_t m_num_nets; size_t m_num_nets;