CADSTAR PCB: Fix loading of thermal pads
- Create a pad if a component copper is associated with any other pads in the footprint. - Rename/renumber 'PCB Only' pads that are associated with a component copper and make them all use the same pad name/number.
This commit is contained in:
parent
2eb96279a2
commit
b5edd5f6a5
|
@ -661,9 +661,10 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadComponentLibrary()
|
|||
|
||||
footprint->SetFPID( libID );
|
||||
loadLibraryFigures( component, footprint );
|
||||
loadLibraryCoppers( component, footprint );
|
||||
loadLibraryAreas( component, footprint );
|
||||
loadLibraryPads( component, footprint );
|
||||
loadLibraryCoppers( component, footprint ); // Load coppers after pads to ensure correct
|
||||
// ordering of pads in footprint->Pads()
|
||||
|
||||
m_libraryMap.insert( std::make_pair( key, footprint ) );
|
||||
}
|
||||
|
@ -690,15 +691,94 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadLibraryFigures( const SYMDEF_PCB& aComponen
|
|||
|
||||
void CADSTAR_PCB_ARCHIVE_LOADER::loadLibraryCoppers( const SYMDEF_PCB& aComponent, FOOTPRINT* aFootprint )
|
||||
{
|
||||
int totalCopperPads = 0;
|
||||
|
||||
for( COMPONENT_COPPER compCopper : aComponent.ComponentCoppers )
|
||||
{
|
||||
int lineThickness = getKiCadLength( getCopperCode( compCopper.CopperCodeID ).CopperWidth );
|
||||
PCB_LAYER_ID copperLayer = getKiCadLayer( compCopper.LayerID );
|
||||
|
||||
drawCadstarShape( compCopper.Shape, getKiCadLayer( compCopper.LayerID ), lineThickness,
|
||||
wxString::Format( "Component %s:%s -> Copper element",
|
||||
aComponent.ReferenceName,
|
||||
aComponent.Alternate ),
|
||||
aFootprint );
|
||||
if( compCopper.AssociatedPadIDs.size() > 0 && LSET::AllCuMask().Contains( copperLayer )
|
||||
&& compCopper.Shape.Type == SHAPE_TYPE::SOLID )
|
||||
{
|
||||
// The copper is associated with pads and in an electrical layer which means it can
|
||||
// have a net associated with it. Load as a pad instead.
|
||||
// Note: we can only handle SOLID copper shapes. If the copper shape is an outline or
|
||||
// hatched or outline, then we give up and load as a graphical shape instead.
|
||||
|
||||
// Find the first non-PCB-only pad. If there are none, use the first one
|
||||
COMPONENT_PAD anchorPad;
|
||||
bool found = false;
|
||||
|
||||
for( PAD_ID padID : compCopper.AssociatedPadIDs )
|
||||
{
|
||||
anchorPad = aComponent.ComponentPads.at( padID );
|
||||
|
||||
if( !anchorPad.PCBonlyPad )
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !found )
|
||||
anchorPad = aComponent.ComponentPads.at( compCopper.AssociatedPadIDs.front() );
|
||||
|
||||
|
||||
PAD* pad = new PAD( aFootprint );
|
||||
pad->SetAttribute( PAD_ATTR_T::PAD_ATTRIB_SMD );
|
||||
pad->SetLayerSet( LSET( 1, copperLayer ) );
|
||||
pad->SetName( anchorPad.Identifier.IsEmpty()
|
||||
? wxString::Format( wxT( "%ld" ), anchorPad.ID )
|
||||
: anchorPad.Identifier );
|
||||
|
||||
// Custom pad shape with an anchor at the position of one of the associated
|
||||
// pads and same size as the pad. Shape circle as it fits inside a rectangle
|
||||
// but not the other way round
|
||||
PADCODE anchorpadcode = getPadCode( anchorPad.PadCodeID );
|
||||
int anchorSize = getKiCadLength( anchorpadcode.Shape.Size );
|
||||
wxPoint anchorPos = getKiCadPoint( anchorPad.Position );
|
||||
|
||||
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_CUSTOM );
|
||||
pad->SetAnchorPadShape( PAD_SHAPE_CIRCLE );
|
||||
pad->SetSize( { anchorSize, anchorSize } );
|
||||
pad->SetPosition( anchorPos );
|
||||
pad->SetLocalCoord();
|
||||
pad->SetLocked( true ); // Cadstar pads are always locked with respect to the footprint
|
||||
|
||||
SHAPE_POLY_SET shapePolys = getPolySetFromCadstarShape( compCopper.Shape,
|
||||
lineThickness,
|
||||
aFootprint );
|
||||
shapePolys.Move( aFootprint->GetPosition() - anchorPos );
|
||||
pad->AddPrimitivePoly( shapePolys, 0, true );
|
||||
|
||||
aFootprint->Add( pad, ADD_MODE::APPEND ); // Append so that we get the correct behaviour
|
||||
// when finding pads by PAD_ID. See loadNets()
|
||||
|
||||
m_librarycopperpads[aComponent.ID][anchorPad.ID].push_back( aFootprint->Pads().size() );
|
||||
totalCopperPads++;
|
||||
|
||||
// Now renumber all the associated pads if they are PCB Only
|
||||
COMPONENT_PAD associatedPad;
|
||||
|
||||
for( PAD_ID padID : compCopper.AssociatedPadIDs )
|
||||
{
|
||||
associatedPad = aComponent.ComponentPads.at( padID );
|
||||
|
||||
if( associatedPad.PCBonlyPad )
|
||||
{
|
||||
PAD* assocPad = getPadReference( aFootprint, padID );
|
||||
assocPad->SetName( pad->GetName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
drawCadstarShape( compCopper.Shape, copperLayer, lineThickness,
|
||||
wxString::Format( "Component %s:%s -> Copper element",
|
||||
aComponent.ReferenceName, aComponent.Alternate ),
|
||||
aFootprint );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -755,7 +835,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadLibraryPads( const SYMDEF_PCB& aComponent,
|
|||
for( std::pair<PAD_ID, COMPONENT_PAD> padPair : aComponent.ComponentPads )
|
||||
{
|
||||
PAD* pad = getKiCadPad( padPair.second, aFootprint );
|
||||
aFootprint->Add( pad, ADD_MODE::INSERT ); // insert so that we get correct behaviour
|
||||
aFootprint->Add( pad, ADD_MODE::APPEND ); // Append so that we get correct behaviour
|
||||
// when finding pads by PAD_ID - see loadNets()
|
||||
}
|
||||
}
|
||||
|
@ -1086,6 +1166,13 @@ PAD* CADSTAR_PCB_ARCHIVE_LOADER::getKiCadPad( const COMPONENT_PAD& aCadstarPad,
|
|||
}
|
||||
|
||||
|
||||
PAD*& CADSTAR_PCB_ARCHIVE_LOADER::getPadReference( FOOTPRINT* aFootprint,
|
||||
const PAD_ID aCadstarPadID )
|
||||
{
|
||||
return aFootprint->Pads().at( aCadstarPadID - (long long) 1 );
|
||||
}
|
||||
|
||||
|
||||
void CADSTAR_PCB_ARCHIVE_LOADER::loadGroups()
|
||||
{
|
||||
for( std::pair<GROUP_ID, GROUP> groupPair : Layout.Groups )
|
||||
|
@ -1506,7 +1593,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadComponents()
|
|||
if( pinName.empty() )
|
||||
pinName = wxString::Format( wxT( "%ld" ), pin.ID );
|
||||
|
||||
footprint->Pads().at( pin.ID - (long long) 1 )->SetName( pinName );
|
||||
getPadReference( footprint, pin.ID )->SetName( pinName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1534,7 +1621,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadComponents()
|
|||
csPad.Side = padEx.Side;
|
||||
|
||||
// Find the pad in the footprint definition
|
||||
PAD* kiPad = footprint->Pads().at( padEx.ID - (long long) 1 );
|
||||
PAD* kiPad = getPadReference( footprint, padEx.ID );
|
||||
wxString padName = kiPad->GetName();
|
||||
|
||||
if( kiPad )
|
||||
|
@ -1542,7 +1629,9 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadComponents()
|
|||
|
||||
kiPad = getKiCadPad( csPad, footprint );
|
||||
kiPad->SetName( padName );
|
||||
footprint->Pads().at( padEx.ID - (long long) 1 ) = kiPad;
|
||||
|
||||
// Change the pointer in the footprint to the newly created pad
|
||||
getPadReference( footprint, padEx.ID ) = kiPad;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2034,9 +2123,27 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadNets()
|
|||
{
|
||||
// The below works because we have added the pads in the correct order to the
|
||||
// footprint and the PAD_ID in Cadstar is a sequential, numerical ID
|
||||
PAD* pad = footprint->Pads().at( pin.PadID - (long) 1 );
|
||||
PAD* pad = getPadReference( footprint, pin.PadID );
|
||||
pad->SetNet( getKiCadNet( net.ID ) );
|
||||
|
||||
// also set the net to any copper pads (i.e. copper elements that we have imported
|
||||
// as pads instead:
|
||||
SYMDEF_ID symdefid = Layout.Components.at( pin.ComponentID ).SymdefID;
|
||||
|
||||
if( m_librarycopperpads.find( symdefid ) != m_librarycopperpads.end() )
|
||||
{
|
||||
ASSOCIATED_COPPER_PADS assocPads = m_librarycopperpads.at( symdefid );
|
||||
|
||||
if( assocPads.find( pin.PadID ) != assocPads.end() )
|
||||
{
|
||||
for( PAD_ID copperPadID : assocPads.at( pin.PadID ) )
|
||||
{
|
||||
PAD* copperpad = getPadReference( footprint, copperPadID );
|
||||
copperpad->SetNet( getKiCadNet( net.ID ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// padsize is used for calculating route offset (as done in CADSTAR post processor)
|
||||
int padsize = std::min( pad->GetSizeX(), pad->GetSizeY() );
|
||||
netelementSizes.insert( { pinPair.first, padsize } );
|
||||
|
|
|
@ -96,6 +96,18 @@ private:
|
|||
///< components on the board. Does NOT own
|
||||
///< the FOOTPRINT objects (these should
|
||||
///< have been loaded to m_board).
|
||||
|
||||
/**
|
||||
* Map of pad anchor points (first) to copper pads (second). In the vast majority
|
||||
* of designs there is only one copper pad, but just in case, making it a vector
|
||||
*/
|
||||
using ASSOCIATED_COPPER_PADS = std::map<PAD_ID, std::vector<PAD_ID>>;
|
||||
|
||||
/**
|
||||
* Associated copper pads (if any) for each component library definition
|
||||
*/
|
||||
std::map<SYMDEF_ID, ASSOCIATED_COPPER_PADS> m_librarycopperpads;
|
||||
|
||||
std::map<NET_ID, NETINFO_ITEM*> m_netMap; ///< Map between Cadstar and KiCad Nets
|
||||
std::map<ROUTECODE_ID, NETCLASSPTR> m_netClassMap; ///< Map between Cadstar and KiCad classes
|
||||
std::map<TEMPLATE_ID, ZONE*> m_zonesMap; ///< Map between Cadstar and KiCad zones
|
||||
|
@ -394,6 +406,7 @@ private:
|
|||
// Helper Functions for obtaining individual elements as KiCad elements:
|
||||
double getHatchCodeAngleDegrees( const HATCHCODE_ID& aCadstarHatchcodeID );
|
||||
PAD* getKiCadPad( const COMPONENT_PAD& aCadstarPad, FOOTPRINT* aParent );
|
||||
PAD*& getPadReference( FOOTPRINT* aFootprint, const PAD_ID aCadstarPadID );
|
||||
FOOTPRINT* getFootprintFromCadstarID( const COMPONENT_ID& aCadstarComponentID );
|
||||
int getKiCadHatchCodeThickness( const HATCHCODE_ID& aCadstarHatchcodeID );
|
||||
int getKiCadHatchCodeGap( const HATCHCODE_ID& aCadstarHatchcodeID );
|
||||
|
|
Loading…
Reference in New Issue