altium: Parse solder and paste mask settings of tracks and arcs

This commit is contained in:
Thomas Pointhuber 2022-02-20 20:18:22 +01:00
parent 5efd29d6f4
commit 52a2d52bf0
6 changed files with 311 additions and 35 deletions

View File

@ -166,12 +166,92 @@ void altium_parse_polygons( std::map<wxString, wxString>& aProps,
} }
} }
static ALTIUM_MODE ReadAltiumModeFromProperties( const std::map<wxString, wxString>& aProps,
wxString aKey )
{
wxString mode = ALTIUM_PARSER::ReadString( aProps, aKey, wxT( "" ) );
if( mode == wxT( "None" ) )
return ALTIUM_MODE::NONE;
else if( mode == wxT( "Rule" ) )
return ALTIUM_MODE::RULE;
else if( mode == wxT( "Manual" ) )
return ALTIUM_MODE::MANUAL;
wxLogError( _( "Unknown Mode string: '%s'." ), mode );
return ALTIUM_MODE::UNKNOWN;
}
static ALTIUM_RECORD ReadAltiumRecordFromProperties( const std::map<wxString, wxString>& aProps,
wxString aKey )
{
wxString record = ALTIUM_PARSER::ReadString( aProps, aKey, wxT( "" ) );
if( record == wxT( "Arc" ) )
return ALTIUM_RECORD::ARC;
else if( record == wxT( "Pad" ) )
return ALTIUM_RECORD::PAD;
else if( record == wxT( "Via" ) )
return ALTIUM_RECORD::VIA;
else if( record == wxT( "Track" ) )
return ALTIUM_RECORD::TRACK;
else if( record == wxT( "Text" ) )
return ALTIUM_RECORD::TEXT;
else if( record == wxT( "Fill" ) )
return ALTIUM_RECORD::FILL;
else if( record == wxT( "Region" ) ) // correct?
return ALTIUM_RECORD::REGION;
else if( record == wxT( "Model" ) )
return ALTIUM_RECORD::MODEL;
wxLogError( _( "Unknown Record name string: '%s'." ), record );
return ALTIUM_RECORD::UNKNOWN;
}
static AEXTENDED_PRIMITIVE_INFORMATION_TYPE
ReadAltiumExtendedPrimitiveInformationTypeFromProperties(
const std::map<wxString, wxString>& aProps, wxString aKey )
{
wxString parsedType = ALTIUM_PARSER::ReadString( aProps, aKey, wxT( "" ) );
if( parsedType == wxT( "Mask" ) )
return AEXTENDED_PRIMITIVE_INFORMATION_TYPE::MASK;
wxLogError( _( "Unknown Extended Primitive Information type: '%s'." ), parsedType );
return AEXTENDED_PRIMITIVE_INFORMATION_TYPE::UNKNOWN;
}
AEXTENDED_PRIMITIVE_INFORMATION::AEXTENDED_PRIMITIVE_INFORMATION( ALTIUM_PARSER& aReader )
{
const std::map<wxString, wxString> props = aReader.ReadProperties();
if( props.empty() )
THROW_IO_ERROR( wxT( "ExtendedPrimitiveInformation stream has no properties!" ) );
primitiveIndex = ALTIUM_PARSER::ReadInt( props, wxT( "PRIMITIVEINDEX" ), -1 );
primitiveObjectId = ReadAltiumRecordFromProperties( props, wxT( "PRIMITIVEOBJECTID" ) );
type = ReadAltiumExtendedPrimitiveInformationTypeFromProperties( props, wxT( "TYPE" ) );
pastemaskexpansionmode = ReadAltiumModeFromProperties( props, wxT( "PASTEMASKEXPANSIONMODE" ) );
pastemaskexpansionmanual = ALTIUM_PARSER::ReadKicadUnit(
props, wxT( "PASTEMASKEXPANSION_MANUAL" ), wxT( "0mil" ) );
soldermaskexpansionmode =
ReadAltiumModeFromProperties( props, wxT( "SOLDERMASKEXPANSIONMODE" ) );
soldermaskexpansionmanual = ALTIUM_PARSER::ReadKicadUnit(
props, wxT( "SOLDERMASKEXPANSION_MANUAL" ), wxT( "0mil" ) );
}
ABOARD6::ABOARD6( ALTIUM_PARSER& aReader ) ABOARD6::ABOARD6( ALTIUM_PARSER& aReader )
{ {
std::map<wxString, wxString> props = aReader.ReadProperties(); std::map<wxString, wxString> props = aReader.ReadProperties();
if( props.empty() ) if( props.empty() )
THROW_IO_ERROR( wxT( "Board6 stream has no props!" ) ); THROW_IO_ERROR( wxT( "Board6 stream has no properties!" ) );
sheetpos = VECTOR2I( ALTIUM_PARSER::ReadKicadUnit( props, wxT( "SHEETX" ), wxT( "0mil" ) ), sheetpos = VECTOR2I( ALTIUM_PARSER::ReadKicadUnit( props, wxT( "SHEETX" ), wxT( "0mil" ) ),
-ALTIUM_PARSER::ReadKicadUnit( props, wxT( "SHEETY" ), wxT( "0mil" ) ) ); -ALTIUM_PARSER::ReadKicadUnit( props, wxT( "SHEETY" ), wxT( "0mil" ) ) );
@ -634,8 +714,8 @@ APAD6::APAD6( ALTIUM_PARSER& aReader )
pastemaskexpansionmanual = aReader.ReadKicadUnit(); pastemaskexpansionmanual = aReader.ReadKicadUnit();
soldermaskexpansionmanual = aReader.ReadKicadUnit(); soldermaskexpansionmanual = aReader.ReadKicadUnit();
aReader.Skip( 7 ); aReader.Skip( 7 );
pastemaskexpansionmode = static_cast<ALTIUM_PAD_RULE>( aReader.Read<uint8_t>() ); pastemaskexpansionmode = static_cast<ALTIUM_MODE>( aReader.Read<uint8_t>() );
soldermaskexpansionmode = static_cast<ALTIUM_PAD_RULE>( aReader.Read<uint8_t>() ); soldermaskexpansionmode = static_cast<ALTIUM_MODE>( aReader.Read<uint8_t>() );
aReader.Skip( 3 ); aReader.Skip( 3 );
holerotation = aReader.Read<double>(); holerotation = aReader.Read<double>();

View File

@ -119,14 +119,16 @@ enum class ALTIUM_CONNECT_STYLE
enum class ALTIUM_RECORD enum class ALTIUM_RECORD
{ {
ARC = 1, UNKNOWN = -1,
PAD = 2,
VIA = 3, ARC = 1,
TRACK = 4, PAD = 2,
TEXT = 5, VIA = 3,
FILL = 6, TRACK = 4,
TEXT = 5,
FILL = 6,
REGION = 11, REGION = 11,
MODEL = 12 MODEL = 12
}; };
enum class ALTIUM_PAD_SHAPE enum class ALTIUM_PAD_SHAPE
@ -161,11 +163,12 @@ enum class ALTIUM_PAD_MODE
FULL_STACK = 2 FULL_STACK = 2
}; };
enum class ALTIUM_PAD_RULE enum class ALTIUM_MODE
{ {
UNKNOWN = 0, UNKNOWN = -1,
RULE = 1, NONE = 0, // TODO: correct ID?
MANUAL = 2 RULE = 1,
MANUAL = 2
}; };
enum class ALTIUM_POLYGON_HATCHSTYLE enum class ALTIUM_POLYGON_HATCHSTYLE
@ -329,6 +332,29 @@ enum class ALTIUM_LAYER
class ALTIUM_PARSER; class ALTIUM_PARSER;
enum class AEXTENDED_PRIMITIVE_INFORMATION_TYPE
{
UNKNOWN = -1,
MASK
};
struct AEXTENDED_PRIMITIVE_INFORMATION
{
int primitiveIndex;
ALTIUM_RECORD primitiveObjectId;
AEXTENDED_PRIMITIVE_INFORMATION_TYPE type;
// Type == Mask
ALTIUM_MODE pastemaskexpansionmode;
int32_t pastemaskexpansionmanual;
ALTIUM_MODE soldermaskexpansionmode;
int32_t soldermaskexpansionmanual;
explicit AEXTENDED_PRIMITIVE_INFORMATION( ALTIUM_PARSER& aReader );
};
struct ABOARD6_LAYER_STACKUP struct ABOARD6_LAYER_STACKUP
{ {
wxString name; wxString name;
@ -585,9 +611,9 @@ struct APAD6
double direction; double direction;
bool plated; bool plated;
ALTIUM_PAD_RULE pastemaskexpansionmode; ALTIUM_MODE pastemaskexpansionmode;
int32_t pastemaskexpansionmanual; int32_t pastemaskexpansionmanual;
ALTIUM_PAD_RULE soldermaskexpansionmode; ALTIUM_MODE soldermaskexpansionmode;
int32_t soldermaskexpansionmanual; int32_t soldermaskexpansionmanual;
double holerotation; double holerotation;

View File

@ -379,6 +379,11 @@ void ALTIUM_PCB::Parse( const ALTIUM_COMPOUND_FILE& altiumPcbFi
{ {
this->ParseBoard6Data( aFile, fileHeader ); this->ParseBoard6Data( aFile, fileHeader );
} }, } },
{ false, ALTIUM_PCB_DIR::EXTENDPRIMITIVEINFORMATION,
[this]( const ALTIUM_COMPOUND_FILE& aFile, auto fileHeader )
{
this->ParseExtendedPrimitiveInformationData( aFile, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::COMPONENTS6, { true, ALTIUM_PCB_DIR::COMPONENTS6,
[this]( const ALTIUM_COMPOUND_FILE& aFile, auto fileHeader ) [this]( const ALTIUM_COMPOUND_FILE& aFile, auto fileHeader )
{ {
@ -660,6 +665,7 @@ FOOTPRINT* ALTIUM_PCB::ParseFootprint( const ALTIUM_COMPOUND_FILE& altiumLibFile
m_layermap.emplace( ALTIUM_LAYER::MECHANICAL_16, Eco2_User ); m_layermap.emplace( ALTIUM_LAYER::MECHANICAL_16, Eco2_User );
m_unicodeStrings.clear(); m_unicodeStrings.clear();
m_extendedPrimitiveInformationMaps.clear();
// TODO: WideStrings are stored as parameterMap in the case of footprints, not as binary // TODO: WideStrings are stored as parameterMap in the case of footprints, not as binary
// std::string unicodeStringsStreamName = aFootprintName.ToStdString() + "\\WideStrings"; // std::string unicodeStringsStreamName = aFootprintName.ToStdString() + "\\WideStrings";
// const CFB::COMPOUND_FILE_ENTRY* unicodeStringsData = altiumLibFile.FindStream( unicodeStringsStreamName ); // const CFB::COMPOUND_FILE_ENTRY* unicodeStringsData = altiumLibFile.FindStream( unicodeStringsStreamName );
@ -710,7 +716,7 @@ FOOTPRINT* ALTIUM_PCB::ParseFootprint( const ALTIUM_COMPOUND_FILE& altiumLibFile
altiumLibFile.FindStream( extendedPrimitiveInformationStreamName ); altiumLibFile.FindStream( extendedPrimitiveInformationStreamName );
if( extendedPrimitiveInformationData != nullptr ) if( extendedPrimitiveInformationData != nullptr )
{ {
// TODO: implement ParseExtendedPrimitiveInformationData( altiumLibFile, extendedPrimitiveInformationData );
} }
footprint->SetReference( wxT( "REF**" ) ); footprint->SetReference( wxT( "REF**" ) );
@ -718,7 +724,7 @@ FOOTPRINT* ALTIUM_PCB::ParseFootprint( const ALTIUM_COMPOUND_FILE& altiumLibFile
footprint->Reference().SetVisible( true ); // TODO: extract visibility information footprint->Reference().SetVisible( true ); // TODO: extract visibility information
footprint->Value().SetVisible( true ); footprint->Value().SetVisible( true );
while( parser.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ ) for( int primitiveIndex = 0; parser.GetRemainingBytes() >= 4; primitiveIndex++ )
{ {
ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( parser.Peek<uint8_t>() ); ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( parser.Peek<uint8_t>() );
switch( recordtype ) switch( recordtype )
@ -726,7 +732,7 @@ FOOTPRINT* ALTIUM_PCB::ParseFootprint( const ALTIUM_COMPOUND_FILE& altiumLibFile
case ALTIUM_RECORD::ARC: case ALTIUM_RECORD::ARC:
{ {
AARC6 arc( parser ); AARC6 arc( parser );
ConvertArcs6ToFootprintItem( footprint.get(), arc, false ); ConvertArcs6ToFootprintItem( footprint.get(), arc, primitiveIndex, false );
break; break;
} }
case ALTIUM_RECORD::PAD: case ALTIUM_RECORD::PAD:
@ -744,7 +750,7 @@ FOOTPRINT* ALTIUM_PCB::ParseFootprint( const ALTIUM_COMPOUND_FILE& altiumLibFile
case ALTIUM_RECORD::TRACK: case ALTIUM_RECORD::TRACK:
{ {
ATRACK6 track( parser ); ATRACK6 track( parser );
ConvertTracks6ToFootprintItem( footprint.get(), track, false ); ConvertTracks6ToFootprintItem( footprint.get(), track, primitiveIndex, false );
break; break;
} }
case ALTIUM_RECORD::TEXT: case ALTIUM_RECORD::TEXT:
@ -860,6 +866,27 @@ void ALTIUM_PCB::ParseFileHeader( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile
//} //}
} }
void ALTIUM_PCB::ParseExtendedPrimitiveInformationData( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile,
const CFB::COMPOUND_FILE_ENTRY* aEntry )
{
if( m_progressReporter )
m_progressReporter->Report( _( "Loading extended primitive information data..." ) );
ALTIUM_PARSER reader( aAltiumPcbFile, aEntry );
while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
{
checkpoint();
AEXTENDED_PRIMITIVE_INFORMATION elem( reader );
m_extendedPrimitiveInformationMaps[elem.primitiveObjectId].emplace( elem.primitiveIndex,
std::move( elem ) );
}
if( reader.GetRemainingBytes() != 0 )
THROW_IO_ERROR( wxT( "ExtendedPrimitiveInformation stream is not fully parsed" ) );
}
void ALTIUM_PCB::ParseBoard6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile, void ALTIUM_PCB::ParseBoard6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile,
const CFB::COMPOUND_FILE_ENTRY* aEntry ) const CFB::COMPOUND_FILE_ENTRY* aEntry )
{ {
@ -2128,19 +2155,19 @@ void ALTIUM_PCB::ParseArcs6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile,
ALTIUM_PARSER reader( aAltiumPcbFile, aEntry ); ALTIUM_PARSER reader( aAltiumPcbFile, aEntry );
while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ ) for( int primitiveIndex = 0; reader.GetRemainingBytes() >= 4; primitiveIndex++ )
{ {
checkpoint(); checkpoint();
AARC6 elem( reader ); AARC6 elem( reader );
if( elem.component == ALTIUM_COMPONENT_NONE ) if( elem.component == ALTIUM_COMPONENT_NONE )
{ {
ConvertArcs6ToBoardItem( elem ); ConvertArcs6ToBoardItem( elem, primitiveIndex );
} }
else else
{ {
FOOTPRINT* footprint = HelperGetFootprint( elem.component ); FOOTPRINT* footprint = HelperGetFootprint( elem.component );
ConvertArcs6ToFootprintItem( footprint, elem, true ); ConvertArcs6ToFootprintItem( footprint, elem, primitiveIndex, true );
} }
} }
@ -2178,7 +2205,7 @@ void ALTIUM_PCB::ConvertArcs6ToPcbShape( const AARC6& aElem, PCB_SHAPE* aShape )
} }
void ALTIUM_PCB::ConvertArcs6ToBoardItem( const AARC6& aElem ) void ALTIUM_PCB::ConvertArcs6ToBoardItem( const AARC6& aElem, const int aPrimitiveIndex )
{ {
if( aElem.is_polygonoutline || aElem.subpolyindex != ALTIUM_POLYGON_NONE ) if( aElem.is_polygonoutline || aElem.subpolyindex != ALTIUM_POLYGON_NONE )
return; return;
@ -2200,11 +2227,27 @@ void ALTIUM_PCB::ConvertArcs6ToBoardItem( const AARC6& aElem )
ConvertArcs6ToBoardItemOnLayer( aElem, klayer ); ConvertArcs6ToBoardItemOnLayer( aElem, klayer );
} }
} }
for( const auto layerExpansionMask :
HelperGetSolderAndPasteMaskExpansions( ALTIUM_RECORD::ARC, aPrimitiveIndex, aElem.layer ) )
{
int width = aElem.width + ( layerExpansionMask.second * 2 );
if( width > 1 )
{
PCB_SHAPE* arc = new PCB_SHAPE( m_board );
ConvertArcs6ToPcbShape( aElem, arc );
arc->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) );
arc->SetLayer( layerExpansionMask.first );
m_board->Add( arc, ADD_MODE::APPEND );
}
}
} }
void ALTIUM_PCB::ConvertArcs6ToFootprintItem( FOOTPRINT* aFootprint, const AARC6& aElem, void ALTIUM_PCB::ConvertArcs6ToFootprintItem( FOOTPRINT* aFootprint, const AARC6& aElem,
const bool aIsBoardImport ) const int aPrimitiveIndex, const bool aIsBoardImport )
{ {
if( aElem.is_polygonoutline || aElem.subpolyindex != ALTIUM_POLYGON_NONE ) if( aElem.is_polygonoutline || aElem.subpolyindex != ALTIUM_POLYGON_NONE )
return; return;
@ -2234,6 +2277,23 @@ void ALTIUM_PCB::ConvertArcs6ToFootprintItem( FOOTPRINT* aFootprint, const AARC6
} }
} }
} }
for( const auto layerExpansionMask :
HelperGetSolderAndPasteMaskExpansions( ALTIUM_RECORD::ARC, aPrimitiveIndex, aElem.layer ) )
{
int width = aElem.width + ( layerExpansionMask.second * 2 );
if( width > 1 )
{
FP_SHAPE* arc = new FP_SHAPE( aFootprint );
ConvertArcs6ToPcbShape( aElem, arc );
arc->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) );
arc->SetLayer( layerExpansionMask.first );
arc->SetLocalCoord();
aFootprint->Add( arc, ADD_MODE::APPEND );
}
}
} }
@ -2508,12 +2568,12 @@ void ALTIUM_PCB::ConvertPads6ToFootprintItemOnCopper( FOOTPRINT* aFootprint, con
break; break;
} }
if( aElem.pastemaskexpansionmode == ALTIUM_PAD_RULE::MANUAL ) if( aElem.pastemaskexpansionmode == ALTIUM_MODE::MANUAL )
{ {
pad->SetLocalSolderPasteMargin( aElem.pastemaskexpansionmanual ); pad->SetLocalSolderPasteMargin( aElem.pastemaskexpansionmanual );
} }
if( aElem.soldermaskexpansionmode == ALTIUM_PAD_RULE::MANUAL ) if( aElem.soldermaskexpansionmode == ALTIUM_MODE::MANUAL )
{ {
pad->SetLocalSolderMaskMargin( aElem.soldermaskexpansionmanual ); pad->SetLocalSolderMaskMargin( aElem.soldermaskexpansionmanual );
} }
@ -2807,19 +2867,19 @@ void ALTIUM_PCB::ParseTracks6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFil
ALTIUM_PARSER reader( aAltiumPcbFile, aEntry ); ALTIUM_PARSER reader( aAltiumPcbFile, aEntry );
while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ ) for( int primitiveIndex = 0; reader.GetRemainingBytes() >= 4; primitiveIndex++ )
{ {
checkpoint(); checkpoint();
ATRACK6 elem( reader ); ATRACK6 elem( reader );
if( elem.component == ALTIUM_COMPONENT_NONE ) if( elem.component == ALTIUM_COMPONENT_NONE )
{ {
ConvertTracks6ToBoardItem( elem ); ConvertTracks6ToBoardItem( elem, primitiveIndex );
} }
else else
{ {
FOOTPRINT* footprint = HelperGetFootprint( elem.component ); FOOTPRINT* footprint = HelperGetFootprint( elem.component );
ConvertTracks6ToFootprintItem( footprint, elem, true ); ConvertTracks6ToFootprintItem( footprint, elem, primitiveIndex, true );
} }
} }
@ -2830,7 +2890,7 @@ void ALTIUM_PCB::ParseTracks6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFil
} }
void ALTIUM_PCB::ConvertTracks6ToBoardItem( const ATRACK6& aElem ) void ALTIUM_PCB::ConvertTracks6ToBoardItem( const ATRACK6& aElem, const int aPrimitiveIndex )
{ {
if( aElem.is_polygonoutline || aElem.subpolyindex != ALTIUM_POLYGON_NONE ) if( aElem.is_polygonoutline || aElem.subpolyindex != ALTIUM_POLYGON_NONE )
return; return;
@ -2852,10 +2912,28 @@ void ALTIUM_PCB::ConvertTracks6ToBoardItem( const ATRACK6& aElem )
ConvertTracks6ToBoardItemOnLayer( aElem, klayer ); ConvertTracks6ToBoardItemOnLayer( aElem, klayer );
} }
} }
for( const auto layerExpansionMask : HelperGetSolderAndPasteMaskExpansions(
ALTIUM_RECORD::TRACK, aPrimitiveIndex, aElem.layer ) )
{
int width = aElem.width + ( layerExpansionMask.second * 2 );
if( width > 1 )
{
PCB_SHAPE* seg = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT );
seg->SetStart( aElem.start );
seg->SetEnd( aElem.end );
seg->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) );
seg->SetLayer( layerExpansionMask.first );
m_board->Add( seg, ADD_MODE::APPEND );
}
}
} }
void ALTIUM_PCB::ConvertTracks6ToFootprintItem( FOOTPRINT* aFootprint, const ATRACK6& aElem, void ALTIUM_PCB::ConvertTracks6ToFootprintItem( FOOTPRINT* aFootprint, const ATRACK6& aElem,
const int aPrimitiveIndex,
const bool aIsBoardImport ) const bool aIsBoardImport )
{ {
if( aElem.is_polygonoutline || aElem.subpolyindex != ALTIUM_POLYGON_NONE ) if( aElem.is_polygonoutline || aElem.subpolyindex != ALTIUM_POLYGON_NONE )
@ -2886,6 +2964,24 @@ void ALTIUM_PCB::ConvertTracks6ToFootprintItem( FOOTPRINT* aFootprint, const ATR
} }
} }
} }
for( const auto layerExpansionMask : HelperGetSolderAndPasteMaskExpansions(
ALTIUM_RECORD::TRACK, aPrimitiveIndex, aElem.layer ) )
{
int width = aElem.width + ( layerExpansionMask.second * 2 );
if( width > 1 )
{
FP_SHAPE* seg = new FP_SHAPE( aFootprint, SHAPE_T::SEGMENT );
seg->SetStart( aElem.start );
seg->SetEnd( aElem.end );
seg->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) );
seg->SetLayer( layerExpansionMask.first );
seg->SetLocalCoord();
aFootprint->Add( seg, ADD_MODE::APPEND );
}
}
} }
@ -3370,6 +3466,7 @@ void ALTIUM_PCB::HelperPcpShapeAsBoardKeepoutRegion( const PCB_SHAPE& aShape,
m_board->Add( zone, ADD_MODE::APPEND ); m_board->Add( zone, ADD_MODE::APPEND );
} }
void ALTIUM_PCB::HelperPcpShapeAsFootprintKeepoutRegion( FOOTPRINT* aFootprint, void ALTIUM_PCB::HelperPcpShapeAsFootprintKeepoutRegion( FOOTPRINT* aFootprint,
const PCB_SHAPE& aShape, const PCB_SHAPE& aShape,
ALTIUM_LAYER aAltiumLayer ) ALTIUM_LAYER aAltiumLayer )
@ -3394,3 +3491,58 @@ void ALTIUM_PCB::HelperPcpShapeAsFootprintKeepoutRegion( FOOTPRINT* aFootp
// TODO: zone->SetLocalCoord(); missing? // TODO: zone->SetLocalCoord(); missing?
aFootprint->Add( zone, ADD_MODE::APPEND ); aFootprint->Add( zone, ADD_MODE::APPEND );
} }
std::vector<std::pair<PCB_LAYER_ID, int>> ALTIUM_PCB::HelperGetSolderAndPasteMaskExpansions(
const ALTIUM_RECORD aType, const int aPrimitiveIndex, const ALTIUM_LAYER aAltiumLayer )
{
if( m_extendedPrimitiveInformationMaps.count( aType ) == 0 )
return {}; // there is nothing to parse
auto elems =
m_extendedPrimitiveInformationMaps[ALTIUM_RECORD::TRACK].equal_range( aPrimitiveIndex );
if( elems.first == elems.second )
return {}; // there is nothing to parse
std::vector<std::pair<PCB_LAYER_ID, int>> layerExpansionPairs;
for( auto it = elems.first; it != elems.second; ++it )
{
const AEXTENDED_PRIMITIVE_INFORMATION& pInf = it->second;
if( pInf.type == AEXTENDED_PRIMITIVE_INFORMATION_TYPE::MASK )
{
if( pInf.soldermaskexpansionmode == ALTIUM_MODE::MANUAL
|| pInf.soldermaskexpansionmode == ALTIUM_MODE::RULE )
{
// TODO: what layers can lead to solder or paste mask usage? E.g. KEEP_OUT_LAYER and other top/bottom layers
if( aAltiumLayer == ALTIUM_LAYER::TOP_LAYER
|| aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
{
layerExpansionPairs.emplace_back( F_Mask, pInf.soldermaskexpansionmanual );
}
if( aAltiumLayer == ALTIUM_LAYER::BOTTOM_LAYER
|| aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
{
layerExpansionPairs.emplace_back( B_Mask, pInf.soldermaskexpansionmanual );
}
}
if( pInf.pastemaskexpansionmode == ALTIUM_MODE::MANUAL
|| pInf.pastemaskexpansionmode == ALTIUM_MODE::RULE )
{
if( aAltiumLayer == ALTIUM_LAYER::TOP_LAYER
|| aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
{
layerExpansionPairs.emplace_back( F_Paste, pInf.pastemaskexpansionmanual );
}
if( aAltiumLayer == ALTIUM_LAYER::BOTTOM_LAYER
|| aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
{
layerExpansionPairs.emplace_back( B_Paste, pInf.pastemaskexpansionmanual );
}
}
}
}
return layerExpansionPairs;
}

View File

@ -149,9 +149,9 @@ private:
void ParseArcs6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile, void ParseArcs6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile,
const CFB::COMPOUND_FILE_ENTRY* aEntry ); const CFB::COMPOUND_FILE_ENTRY* aEntry );
void ConvertArcs6ToPcbShape( const AARC6& aElem, PCB_SHAPE* aShape ); void ConvertArcs6ToPcbShape( const AARC6& aElem, PCB_SHAPE* aShape );
void ConvertArcs6ToBoardItem( const AARC6& aElem ); void ConvertArcs6ToBoardItem( const AARC6& aElem, const int aPrimitiveIndex );
void ConvertArcs6ToFootprintItem( FOOTPRINT* aFootprint, const AARC6& aElem, void ConvertArcs6ToFootprintItem( FOOTPRINT* aFootprint, const AARC6& aElem,
const bool aIsBoardImport ); const int aPrimitiveIndex, const bool aIsBoardImport );
void ConvertArcs6ToBoardItemOnLayer( const AARC6& aElem, PCB_LAYER_ID aLayer ); void ConvertArcs6ToBoardItemOnLayer( const AARC6& aElem, PCB_LAYER_ID aLayer );
void ConvertArcs6ToFootprintItemOnLayer( FOOTPRINT* aFootprint, const AARC6& aElem, void ConvertArcs6ToFootprintItemOnLayer( FOOTPRINT* aFootprint, const AARC6& aElem,
PCB_LAYER_ID aLayer ); PCB_LAYER_ID aLayer );
@ -168,9 +168,9 @@ private:
const CFB::COMPOUND_FILE_ENTRY* aEntry ); const CFB::COMPOUND_FILE_ENTRY* aEntry );
void ParseTracks6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile, void ParseTracks6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile,
const CFB::COMPOUND_FILE_ENTRY* aEntry ); const CFB::COMPOUND_FILE_ENTRY* aEntry );
void ConvertTracks6ToBoardItem( const ATRACK6& aElem ); void ConvertTracks6ToBoardItem( const ATRACK6& aElem, const int aPrimitiveIndex );
void ConvertTracks6ToFootprintItem( FOOTPRINT* aFootprint, const ATRACK6& aElem, void ConvertTracks6ToFootprintItem( FOOTPRINT* aFootprint, const ATRACK6& aElem,
const bool aIsBoardImport ); const int aPrimitiveIndex, const bool aIsBoardImport );
void ConvertTracks6ToBoardItemOnLayer( const ATRACK6& aElem, PCB_LAYER_ID aLayer ); void ConvertTracks6ToBoardItemOnLayer( const ATRACK6& aElem, PCB_LAYER_ID aLayer );
void ConvertTracks6ToFootprintItemOnLayer( FOOTPRINT* aFootprint, const ATRACK6& aElem, void ConvertTracks6ToFootprintItemOnLayer( FOOTPRINT* aFootprint, const ATRACK6& aElem,
PCB_LAYER_ID aLayer ); PCB_LAYER_ID aLayer );
@ -201,6 +201,8 @@ private:
void ConvertShapeBasedRegions6ToFootprintItemOnLayer( FOOTPRINT* aFootprint, void ConvertShapeBasedRegions6ToFootprintItemOnLayer( FOOTPRINT* aFootprint,
const AREGION6& aElem, const AREGION6& aElem,
PCB_LAYER_ID aLayer ); PCB_LAYER_ID aLayer );
void ParseExtendedPrimitiveInformationData( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile,
const CFB::COMPOUND_FILE_ENTRY* aEntry );
void ParseRegions6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile, void ParseRegions6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile,
const CFB::COMPOUND_FILE_ENTRY* aEntry ); const CFB::COMPOUND_FILE_ENTRY* aEntry );
void ParseWideStrings6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile, void ParseWideStrings6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFile,
@ -222,6 +224,10 @@ private:
void HelperPcpShapeAsFootprintKeepoutRegion( FOOTPRINT* aFootprint, const PCB_SHAPE& aShape, void HelperPcpShapeAsFootprintKeepoutRegion( FOOTPRINT* aFootprint, const PCB_SHAPE& aShape,
ALTIUM_LAYER aAltiumLayer ); ALTIUM_LAYER aAltiumLayer );
std::vector<std::pair<PCB_LAYER_ID, int>>
HelperGetSolderAndPasteMaskExpansions( const ALTIUM_RECORD aType, const int aPrimitiveIndex,
const ALTIUM_LAYER aAltiumLayer );
FOOTPRINT* HelperGetFootprint( uint16_t aComponent ) const; FOOTPRINT* HelperGetFootprint( uint16_t aComponent ) const;
PCB_SHAPE* HelperCreateAndAddShape( uint16_t aComponent ); PCB_SHAPE* HelperCreateAndAddShape( uint16_t aComponent );
void HelperShapeSetLocalCoord( PCB_SHAPE* aShape, uint16_t aComponent ); void HelperShapeSetLocalCoord( PCB_SHAPE* aShape, uint16_t aComponent );
@ -236,6 +242,8 @@ private:
size_t m_num_nets; size_t m_num_nets;
std::map<ALTIUM_LAYER, PCB_LAYER_ID> m_layermap; // used to correctly map copper layers std::map<ALTIUM_LAYER, PCB_LAYER_ID> m_layermap; // used to correctly map copper layers
std::map<ALTIUM_RULE_KIND, std::vector<ARULE6>> m_rules; std::map<ALTIUM_RULE_KIND, std::vector<ARULE6>> m_rules;
std::map<ALTIUM_RECORD, std::multimap<int, const AEXTENDED_PRIMITIVE_INFORMATION>>
m_extendedPrimitiveInformationMaps;
std::map<ALTIUM_LAYER, ZONE*> m_outer_plane; std::map<ALTIUM_LAYER, ZONE*> m_outer_plane;

View File

@ -32,4 +32,6 @@
(stroke (width 0.5) (type solid)) (layer "F.Cu") (tstamp e16db058-fa43-40bf-9cff-c2ed4fab6ab5)) (stroke (width 0.5) (type solid)) (layer "F.Cu") (tstamp e16db058-fa43-40bf-9cff-c2ed4fab6ab5))
(fp_line (start 13 5) (end 13 -5) (fp_line (start 13 5) (end 13 -5)
(stroke (width 0.5) (type solid)) (layer "F.Cu") (tstamp 3de27c1c-897a-4a6c-b0f7-6b3c6fd91fd1)) (stroke (width 0.5) (type solid)) (layer "F.Cu") (tstamp 3de27c1c-897a-4a6c-b0f7-6b3c6fd91fd1))
(fp_line (start 13 5) (end 13 -5)
(stroke (width 0.3) (type solid)) (layer "F.Mask") (tstamp 3466cda7-8b6d-422c-92e4-d22bbe2d4a4d))
) )

View File

@ -202,4 +202,12 @@
(stroke (width 0.5) (type solid)) (layer "B.Cu") (tstamp 775b50f1-c021-45e5-b4f4-3da4bfa305be)) (stroke (width 0.5) (type solid)) (layer "B.Cu") (tstamp 775b50f1-c021-45e5-b4f4-3da4bfa305be))
(fp_line (start -10 2) (end 10 2) (fp_line (start -10 2) (end 10 2)
(stroke (width 0.5) (type solid)) (layer "B.Cu") (tstamp ee19307b-ab88-4d6f-9dfb-4149660b5a08)) (stroke (width 0.5) (type solid)) (layer "B.Cu") (tstamp ee19307b-ab88-4d6f-9dfb-4149660b5a08))
(fp_line (start -10 -2) (end 10 -2)
(stroke (width 1.5) (type solid)) (layer "B.Mask") (tstamp 786b6072-5772-4bc1-8eeb-6c4e19f2a91b))
(fp_line (start -10 0) (end 10 0)
(stroke (width 0.3) (type solid)) (layer "B.Mask") (tstamp 632acde9-b7fd-4f04-8cb4-d2cbb06b3595))
(fp_line (start -10 -2) (end 10 -2)
(stroke (width 1.5) (type solid)) (layer "F.Mask") (tstamp 4d609e7c-74c9-4ae9-a26d-946ff00c167d))
(fp_line (start -10 0) (end 10 0)
(stroke (width 0.3) (type solid)) (layer "F.Mask") (tstamp 0f41a909-27c4-4be2-9d5e-9ae2108c8ff5))
) )