diff --git a/pcbnew/plugins/altium/altium_pcb.cpp b/pcbnew/plugins/altium/altium_pcb.cpp index 7d4ed36d4f..5166f9a426 100644 --- a/pcbnew/plugins/altium/altium_pcb.cpp +++ b/pcbnew/plugins/altium/altium_pcb.cpp @@ -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 // 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:. - for( PCB_DIMENSION_BASE* dim : m_radialDimensions ) + for( PCB_DIM_RADIAL* dim : m_radialDimensions ) { 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 - // 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 + // Move the radius point onto the circumference VECTOR2I radialLine = dim->GetEnd() - dim->GetStart(); - radialLine = radialLine.Resize( radius ); - dim->SetStart( dim->GetStart() + (wxPoint) radialLine ); + int totalLength = radialLine.EuclideanNorm(); + + // 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 @@ -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 auto rules = m_rules.find( aKind ); + if( rules == m_rules.end() ) - { return nullptr; - } + for( const ARULE6& rule : rules->second ) { if( rule.name == aName ) - { return &rule; - } } + return nullptr; } const ARULE6* ALTIUM_PCB::GetRuleDefault( ALTIUM_RULE_KIND aKind ) const { const auto rules = m_rules.find( aKind ); + if( rules == m_rules.end() ) - { return nullptr; - } + for( const ARULE6& rule : rules->second ) { if( rule.scope1expr == "All" && rule.scope2expr == "All" ) - { return &rule; - } } + return nullptr; } @@ -713,18 +710,21 @@ void ALTIUM_PCB::ParseBoard6Data( const CFB::CompoundFileReader& aReader, ABOARD6 elem( reader ); if( reader.GetRemainingBytes() != 0 ) - { THROW_IO_ERROR( "Board6 stream is not fully parsed" ); - } m_board->GetDesignSettings().SetAuxOrigin( elem.sheetpos ); m_board->GetDesignSettings().SetGridOrigin( elem.sheetpos ); // read layercount from stackup, because LAYERSETSCOUNT is not always correct?! size_t layercount = 0; - for( size_t i = static_cast( ALTIUM_LAYER::TOP_LAYER ); - i < elem.stackup.size() && i != 0; i = elem.stackup[i - 1].nextId, layercount++ ) - ; + size_t layer = static_cast( ALTIUM_LAYER::TOP_LAYER ); + + while( layer < elem.stackup.size() && layer != 0 ) + { + layer = elem.stackup[ layer - 1 ].nextId; + layercount++; + } + size_t kicadLayercount = ( layercount % 2 == 0 ) ? layercount : layercount + 1; m_board->SetCopperLayerCount( kicadLayercount ); @@ -871,11 +871,11 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector& aV { shape->SetShape( SHAPE_T::ARC ); - double includedAngle = cur->endangle - cur->startangle; - double startradiant = DEG2RAD( cur->startangle ); - wxPoint arcStartOffset = wxPoint( KiROUND( std::cos( startradiant ) * cur->radius ), - -KiROUND( std::sin( startradiant ) * cur->radius ) ); - wxPoint arcStart = cur->center + arcStartOffset; + double includedAngle = cur->endangle - cur->startangle; + double startAngle = DEG2RAD( cur->endangle ); + wxPoint startOffset = wxPoint( KiROUND( std::cos( startAngle ) * cur->radius ), + -KiROUND( std::sin( startAngle ) * cur->radius ) ); + wxPoint arcStart = cur->center + startOffset; shape->SetCenter( cur->center ); shape->SetStart( arcStart ); @@ -883,10 +883,10 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector& aV if( !last->isRound ) { - double endradiant = DEG2RAD( cur->endangle ); - wxPoint arcEndOffset = wxPoint( KiROUND( std::cos( endradiant ) * cur->radius ), - -KiROUND( std::sin( endradiant ) * cur->radius ) ); - wxPoint arcEnd = cur->center + arcEndOffset; + double endAngle = DEG2RAD( cur->endangle ); + wxPoint endOffset = wxPoint( KiROUND( std::cos( endAngle ) * cur->radius ), + -KiROUND( std::sin( endAngle ) * cur->radius ) ); + wxPoint arcEnd = cur->center + endOffset; PCB_SHAPE* shape2 = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT ); m_board->Add( shape2, ADD_MODE::APPEND ); @@ -899,9 +899,9 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector& aV double lineLengthEnd = GetLineLength( last->position, arcEnd ); if( lineLengthStart > lineLengthEnd ) - shape2->SetEnd( cur->center + arcEndOffset ); + shape2->SetEnd( cur->center + endOffset ); else - shape2->SetEnd( cur->center + arcStartOffset ); + shape2->SetEnd( cur->center + startOffset ); } } last = cur; @@ -941,9 +941,7 @@ void ALTIUM_PCB::ParseClasses6Data( const CFB::CompoundFileReader& aReader, } if( reader.GetRemainingBytes() != 0 ) - { THROW_IO_ERROR( "Classes6 stream is not fully parsed" ); - } m_board->m_LegacyNetclassesLoaded = true; } @@ -989,9 +987,7 @@ void ALTIUM_PCB::ParseComponents6Data( const CFB::CompoundFileReader& aReader, } if( reader.GetRemainingBytes() != 0 ) - { THROW_IO_ERROR( "Components6 stream is not fully parsed" ); - } } @@ -1170,10 +1166,7 @@ void ALTIUM_PCB::HelperParseDimensions6Radial(const ADIMENSION6 &aElem) wxPoint referencePoint0 = aElem.referencePoint.at( 0 ); wxPoint referencePoint1 = aElem.referencePoint.at( 1 ); - // - // We don't have radial dimensions yet so fake it with a leader: - - PCB_DIM_LEADER* dimension = new PCB_DIM_LEADER( m_board ); + PCB_DIM_RADIAL* dimension = new PCB_DIM_RADIAL( m_board ); m_board->Add( dimension, ADD_MODE::APPEND ); m_radialDimensions.push_back( dimension ); @@ -1182,6 +1175,7 @@ void ALTIUM_PCB::HelperParseDimensions6Radial(const ADIMENSION6 &aElem) dimension->SetStart( referencePoint0 ); dimension->SetEnd( aElem.xy1 ); dimension->SetLineThickness( aElem.linewidth ); + dimension->SetKeepTextAligned( false ); dimension->SetPrefix( aElem.textprefix ); @@ -1910,6 +1904,34 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader, if( m_progressReporter ) 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 ); 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 ) ) { PCB_SHAPE shape( nullptr ); // just a helper to get the graphic - 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 ) ); - } - 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 ); - } + setupShape( elem, klayer, shape ); ZONE* zone = new ZONE( m_board ); m_board->Add( zone, ADD_MODE::APPEND ); @@ -1969,8 +1971,6 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader, } else { - PCB_LAYER_ID klayer = GetKicadLayer( elem.layer ); - if( klayer == UNDEFINED_LAYER ) { wxLogWarning( _( "Arc keepout found on an Altium layer (%d) with no KiCad " @@ -2034,37 +2034,15 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader, else { 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. ) - { // 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 ); - } + setupShape( elem, klayer, *shape ); HelperShapeSetLocalCoord( shape, elem.component ); } } if( reader.GetRemainingBytes() != 0 ) - { THROW_IO_ERROR( "Arcs6 stream is not fully parsed" ); - } } diff --git a/pcbnew/plugins/altium/altium_pcb.h b/pcbnew/plugins/altium/altium_pcb.h index bb19762e1e..b24cb5ae7d 100644 --- a/pcbnew/plugins/altium/altium_pcb.h +++ b/pcbnew/plugins/altium/altium_pcb.h @@ -85,7 +85,7 @@ class BOARD; class PCB_SHAPE; class FOOTPRINT; class ZONE; -class PCB_DIMENSION_BASE; +class PCB_DIM_RADIAL; class PROGRESS_REPORTER; @@ -193,7 +193,7 @@ private: BOARD* m_board; std::vector m_components; std::vector m_polygons; - std::vector m_radialDimensions; + std::vector m_radialDimensions; std::map m_models; std::map m_unicodeStrings; size_t m_num_nets;