From 7f667764bf192bd7dac71917b568fec67f67d51f Mon Sep 17 00:00:00 2001 From: Thomas Pointhuber Date: Sun, 16 Jan 2022 15:37:25 +0100 Subject: [PATCH] altium: Refactor pad parsing to make it reusable for footprint import --- pcbnew/plugins/altium/altium_pcb.cpp | 587 +++++++++++++++------------ pcbnew/plugins/altium/altium_pcb.h | 9 +- 2 files changed, 330 insertions(+), 266 deletions(-) diff --git a/pcbnew/plugins/altium/altium_pcb.cpp b/pcbnew/plugins/altium/altium_pcb.cpp index 4d2074c822..1394cf903a 100644 --- a/pcbnew/plugins/altium/altium_pcb.cpp +++ b/pcbnew/plugins/altium/altium_pcb.cpp @@ -133,6 +133,25 @@ void ALTIUM_PCB::HelperShapeSetLocalCoord( PCB_SHAPE* aShape, uint16_t aComponen } +void ALTIUM_PCB::HelperShapeSetLocalCoord( FP_SHAPE* aShape ) +{ + aShape->SetLocalCoord(); + + // TODO: SetLocalCoord() does not update the polygon shape! + // This workaround converts the poly shape into the local coordinates + SHAPE_POLY_SET& polyShape = aShape->GetPolyShape(); + if( !polyShape.IsEmpty() ) + { + FOOTPRINT* fp = dynamic_cast( aShape->GetParent() ); + if( fp ) + { + polyShape.Move( -fp->GetPosition() ); + polyShape.Rotate( -fp->GetOrientation().AsRadians() ); + } + } +} + + void HelperShapeLineChainFromAltiumVertices( SHAPE_LINE_CHAIN& aLine, const std::vector& aVertices ) { @@ -684,11 +703,13 @@ FOOTPRINT* ALTIUM_PCB::ParseFootprint( const ALTIUM_COMPOUND_FILE& altiumLibFile case ALTIUM_RECORD::PAD: { APAD6 pad( parser ); + ConvertPads6ToFootprintItem( footprint.get(), pad ); break; } case ALTIUM_RECORD::VIA: { AVIA6 via( parser ); + // TODO: implement break; } case ALTIUM_RECORD::TRACK: @@ -706,16 +727,19 @@ FOOTPRINT* ALTIUM_PCB::ParseFootprint( const ALTIUM_COMPOUND_FILE& altiumLibFile case ALTIUM_RECORD::FILL: { AFILL6 fill( parser ); + // TODO: implement break; } case ALTIUM_RECORD::REGION: { AREGION6 region( parser, false /* TODO */ ); + // TODO: implement break; } case ALTIUM_RECORD::MODEL: { ACOMPONENTBODY6 componentBody( parser ); + // Won't be supported for now, as we would need to extract the model break; } default: @@ -2203,209 +2227,14 @@ void ALTIUM_PCB::ParsePads6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile, checkpoint(); APAD6 elem( reader ); - // It is possible to place altium pads on non-copper layers -> we need to interpolate them using drawings! - if( !IsAltiumLayerCopper( elem.layer ) && !IsAltiumLayerAPlane( elem.layer ) - && elem.layer != ALTIUM_LAYER::MULTI_LAYER ) - { - HelperParsePad6NonCopper( elem ); - continue; - } - - // Create Pad - FOOTPRINT* footprint = nullptr; - if( elem.component == ALTIUM_COMPONENT_NONE ) { - footprint = new FOOTPRINT( m_board ); // We cannot add a pad directly into the PCB - m_board->Add( footprint, ADD_MODE::APPEND ); - footprint->SetPosition( elem.position ); + ConvertPads6ToBoardItem( elem ); } else { - if( m_components.size() <= elem.component ) - { - THROW_IO_ERROR( wxString::Format( "Pads6 stream tries to access component id %d " - "of %d existing components", - elem.component, - m_components.size() ) ); - } - footprint = m_components.at( elem.component ); - } - - PAD* pad = new PAD( footprint ); - footprint->Add( pad, ADD_MODE::APPEND ); - - pad->SetNumber( elem.name ); - pad->SetNetCode( GetNetCode( elem.net ) ); - pad->SetLocked( elem.is_locked ); - - pad->SetPosition( elem.position ); - pad->SetOrientationDegrees( elem.direction ); - pad->SetLocalCoord(); - - pad->SetSize( elem.topsize ); - - if( elem.holesize == 0 ) - { - pad->SetAttribute( PAD_ATTRIB::SMD ); - } - else - { - if( elem.layer != ALTIUM_LAYER::MULTI_LAYER ) - { - // TODO: I assume other values are possible as well? - wxLogError( _( "Footprint %s pad %s is not marked as multilayer, but is a TH pad." ), - footprint->GetReference(), - elem.name ); - } - pad->SetAttribute( elem.plated ? PAD_ATTRIB::PTH : - PAD_ATTRIB::NPTH ); - if( !elem.sizeAndShape || elem.sizeAndShape->holeshape == ALTIUM_PAD_HOLE_SHAPE::ROUND ) - { - pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_CIRCLE ); - pad->SetDrillSize( wxSize( elem.holesize, elem.holesize ) ); - } - else - { - switch( elem.sizeAndShape->holeshape ) - { - case ALTIUM_PAD_HOLE_SHAPE::ROUND: - wxFAIL_MSG( "Round holes are handled before the switch" ); - break; - - case ALTIUM_PAD_HOLE_SHAPE::SQUARE: - wxLogWarning( _( "Footprint %s pad %s has a square hole (not yet supported)." ), - footprint->GetReference(), - elem.name ); - pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_CIRCLE ); - pad->SetDrillSize( wxSize( elem.holesize, elem.holesize ) ); // Workaround - // TODO: elem.sizeAndShape->slotsize was 0 in testfile. Either use holesize in this case or rect holes have a different id - break; - - case ALTIUM_PAD_HOLE_SHAPE::SLOT: - { - pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_OBLONG ); - EDA_ANGLE slotRotation( elem.sizeAndShape->slotrotation, DEGREES_T ); - - slotRotation.Normalize(); - - if( slotRotation == ANGLE_0 || slotRotation == ANGLE_180 ) - { - pad->SetDrillSize( wxSize( elem.sizeAndShape->slotsize, elem.holesize ) ); - } - else - { - if( slotRotation != ANGLE_90 && slotRotation != ANGLE_270 ) - { - wxLogWarning( _( "Footprint %s pad %s has a hole-rotation of %f " - "degrees. KiCad only supports 90 degree rotations." ), - footprint->GetReference(), - elem.name, - slotRotation.AsDegrees() ); - } - - pad->SetDrillSize( wxSize( elem.holesize, elem.sizeAndShape->slotsize ) ); - } - } - break; - - default: - case ALTIUM_PAD_HOLE_SHAPE::UNKNOWN: - wxLogError( _( "Footprint %s pad %s uses a hole of unknown kind %d." ), - footprint->GetReference(), - elem.name, - elem.sizeAndShape->holeshape ); - pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_CIRCLE ); - pad->SetDrillSize( wxSize( elem.holesize, elem.holesize ) ); // Workaround - break; - } - } - - if( elem.sizeAndShape ) - { - pad->SetOffset( elem.sizeAndShape->holeoffset[0] ); - } - } - - if( elem.padmode != ALTIUM_PAD_MODE::SIMPLE ) - { - wxLogError( _( "Footprint %s pad %s uses a complex pad stack (not yet supported.)" ), - footprint->GetReference(), - elem.name ); - } - - switch( elem.topshape ) - { - case ALTIUM_PAD_SHAPE::RECT: - pad->SetShape( PAD_SHAPE::RECT ); - break; - case ALTIUM_PAD_SHAPE::CIRCLE: - if( elem.sizeAndShape - && elem.sizeAndShape->alt_shape[0] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT ) - { - pad->SetShape( PAD_SHAPE::ROUNDRECT ); // 100 = round, 0 = rectangular - double ratio = elem.sizeAndShape->cornerradius[0] / 200.; - pad->SetRoundRectRadiusRatio( ratio ); - } - else if( elem.topsize.x == elem.topsize.y ) - { - pad->SetShape( PAD_SHAPE::CIRCLE ); - } - else - { - pad->SetShape( PAD_SHAPE::OVAL ); - } - break; - case ALTIUM_PAD_SHAPE::OCTAGONAL: - pad->SetShape( PAD_SHAPE::CHAMFERED_RECT ); - pad->SetChamferPositions( RECT_CHAMFER_ALL ); - pad->SetChamferRectRatio( 0.25 ); - break; - case ALTIUM_PAD_SHAPE::UNKNOWN: - default: - wxLogError( _( "Footprint %s pad %s uses an unknown pad-shape." ), - footprint->GetReference(), - elem.name ); - break; - } - - switch( elem.layer ) - { - case ALTIUM_LAYER::TOP_LAYER: - pad->SetLayer( F_Cu ); - pad->SetLayerSet( PAD::SMDMask() ); - break; - case ALTIUM_LAYER::BOTTOM_LAYER: - pad->SetLayer( B_Cu ); - pad->SetLayerSet( FlipLayerMask( PAD::SMDMask() ) ); - break; - case ALTIUM_LAYER::MULTI_LAYER: - pad->SetLayerSet( elem.plated ? PAD::PTHMask() : PAD::UnplatedHoleMask() ); - break; - default: - PCB_LAYER_ID klayer = GetKicadLayer( elem.layer ); - pad->SetLayer( klayer ); - pad->SetLayerSet( LSET( 1, klayer ) ); - break; - } - - if( elem.pastemaskexpansionmode == ALTIUM_PAD_RULE::MANUAL ) - { - pad->SetLocalSolderPasteMargin( elem.pastemaskexpansionmanual ); - } - - if( elem.soldermaskexpansionmode == ALTIUM_PAD_RULE::MANUAL ) - { - pad->SetLocalSolderMaskMargin( elem.soldermaskexpansionmanual ); - } - - if( elem.is_tent_top ) - { - pad->SetLayerSet( pad->GetLayerSet().reset( F_Mask ) ); - } - if( elem.is_tent_bottom ) - { - pad->SetLayerSet( pad->GetLayerSet().reset( B_Mask ) ); + FOOTPRINT* footprint = HelperGetFootprint( elem.component ); + ConvertPads6ToFootprintItem( footprint, elem ); } } @@ -2416,19 +2245,259 @@ void ALTIUM_PCB::ParsePads6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile, } -void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) +void ALTIUM_PCB::ConvertPads6ToBoardItem( const APAD6& aElem ) +{ + // It is possible to place altium pads on non-copper layers -> we need to interpolate them using drawings! + if( !IsAltiumLayerCopper( aElem.layer ) && !IsAltiumLayerAPlane( aElem.layer ) + && aElem.layer != ALTIUM_LAYER::MULTI_LAYER ) + { + ConvertPads6ToBoardItemOnNonCopper( aElem ); + } + else + { + // We cannot add a pad directly into the PCB + FOOTPRINT* footprint = new FOOTPRINT( m_board ); + footprint->SetPosition( aElem.position ); + + ConvertPads6ToFootprintItemOnCopper( footprint, aElem ); + + m_board->Add( footprint, ADD_MODE::APPEND ); + } +} + + +void ALTIUM_PCB::ConvertPads6ToFootprintItem( FOOTPRINT* aFootprint, const APAD6& aElem ) +{ + // It is possible to place altium pads on non-copper layers -> we need to interpolate them using drawings! + if( !IsAltiumLayerCopper( aElem.layer ) && !IsAltiumLayerAPlane( aElem.layer ) + && aElem.layer != ALTIUM_LAYER::MULTI_LAYER ) + { + ConvertPads6ToFootprintItemOnNonCopper( aFootprint, aElem ); + } + else + { + ConvertPads6ToFootprintItemOnCopper( aFootprint, aElem ); + } +} + + +void ALTIUM_PCB::ConvertPads6ToFootprintItemOnCopper( FOOTPRINT* aFootprint, const APAD6& aElem ) +{ + PAD* pad = new PAD( aFootprint ); + + pad->SetNumber( aElem.name ); + pad->SetNetCode( GetNetCode( aElem.net ) ); + pad->SetLocked( aElem.is_locked ); + + pad->SetPosition( aElem.position ); + pad->SetOrientationDegrees( aElem.direction ); + pad->SetLocalCoord(); + + pad->SetSize( aElem.topsize ); + + if( aElem.holesize == 0 ) + { + pad->SetAttribute( PAD_ATTRIB::SMD ); + } + else + { + if( aElem.layer != ALTIUM_LAYER::MULTI_LAYER ) + { + // TODO: I assume other values are possible as well? + wxLogError( _( "Footprint %s pad %s is not marked as multilayer, but is a TH pad." ), + aFootprint->GetReference(), aElem.name ); + } + pad->SetAttribute( aElem.plated ? PAD_ATTRIB::PTH : PAD_ATTRIB::NPTH ); + if( !aElem.sizeAndShape || aElem.sizeAndShape->holeshape == ALTIUM_PAD_HOLE_SHAPE::ROUND ) + { + pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_CIRCLE ); + pad->SetDrillSize( wxSize( aElem.holesize, aElem.holesize ) ); + } + else + { + switch( aElem.sizeAndShape->holeshape ) + { + case ALTIUM_PAD_HOLE_SHAPE::ROUND: + wxFAIL_MSG( "Round holes are handled before the switch" ); + break; + + case ALTIUM_PAD_HOLE_SHAPE::SQUARE: + wxLogWarning( _( "Footprint %s pad %s has a square hole (not yet supported)." ), + aFootprint->GetReference(), aElem.name ); + pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_CIRCLE ); + pad->SetDrillSize( wxSize( aElem.holesize, aElem.holesize ) ); // Workaround + // TODO: elem.sizeAndShape->slotsize was 0 in testfile. Either use holesize in this case or rect holes have a different id + break; + + case ALTIUM_PAD_HOLE_SHAPE::SLOT: + { + pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_OBLONG ); + EDA_ANGLE slotRotation( aElem.sizeAndShape->slotrotation, DEGREES_T ); + + slotRotation.Normalize(); + + if( slotRotation == ANGLE_0 || slotRotation == ANGLE_180 ) + { + pad->SetDrillSize( wxSize( aElem.sizeAndShape->slotsize, aElem.holesize ) ); + } + else + { + if( slotRotation != ANGLE_90 && slotRotation != ANGLE_270 ) + { + wxLogWarning( _( "Footprint %s pad %s has a hole-rotation of %f " + "degrees. KiCad only supports 90 degree rotations." ), + aFootprint->GetReference(), aElem.name, + slotRotation.AsDegrees() ); + } + + pad->SetDrillSize( wxSize( aElem.holesize, aElem.sizeAndShape->slotsize ) ); + } + } + break; + + default: + case ALTIUM_PAD_HOLE_SHAPE::UNKNOWN: + wxLogError( _( "Footprint %s pad %s uses a hole of unknown kind %d." ), + aFootprint->GetReference(), aElem.name, aElem.sizeAndShape->holeshape ); + pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_CIRCLE ); + pad->SetDrillSize( wxSize( aElem.holesize, aElem.holesize ) ); // Workaround + break; + } + } + + if( aElem.sizeAndShape ) + { + pad->SetOffset( aElem.sizeAndShape->holeoffset[0] ); + } + } + + if( aElem.padmode != ALTIUM_PAD_MODE::SIMPLE ) + { + wxLogError( _( "Footprint %s pad %s uses a complex pad stack (not yet supported.)" ), + aFootprint->GetReference(), aElem.name ); + } + + switch( aElem.topshape ) + { + case ALTIUM_PAD_SHAPE::RECT: pad->SetShape( PAD_SHAPE::RECT ); break; + case ALTIUM_PAD_SHAPE::CIRCLE: + if( aElem.sizeAndShape + && aElem.sizeAndShape->alt_shape[0] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT ) + { + pad->SetShape( PAD_SHAPE::ROUNDRECT ); // 100 = round, 0 = rectangular + double ratio = aElem.sizeAndShape->cornerradius[0] / 200.; + pad->SetRoundRectRadiusRatio( ratio ); + } + else if( aElem.topsize.x == aElem.topsize.y ) + { + pad->SetShape( PAD_SHAPE::CIRCLE ); + } + else + { + pad->SetShape( PAD_SHAPE::OVAL ); + } + break; + case ALTIUM_PAD_SHAPE::OCTAGONAL: + pad->SetShape( PAD_SHAPE::CHAMFERED_RECT ); + pad->SetChamferPositions( RECT_CHAMFER_ALL ); + pad->SetChamferRectRatio( 0.25 ); + break; + case ALTIUM_PAD_SHAPE::UNKNOWN: + default: + wxLogError( _( "Footprint %s pad %s uses an unknown pad-shape." ), + aFootprint->GetReference(), aElem.name ); + break; + } + + switch( aElem.layer ) + { + case ALTIUM_LAYER::TOP_LAYER: + pad->SetLayer( F_Cu ); + pad->SetLayerSet( PAD::SMDMask() ); + break; + case ALTIUM_LAYER::BOTTOM_LAYER: + pad->SetLayer( B_Cu ); + pad->SetLayerSet( FlipLayerMask( PAD::SMDMask() ) ); + break; + case ALTIUM_LAYER::MULTI_LAYER: + pad->SetLayerSet( aElem.plated ? PAD::PTHMask() : PAD::UnplatedHoleMask() ); + break; + default: + PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer ); + pad->SetLayer( klayer ); + pad->SetLayerSet( LSET( 1, klayer ) ); + break; + } + + if( aElem.pastemaskexpansionmode == ALTIUM_PAD_RULE::MANUAL ) + { + pad->SetLocalSolderPasteMargin( aElem.pastemaskexpansionmanual ); + } + + if( aElem.soldermaskexpansionmode == ALTIUM_PAD_RULE::MANUAL ) + { + pad->SetLocalSolderMaskMargin( aElem.soldermaskexpansionmanual ); + } + + if( aElem.is_tent_top ) + { + pad->SetLayerSet( pad->GetLayerSet().reset( F_Mask ) ); + } + if( aElem.is_tent_bottom ) + { + pad->SetLayerSet( pad->GetLayerSet().reset( B_Mask ) ); + } + + aFootprint->Add( pad, ADD_MODE::APPEND ); +} + + +void ALTIUM_PCB::ConvertPads6ToBoardItemOnNonCopper( const APAD6& aElem ) { PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer ); if( klayer == UNDEFINED_LAYER ) { - wxLogWarning( _( "Non-copper pad %s found on an Altium layer (%d) with no KiCad equivalent. " - "It has been moved to KiCad layer Eco1_User." ), - aElem.name, - aElem.layer ); + wxLogWarning( + _( "Non-copper pad %s found on an Altium layer (%d) with no KiCad equivalent. " + "It has been moved to KiCad layer Eco1_User." ), + aElem.name, aElem.layer ); klayer = Eco1_User; } + PCB_SHAPE* pad = new PCB_SHAPE( m_board ); + + HelperParsePad6NonCopper( aElem, klayer, pad ); + + m_board->Add( pad, ADD_MODE::APPEND ); +} + + +void ALTIUM_PCB::ConvertPads6ToFootprintItemOnNonCopper( FOOTPRINT* aFootprint, const APAD6& aElem ) +{ + PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer ); + + if( klayer == UNDEFINED_LAYER ) + { + wxLogWarning( + _( "Non-copper pad %s found on an Altium layer (%d) with no KiCad equivalent. " + "It has been moved to KiCad layer Eco1_User." ), + aElem.name, aElem.layer ); + klayer = Eco1_User; + } + + FP_SHAPE* pad = new FP_SHAPE( aFootprint ); + + HelperParsePad6NonCopper( aElem, klayer, pad ); + + HelperShapeSetLocalCoord( pad ); + aFootprint->Add( pad, ADD_MODE::APPEND ); +} + + +void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem, PCB_LAYER_ID aLayer, + PCB_SHAPE* aShape ) +{ if( aElem.net != ALTIUM_NET_UNCONNECTED ) { wxLogError( _( "Non-copper pad %s is connected to a net, which is not supported." ), @@ -2451,21 +2520,19 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) case ALTIUM_PAD_SHAPE::RECT: { // filled rect - PCB_SHAPE* shape = HelperCreateAndAddShape( aElem.component ); - shape->SetShape( SHAPE_T::POLY ); - shape->SetFilled( true ); - shape->SetLayer( klayer ); - shape->SetStroke( STROKE_PARAMS( 0 ) ); + aShape->SetShape( SHAPE_T::POLY ); + aShape->SetFilled( true ); + aShape->SetLayer( aLayer ); + aShape->SetStroke( STROKE_PARAMS( 0 ) ); - shape->SetPolyPoints( { aElem.position + VECTOR2I( aElem.topsize.x / 2, aElem.topsize.y / 2 ), - aElem.position + VECTOR2I( aElem.topsize.x / 2, -aElem.topsize.y / 2 ), - aElem.position + VECTOR2I( -aElem.topsize.x / 2, -aElem.topsize.y / 2 ), - aElem.position + VECTOR2I( -aElem.topsize.x / 2, aElem.topsize.y / 2 ) } ); + aShape->SetPolyPoints( + { aElem.position + VECTOR2I( aElem.topsize.x / 2, aElem.topsize.y / 2 ), + aElem.position + VECTOR2I( aElem.topsize.x / 2, -aElem.topsize.y / 2 ), + aElem.position + VECTOR2I( -aElem.topsize.x / 2, -aElem.topsize.y / 2 ), + aElem.position + VECTOR2I( -aElem.topsize.x / 2, aElem.topsize.y / 2 ) } ); if( aElem.direction != 0 ) - shape->Rotate( aElem.position, EDA_ANGLE( aElem.direction, DEGREES_T ) ); - - HelperShapeSetLocalCoord( shape, aElem.component ); + aShape->Rotate( aElem.position, EDA_ANGLE( aElem.direction, DEGREES_T ) ); } break; @@ -2477,9 +2544,8 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) int cornerradius = aElem.sizeAndShape->cornerradius[0]; int offset = ( std::min( aElem.topsize.x, aElem.topsize.y ) * cornerradius ) / 200; - PCB_SHAPE* shape = HelperCreateAndAddShape( aElem.component ); - shape->SetLayer( klayer ); - shape->SetStroke( STROKE_PARAMS( offset * 2, PLOT_DASH_TYPE::SOLID ) ); + aShape->SetLayer( aLayer ); + aShape->SetStroke( STROKE_PARAMS( offset * 2, PLOT_DASH_TYPE::SOLID ) ); if( cornerradius < 100 ) { @@ -2491,90 +2557,82 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) VECTOR2I p22 = aElem.position + VECTOR2I( -offsetX, -offsetY ); VECTOR2I p21 = aElem.position + VECTOR2I( -offsetX, offsetY ); - shape->SetShape( SHAPE_T::POLY ); - shape->SetFilled( true ); - shape->SetPolyPoints( { p11, p12, p22, p21 } ); + aShape->SetShape( SHAPE_T::POLY ); + aShape->SetFilled( true ); + aShape->SetPolyPoints( { p11, p12, p22, p21 } ); } else if( aElem.topsize.x == aElem.topsize.y ) { // circle - shape->SetShape( SHAPE_T::CIRCLE ); - shape->SetFilled( true ); - shape->SetStart( aElem.position ); - shape->SetEnd( aElem.position - VECTOR2I( 0, aElem.topsize.x / 4 ) ); - shape->SetStroke( STROKE_PARAMS( aElem.topsize.x / 2, PLOT_DASH_TYPE::SOLID ) ); + aShape->SetShape( SHAPE_T::CIRCLE ); + aShape->SetFilled( true ); + aShape->SetStart( aElem.position ); + aShape->SetEnd( aElem.position - VECTOR2I( 0, aElem.topsize.x / 4 ) ); + aShape->SetStroke( STROKE_PARAMS( aElem.topsize.x / 2, PLOT_DASH_TYPE::SOLID ) ); } else if( aElem.topsize.x < aElem.topsize.y ) { // short vertical line - shape->SetShape( SHAPE_T::SEGMENT ); + aShape->SetShape( SHAPE_T::SEGMENT ); VECTOR2I pointOffset( 0, ( aElem.topsize.y - aElem.topsize.x ) / 2 ); - shape->SetStart( aElem.position + pointOffset ); - shape->SetEnd( aElem.position - pointOffset ); + aShape->SetStart( aElem.position + pointOffset ); + aShape->SetEnd( aElem.position - pointOffset ); } else { // short horizontal line - shape->SetShape( SHAPE_T::SEGMENT ); + aShape->SetShape( SHAPE_T::SEGMENT ); VECTOR2I pointOffset( ( aElem.topsize.x - aElem.topsize.y ) / 2, 0 ); - shape->SetStart( aElem.position + pointOffset ); - shape->SetEnd( aElem.position - pointOffset ); + aShape->SetStart( aElem.position + pointOffset ); + aShape->SetEnd( aElem.position - pointOffset ); } if( aElem.direction != 0 ) - shape->Rotate( aElem.position, EDA_ANGLE( aElem.direction, DEGREES_T ) ); - - HelperShapeSetLocalCoord( shape, aElem.component ); + aShape->Rotate( aElem.position, EDA_ANGLE( aElem.direction, DEGREES_T ) ); } else if( aElem.topsize.x == aElem.topsize.y ) { // filled circle - PCB_SHAPE* shape = HelperCreateAndAddShape( aElem.component ); - shape->SetShape( SHAPE_T::CIRCLE ); - shape->SetFilled( true ); - shape->SetLayer( klayer ); - shape->SetStart( aElem.position ); - shape->SetEnd( aElem.position - VECTOR2I( 0, aElem.topsize.x / 4 ) ); - shape->SetStroke( STROKE_PARAMS( aElem.topsize.x / 2, PLOT_DASH_TYPE::SOLID ) ); - HelperShapeSetLocalCoord( shape, aElem.component ); + aShape->SetShape( SHAPE_T::CIRCLE ); + aShape->SetFilled( true ); + aShape->SetLayer( aLayer ); + aShape->SetStart( aElem.position ); + aShape->SetEnd( aElem.position - VECTOR2I( 0, aElem.topsize.x / 4 ) ); + aShape->SetStroke( STROKE_PARAMS( aElem.topsize.x / 2, PLOT_DASH_TYPE::SOLID ) ); } else { // short line - PCB_SHAPE* shape = HelperCreateAndAddShape( aElem.component ); - shape->SetShape( SHAPE_T::SEGMENT ); - shape->SetLayer( klayer ); - shape->SetStroke( STROKE_PARAMS( std::min( aElem.topsize.x, aElem.topsize.y ), - PLOT_DASH_TYPE::SOLID ) ); + aShape->SetShape( SHAPE_T::SEGMENT ); + aShape->SetLayer( aLayer ); + aShape->SetStroke( STROKE_PARAMS( std::min( aElem.topsize.x, aElem.topsize.y ), + PLOT_DASH_TYPE::SOLID ) ); if( aElem.topsize.x < aElem.topsize.y ) { VECTOR2I offset( 0, ( aElem.topsize.y - aElem.topsize.x ) / 2 ); - shape->SetStart( aElem.position + offset ); - shape->SetEnd( aElem.position - offset ); + aShape->SetStart( aElem.position + offset ); + aShape->SetEnd( aElem.position - offset ); } else { VECTOR2I offset( ( aElem.topsize.x - aElem.topsize.y ) / 2, 0 ); - shape->SetStart( aElem.position + offset ); - shape->SetEnd( aElem.position - offset ); + aShape->SetStart( aElem.position + offset ); + aShape->SetEnd( aElem.position - offset ); } if( aElem.direction != 0 ) - shape->Rotate( aElem.position, EDA_ANGLE( aElem.direction, DEGREES_T ) ); - - HelperShapeSetLocalCoord( shape, aElem.component ); + aShape->Rotate( aElem.position, EDA_ANGLE( aElem.direction, DEGREES_T ) ); } break; case ALTIUM_PAD_SHAPE::OCTAGONAL: { // filled octagon - PCB_SHAPE* shape = HelperCreateAndAddShape( aElem.component ); - shape->SetShape( SHAPE_T::POLY ); - shape->SetFilled( true ); - shape->SetLayer( klayer ); - shape->SetStroke( STROKE_PARAMS( 0 ) ); + aShape->SetShape( SHAPE_T::POLY ); + aShape->SetFilled( true ); + aShape->SetLayer( aLayer ); + aShape->SetStroke( STROKE_PARAMS( 0 ) ); VECTOR2I p11 = aElem.position + VECTOR2I( aElem.topsize.x / 2, aElem.topsize.y / 2 ); VECTOR2I p12 = aElem.position + VECTOR2I( aElem.topsize.x / 2, -aElem.topsize.y / 2 ); @@ -2585,13 +2643,11 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) VECTOR2I chamferX( chamfer, 0 ); VECTOR2I chamferY( 0, chamfer ); - shape->SetPolyPoints( { p11 - chamferX, p11 - chamferY, p12 + chamferY, p12 - chamferX, - p22 + chamferX, p22 + chamferY, p21 - chamferY, p21 + chamferX } ); + aShape->SetPolyPoints( { p11 - chamferX, p11 - chamferY, p12 + chamferY, p12 - chamferX, + p22 + chamferX, p22 + chamferY, p21 - chamferY, p21 + chamferX } ); if( aElem.direction != 0. ) - shape->Rotate( aElem.position, EDA_ANGLE( aElem.direction, DEGREES_T ) ); - - HelperShapeSetLocalCoord( shape, aElem.component ); + aShape->Rotate( aElem.position, EDA_ANGLE( aElem.direction, DEGREES_T ) ); } break; @@ -2602,6 +2658,7 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) } } + void ALTIUM_PCB::ParseVias6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY* aEntry ) { diff --git a/pcbnew/plugins/altium/altium_pcb.h b/pcbnew/plugins/altium/altium_pcb.h index 201c768438..d6c1807cee 100644 --- a/pcbnew/plugins/altium/altium_pcb.h +++ b/pcbnew/plugins/altium/altium_pcb.h @@ -82,6 +82,7 @@ enum class ALTIUM_PCB_DIR class BOARD; +class FP_SHAPE; class PCB_SHAPE; class FOOTPRINT; class ZONE; @@ -157,6 +158,11 @@ private: const CFB::COMPOUND_FILE_ENTRY* aEntry ); void ParsePads6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY* aEntry ); + void ConvertPads6ToBoardItem( const APAD6& aElem ); + void ConvertPads6ToFootprintItem( FOOTPRINT* aFootprint, const APAD6& aElem ); + void ConvertPads6ToBoardItemOnNonCopper( const APAD6& aElem ); + void ConvertPads6ToFootprintItemOnCopper( FOOTPRINT* aFootprint, const APAD6& aElem ); + void ConvertPads6ToFootprintItemOnNonCopper( FOOTPRINT* aFootprint, const APAD6& aElem ); void ParseVias6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY* aEntry ); void ParseTracks6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile, @@ -193,7 +199,7 @@ private: void HelperParseDimensions6Datum( const ADIMENSION6& aElem ); void HelperParseDimensions6Center( const ADIMENSION6& aElem ); - void HelperParsePad6NonCopper( const APAD6& aElem ); + void HelperParsePad6NonCopper( const APAD6& aElem, PCB_LAYER_ID aLayer, PCB_SHAPE* aShape ); void HelperCreateBoardOutline( const std::vector& aVertices ); @@ -204,6 +210,7 @@ private: FOOTPRINT* HelperGetFootprint( uint16_t aComponent ) const; PCB_SHAPE* HelperCreateAndAddShape( uint16_t aComponent ); void HelperShapeSetLocalCoord( PCB_SHAPE* aShape, uint16_t aComponent ); + void HelperShapeSetLocalCoord( FP_SHAPE* aShape ); BOARD* m_board; std::vector m_components;