From a073ae5712f8ab9c3550eebc7533c35a09201044 Mon Sep 17 00:00:00 2001 From: Jon Evans Date: Sun, 10 May 2020 13:30:03 -0400 Subject: [PATCH] Properly interpret Altium pour index and pad connect style --- .../altium_parser_pcb.cpp | 14 +++++ .../altium_parser_pcb.h | 18 +++++-- pcbnew/altium2kicadpcb_plugin/altium_pcb.cpp | 52 ++++++++++++++++++- pcbnew/altium2kicadpcb_plugin/altium_pcb.h | 3 ++ 4 files changed, 82 insertions(+), 5 deletions(-) diff --git a/pcbnew/altium2kicadpcb_plugin/altium_parser_pcb.cpp b/pcbnew/altium2kicadpcb_plugin/altium_parser_pcb.cpp index 5e0376c31c..d1e56a8425 100644 --- a/pcbnew/altium2kicadpcb_plugin/altium_parser_pcb.cpp +++ b/pcbnew/altium2kicadpcb_plugin/altium_parser_pcb.cpp @@ -435,7 +435,10 @@ APOLYGON6::APOLYGON6( ALTIUM_PARSER& aReader ) minprimlength = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "MINPRIMLENGTH", "0mil" ); useoctagons = ALTIUM_PARSER::PropertiesReadBool( properties, "USEOCTAGONS", false ); + pourindex = ALTIUM_PARSER::PropertiesReadInt( properties, "POURINDEX", 0 ); + wxString hatchstyleraw = ALTIUM_PARSER::PropertiesReadString( properties, "HATCHSTYLE", "" ); + if( hatchstyleraw == "Solid" ) { hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::SOLID; @@ -540,6 +543,17 @@ ARULE6::ARULE6( ALTIUM_PARSER& aReader ) properties, "RELIEFCONDUCTORWIDTH", "10mil" ); polygonconnectReliefentries = ALTIUM_PARSER::PropertiesReadInt( properties, "RELIEFENTRIES", 4 ); + + wxString style = ALTIUM_PARSER::PropertiesReadString( properties, "CONNECTSTYLE", "" ); + + if( style == "Direct" ) + polygonconnectStyle = ALTIUM_CONNECT_STYLE::DIRECT; + else if( style == "Relief" ) + polygonconnectStyle = ALTIUM_CONNECT_STYLE::RELIEF; + else if( style == "NoConnect" ) + polygonconnectStyle = ALTIUM_CONNECT_STYLE::NONE; + else + polygonconnectStyle = ALTIUM_CONNECT_STYLE::UNKNOWN; } else { diff --git a/pcbnew/altium2kicadpcb_plugin/altium_parser_pcb.h b/pcbnew/altium2kicadpcb_plugin/altium_parser_pcb.h index 47a0a5f49c..a7a5d780e9 100644 --- a/pcbnew/altium2kicadpcb_plugin/altium_parser_pcb.h +++ b/pcbnew/altium2kicadpcb_plugin/altium_parser_pcb.h @@ -106,6 +106,14 @@ enum class ALTIUM_RULE_KIND POLYGON_CONNECT = 9, }; +enum class ALTIUM_CONNECT_STYLE +{ + UNKNOWN = 0, + DIRECT = 1, + RELIEF = 2, + NONE = 3 +}; + enum class ALTIUM_RECORD { ARC = 1, @@ -427,6 +435,9 @@ struct APOLYGON6 int32_t minprimlength; bool useoctagons; + // Note: Altium pour index is the opposite of KiCad zone priority! + int32_t pourindex; + std::vector vertices; explicit APOLYGON6( ALTIUM_PARSER& aReader ); @@ -450,9 +461,10 @@ struct ARULE6 int planeclearanceClearance; // ALTIUM_RULE_KIND::POLYGON_CONNECT - int32_t polygonconnectAirgapwidth; - int32_t polygonconnectReliefconductorwidth; - int polygonconnectReliefentries; + int32_t polygonconnectAirgapwidth; + int32_t polygonconnectReliefconductorwidth; + int polygonconnectReliefentries; + ALTIUM_CONNECT_STYLE polygonconnectStyle; // TODO: implement different types of rules we need to parse diff --git a/pcbnew/altium2kicadpcb_plugin/altium_pcb.cpp b/pcbnew/altium2kicadpcb_plugin/altium_pcb.cpp index 718fb67dd3..d8f1ba1acc 100644 --- a/pcbnew/altium2kicadpcb_plugin/altium_pcb.cpp +++ b/pcbnew/altium2kicadpcb_plugin/altium_pcb.cpp @@ -330,8 +330,9 @@ PCB_LAYER_ID ALTIUM_PCB::GetKicadLayer( ALTIUM_LAYER aAltiumLayer ) const ALTIUM_PCB::ALTIUM_PCB( BOARD* aBoard ) { - m_board = aBoard; - m_num_nets = 0; + m_board = aBoard; + m_num_nets = 0; + m_highest_pour_index = 0; } ALTIUM_PCB::~ALTIUM_PCB() @@ -453,6 +454,27 @@ void ALTIUM_PCB::Parse( const CFB::CompoundFileReader& aReader, } } + // fixup zone priorities since Altium stores them in the opposite order + for( auto& zone : m_polygons ) + { + if( !zone ) + continue; + + // Altium "fills" - not poured in Altium + if( zone->GetPriority() == 1000 ) + { + // Unlikely, but you never know + if( m_highest_pour_index >= 1000 ) + zone->SetPriority( m_highest_pour_index + 1 ); + + continue; + } + + int priority = m_highest_pour_index - zone->GetPriority(); + + zone->SetPriority( priority >= 0 ? priority : 0 ); + } + // change priority of outer zone to zero for( auto& zone : m_outer_plane ) { @@ -1249,6 +1271,10 @@ void ALTIUM_PCB::ParsePolygons6Data( zone->SetLayer( klayer ); zone->SetPosition( elem.vertices.at( 0 ).position ); zone->SetLocked( elem.locked ); + zone->SetPriority( elem.pourindex > 0 ? elem.pourindex : 0 ); + + if( elem.pourindex > m_highest_pour_index ) + m_highest_pour_index = elem.pourindex; for( auto& vertice : elem.vertices ) { @@ -1257,17 +1283,39 @@ void ALTIUM_PCB::ParsePolygons6Data( // TODO: more flexible rule parsing const ARULE6* clearanceRule = GetRuleDefault( ALTIUM_RULE_KIND::PLANE_CLEARANCE ); + if( clearanceRule != nullptr ) { zone->SetZoneClearance( clearanceRule->planeclearanceClearance ); } + const ARULE6* polygonConnectRule = GetRuleDefault( ALTIUM_RULE_KIND::POLYGON_CONNECT ); + if( polygonConnectRule != nullptr ) { + switch( polygonConnectRule->polygonconnectStyle ) + { + case ALTIUM_CONNECT_STYLE::DIRECT: + zone->SetPadConnection( ZONE_CONNECTION::FULL ); + break; + + case ALTIUM_CONNECT_STYLE::NONE: + zone->SetPadConnection( ZONE_CONNECTION::NONE ); + break; + + default: + case ALTIUM_CONNECT_STYLE::RELIEF: + zone->SetPadConnection( ZONE_CONNECTION::THERMAL ); + break; + } + // TODO: correct variables? zone->SetThermalReliefCopperBridge( polygonConnectRule->polygonconnectReliefconductorwidth ); zone->SetThermalReliefGap( polygonConnectRule->polygonconnectAirgapwidth ); + + if( polygonConnectRule->polygonconnectReliefconductorwidth < zone->GetMinThickness() ) + zone->SetMinThickness( polygonConnectRule->polygonconnectReliefconductorwidth ); } if( IsAltiumLayerAPlane( elem.layer ) ) diff --git a/pcbnew/altium2kicadpcb_plugin/altium_pcb.h b/pcbnew/altium2kicadpcb_plugin/altium_pcb.h index b13b3fffcb..0781b0634d 100644 --- a/pcbnew/altium2kicadpcb_plugin/altium_pcb.h +++ b/pcbnew/altium2kicadpcb_plugin/altium_pcb.h @@ -191,6 +191,9 @@ private: std::map> m_rules; std::map m_outer_plane; + + /// Altium stores pour order across all layers + int m_highest_pour_index; };