Convert Altium radial dimensions to leaders.

This is because we don't yet support radial dimensions.

Also fixes a bug where we fail to read an Altium circular track.  We
now convert it to a pair of 180-degree arcs.

Also fixes a bug where we were failing to import prefixes on linear
dimensions.

Fixes https://gitlab.com/kicad/code/kicad/issues/8789
This commit is contained in:
Jeff Young 2021-07-24 14:23:55 +01:00
parent 531f5480a7
commit 373f0335c8
6 changed files with 238 additions and 66 deletions

View File

@ -156,6 +156,10 @@ std::map<wxString, wxString> ALTIUM_PARSER::ReadProperties()
else
value = wxString( valueS.c_str(), wxConvISO8859_1 );
// Breathless hack because I haven't a clue what the story is here (but this character
// appears in a lot of radial dimensions and is rendered by Altium as a space).
value.Replace( wxT( "ÿ" ), wxT( " " ) );
if( canonicalKey == wxT( "DESIGNATOR" )
|| canonicalKey == wxT( "NAME" )
|| canonicalKey == wxT( "TEXT" ) )

View File

@ -135,6 +135,9 @@ public:
int GetMeasuredValue() const { return m_measuredValue; }
// KiCad normally calculates the measured value but some importers need to set it.
void SetMeasuredValue( int aValue ) { m_measuredValue = aValue; }
/**
* @return the dimension value, rendered with precision / zero suppression but no units, etc
*/

View File

@ -278,6 +278,8 @@ ADIMENSION6::ADIMENSION6( ALTIUM_PARSER& aReader )
kind = static_cast<ALTIUM_DIMENSION_KIND>( ALTIUM_PARSER::ReadInt( props, "DIMENSIONKIND", 0 ) );
textformat = ALTIUM_PARSER::ReadString( props, "TEXTFORMAT", "" );
textprefix = ALTIUM_PARSER::ReadString( props, "TEXTPREFIX", "" );
textsuffix = ALTIUM_PARSER::ReadString( props, "TEXTSUFFIX", "" );
height = ALTIUM_PARSER::ReadKicadUnit( props, "HEIGHT", "0mil" );
angle = ALTIUM_PARSER::ReadDouble( props, "ANGLE", 0. );
@ -288,9 +290,12 @@ ADIMENSION6::ADIMENSION6( ALTIUM_PARSER& aReader )
textprecision = ALTIUM_PARSER::ReadInt( props, "TEXTPRECISION", 2 );
textbold = ALTIUM_PARSER::ReadBool( props, "TEXTLINEWIDTH", false );
textitalic = ALTIUM_PARSER::ReadBool( props, "ITALIC", false );
textgap = ALTIUM_PARSER::ReadKicadUnit( props, "TEXTGAP", "10mil" );
arrowsize = ALTIUM_PARSER::ReadKicadUnit( props, "ARROWSIZE", "60mil" );
wxString text_position_raw = ALTIUM_PARSER::ReadString( props, "TEXTPOSITION", "" );
xy1 = wxPoint( ALTIUM_PARSER::ReadKicadUnit( props, "X1", "0mil" ),
-ALTIUM_PARSER::ReadKicadUnit( props, "Y1", "0mil" ) );

View File

@ -393,6 +393,8 @@ struct ADIMENSION6
ALTIUM_DIMENSION_KIND kind;
wxString textformat;
wxString textprefix;
wxString textsuffix;
int32_t height;
double angle;
@ -401,6 +403,7 @@ struct ADIMENSION6
uint32_t textheight;
uint32_t textlinewidth;
int32_t textprecision;
uint32_t textgap;
bool textbold;
bool textitalic;

View File

@ -165,8 +165,8 @@ void ALTIUM_PCB::HelperDrawsegmentSetLocalCoord( PCB_SHAPE* aShape, uint16_t aCo
}
void HelperShapeLineChainFromAltiumVertices(
SHAPE_LINE_CHAIN& aLine, const std::vector<ALTIUM_VERTICE>& aVertices )
void HelperShapeLineChainFromAltiumVertices( SHAPE_LINE_CHAIN& aLine,
const std::vector<ALTIUM_VERTICE>& aVertices )
{
for( auto& vertice : aVertices )
{
@ -350,80 +350,99 @@ void ALTIUM_PCB::Parse( const CFB::CompoundFileReader& aReader,
// this vector simply declares in which order which functions to call.
const std::vector<std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>> parserOrder = {
{ true, ALTIUM_PCB_DIR::FILE_HEADER,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseFileHeader( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::BOARD6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseBoard6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::COMPONENTS6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseComponents6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::MODELS,
[this, aFileMapping]( auto aReader, auto fileHeader ) {
[this, aFileMapping]( auto aReader, auto fileHeader )
{
wxString dir( aFileMapping.at( ALTIUM_PCB_DIR::MODELS ) );
this->ParseModelsData( aReader, fileHeader, dir );
} },
{ true, ALTIUM_PCB_DIR::COMPONENTBODIES6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseComponentsBodies6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::NETS6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseNets6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::CLASSES6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseClasses6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::RULES6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseRules6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::DIMENSIONS6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseDimensions6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::POLYGONS6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParsePolygons6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::ARCS6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseArcs6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::PADS6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParsePads6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::VIAS6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseVias6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::TRACKS6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseTracks6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::TEXTS6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseTexts6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::FILLS6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseFills6Data( aReader, fileHeader );
} },
{ false, ALTIUM_PCB_DIR::BOARDREGIONS,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseBoardRegionsData( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::SHAPEBASEDREGIONS6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseShapeBasedRegions6Data( aReader, fileHeader );
} },
{ true, ALTIUM_PCB_DIR::REGIONS6,
[this]( auto aReader, auto fileHeader ) {
[this]( auto aReader, auto fileHeader )
{
this->ParseRegions6Data( aReader, fileHeader );
} }
};
@ -485,6 +504,7 @@ void ALTIUM_PCB::Parse( const CFB::CompoundFileReader& aReader,
std::tie( isRequired, directory, fp ) = cur;
const auto& mappedDirectory = aFileMapping.find( directory );
if( mappedDirectory == aFileMapping.end() )
{
wxASSERT_MSG( !isRequired, wxString::Format( "Altium Directory of kind %d was expected, "
@ -494,24 +514,20 @@ void ALTIUM_PCB::Parse( const CFB::CompoundFileReader& aReader,
}
std::string mappedFile = mappedDirectory->second;
if( directory != ALTIUM_PCB_DIR::FILE_HEADER )
{
mappedFile += "Data";
}
const CFB::COMPOUND_FILE_ENTRY* file = FindStream( aReader, mappedFile.c_str() );
if( file != nullptr )
{
fp( aReader, file );
}
else if( isRequired )
{
wxLogError( _( "File not found: '%s'." ), mappedFile );
}
}
// fixup zone priorities since Altium stores them in the opposite order
for( auto& zone : m_polygons )
for( ZONE* zone : m_polygons )
{
if( !zone )
continue;
@ -532,9 +548,62 @@ void ALTIUM_PCB::Parse( const CFB::CompoundFileReader& aReader,
}
// change priority of outer zone to zero
for( auto& zone : m_outer_plane )
{
for( std::pair<const ALTIUM_LAYER, ZONE*>& zone : m_outer_plane )
zone.second->SetPriority( 0 );
// Altium doesn't appear to store either the dimension value nor the dimensioned object in
// 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 )
{
int radius = 0;
for( BOARD_ITEM* item : m_board->Drawings() )
{
if( item->Type() != PCB_SHAPE_T )
continue;
PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item );
if( shape->GetShape() != SHAPE_T::ARC && shape->GetShape() != SHAPE_T::CIRCLE )
continue;
if( shape->GetPosition() == dim->GetPosition() )
{
radius = shape->GetRadius();
break;
}
}
if( radius == 0 )
{
for( PCB_TRACK* track : m_board->Tracks() )
{
if( track->Type() != PCB_ARC_T )
continue;
PCB_ARC* arc = static_cast<PCB_ARC*>( track );
if( arc->GetCenter() == dim->GetPosition() )
{
radius = arc->GetRadius();
break;
}
}
}
// 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
VECTOR2I radialLine = dim->GetEnd() - dim->GetStart();
radialLine = radialLine.Resize( radius );
dim->SetStart( dim->GetStart() + (wxPoint) radialLine );
}
// center board
@ -934,9 +1003,7 @@ void ALTIUM_PCB::ParseComponentsBodies6Data( const CFB::CompoundFileReader& aRea
ACOMPONENTBODY6 elem( reader ); // TODO: implement
if( elem.component == ALTIUM_COMPONENT_NONE )
{
continue; // TODO: we do not support components for the board yet
}
if( m_components.size() <= elem.component )
{
@ -946,11 +1013,10 @@ void ALTIUM_PCB::ParseComponentsBodies6Data( const CFB::CompoundFileReader& aRea
}
if( !elem.modelIsEmbedded )
{
continue;
}
auto modelTuple = m_models.find( elem.modelId );
if( modelTuple == m_models.end() )
{
THROW_IO_ERROR( wxString::Format(
@ -981,27 +1047,23 @@ void ALTIUM_PCB::ParseComponentsBodies6Data( const CFB::CompoundFileReader& aRea
modelSettings.m_Rotation.x = NormalizeAngleDegrees( -elem.modelRotation.x, -180, 180 );
modelSettings.m_Rotation.y = NormalizeAngleDegrees( -elem.modelRotation.y, -180, 180 );
modelSettings.m_Rotation.z = NormalizeAngleDegrees(
-elem.modelRotation.z + elem.rotation + orientation / 10, -180, 180 );
modelSettings.m_Rotation.z = NormalizeAngleDegrees( -elem.modelRotation.z
+ elem.rotation
+ orientation / 10, -180, 180 );
modelSettings.m_Opacity = elem.bodyOpacity;
footprint->Models().push_back( modelSettings );
}
if( reader.GetRemainingBytes() != 0 )
{
THROW_IO_ERROR( "ComponentsBodies6 stream is not fully parsed" );
}
}
void ALTIUM_PCB::HelperParseDimensions6Linear( const ADIMENSION6& aElem )
{
if( aElem.referencePoint.size() != 2 )
{
THROW_IO_ERROR( "Incorrect number of reference points for linear dimension object" );
}
PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
@ -1027,12 +1089,12 @@ void ALTIUM_PCB::HelperParseDimensions6Linear( const ADIMENSION6& aElem )
{
/**
* Basically REFERENCE0POINT and REFERENCE1POINT are the two end points of the dimension.
* XY1 is the position of the arrow above REFERENCE0POINT. those three points are not necessarily
* in 90degree angle, but KiCad requires this to show the correct measurements.
* XY1 is the position of the arrow above REFERENCE0POINT. those three points are not
* necessarily in 90degree angle, but KiCad requires this to show the correct measurements.
*
* Therefore, we take the vector of REFERENCE0POINT -> XY1, calculate the normal, and intersect it with
* REFERENCE1POINT pointing the same direction as REFERENCE0POINT -> XY1. This should give us a valid
* measurement point where we can place the drawsegment.
* Therefore, we take the vector of REFERENCE0POINT -> XY1, calculate the normal, and
* intersect it with REFERENCE1POINT pointing the same direction as REFERENCE0POINT -> XY1.
* This should give us a valid measurement point where we can place the drawsegment.
*/
wxPoint direction = aElem.xy1 - referencePoint0;
wxPoint directionNormalVector = wxPoint( -direction.y, direction.x );
@ -1044,9 +1106,7 @@ void ALTIUM_PCB::HelperParseDimensions6Linear( const ADIMENSION6& aElem )
int height = static_cast<int>( EuclideanNorm( direction ) );
if( direction.x <= 0 && direction.y <= 0 ) // TODO: I suspect this is not always correct
{
height = -height;
}
dimension->SetHeight( height );
}
@ -1057,6 +1117,12 @@ void ALTIUM_PCB::HelperParseDimensions6Linear( const ADIMENSION6& aElem )
dimension->SetLineThickness( aElem.linewidth );
dimension->SetPrefix( aElem.textprefix );
// Suffix normally holds the units
dimension->SetUnitsFormat( aElem.textsuffix.IsEmpty() ? DIM_UNITS_FORMAT::NO_SUFFIX
: DIM_UNITS_FORMAT::BARE_SUFFIX );
dimension->Text().SetTextThickness( aElem.textlinewidth );
dimension->Text().SetTextSize( wxSize( aElem.textheight, aElem.textheight ) );
dimension->Text().SetBold( aElem.textbold );
@ -1079,6 +1145,80 @@ void ALTIUM_PCB::HelperParseDimensions6Linear( const ADIMENSION6& aElem )
}
}
void ALTIUM_PCB::HelperParseDimensions6Radial(const ADIMENSION6 &aElem)
{
if( aElem.referencePoint.size() < 2 )
THROW_IO_ERROR( "Not enough reference points for radial dimension object" );
PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
if( klayer == UNDEFINED_LAYER )
{
wxLogWarning( _( "Dimension found on an Altium layer (%d) with no KiCad equivalent. "
"It has been moved to KiCad layer Eco1_User." ),
aElem.layer );
klayer = Eco1_User;
}
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 );
m_board->Add( dimension, ADD_MODE::APPEND );
m_radialDimensions.push_back( dimension );
dimension->SetPrecision( aElem.textprecision );
dimension->SetLayer( klayer );
dimension->SetStart( referencePoint0 );
dimension->SetEnd( aElem.xy1 );
dimension->SetLineThickness( aElem.linewidth );
dimension->SetPrefix( aElem.textprefix );
// Suffix normally holds the units
dimension->SetUnitsFormat( aElem.textsuffix.IsEmpty() ? DIM_UNITS_FORMAT::NO_SUFFIX
: DIM_UNITS_FORMAT::BARE_SUFFIX );
switch( aElem.textunit )
{
case ALTIUM_UNIT::INCHES:
dimension->SetUnits( EDA_UNITS::INCHES );
break;
case ALTIUM_UNIT::MILS:
dimension->SetUnits( EDA_UNITS::MILS );
break;
case ALTIUM_UNIT::MILLIMETERS:
case ALTIUM_UNIT::CENTIMETER:
dimension->SetUnits( EDA_UNITS::MILLIMETRES );
break;
default:
break;
}
if( aElem.textPoint.empty() )
{
wxLogError( "No text position present for leader dimension object" );
return;
}
dimension->Text().SetPosition( aElem.textPoint.at( 0 ) );
dimension->Text().SetTextThickness( aElem.textlinewidth );
dimension->Text().SetTextSize( wxSize( aElem.textheight, aElem.textheight ) );
dimension->Text().SetBold( aElem.textbold );
dimension->Text().SetItalic( aElem.textitalic );
dimension->Text().SetVertJustify( EDA_TEXT_VJUSTIFY_T::GR_TEXT_VJUSTIFY_BOTTOM );
dimension->Text().SetHorizJustify( EDA_TEXT_HJUSTIFY_T::GR_TEXT_HJUSTIFY_LEFT );
int yAdjust = dimension->Text().GetCenter().y - dimension->Text().GetPosition().y;
dimension->Text().Move( wxPoint( 0, yAdjust + aElem.textgap ) );
dimension->Text().SetVertJustify( EDA_TEXT_VJUSTIFY_T::GR_TEXT_VJUSTIFY_CENTER );
}
void ALTIUM_PCB::HelperParseDimensions6Leader( const ADIMENSION6& aElem )
{
PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
@ -1158,6 +1298,7 @@ void ALTIUM_PCB::HelperParseDimensions6Leader( const ADIMENSION6& aElem )
text->SetVertJustify( EDA_TEXT_VJUSTIFY_T::GR_TEXT_VJUSTIFY_BOTTOM );
}
void ALTIUM_PCB::HelperParseDimensions6Datum( const ADIMENSION6& aElem )
{
PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
@ -1182,6 +1323,7 @@ void ALTIUM_PCB::HelperParseDimensions6Datum( const ADIMENSION6& aElem )
}
}
void ALTIUM_PCB::HelperParseDimensions6Center( const ADIMENSION6& aElem )
{
PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
@ -1224,29 +1366,28 @@ void ALTIUM_PCB::ParseDimensions6Data( const CFB::CompoundFileReader& aReader,
case ALTIUM_DIMENSION_KIND::LINEAR:
HelperParseDimensions6Linear( elem );
break;
case ALTIUM_DIMENSION_KIND::RADIAL:
HelperParseDimensions6Radial( elem );
break;
case ALTIUM_DIMENSION_KIND::LEADER:
HelperParseDimensions6Leader( elem );
break;
case ALTIUM_DIMENSION_KIND::DATUM:
wxLogError( _( "Ignored dimension of kind %d (not yet supported)." ),
elem.kind );
wxLogError( _( "Ignored dimension of kind %d (not yet supported)." ), elem.kind );
// HelperParseDimensions6Datum( elem );
break;
case ALTIUM_DIMENSION_KIND::CENTER:
HelperParseDimensions6Center( elem );
break;
default:
wxLogError( _( "Ignored dimension of kind %d (not yet supported)." ),
elem.kind );
wxLogError( _( "Ignored dimension of kind %d (not yet supported)." ), elem.kind );
break;
}
}
if( reader.GetRemainingBytes() != 0 )
{
THROW_IO_ERROR( "Dimensions6 stream is not fully parsed" );
}
}
void ALTIUM_PCB::ParseModelsData( const CFB::CompoundFileReader& aReader,
@ -1332,10 +1473,8 @@ void ALTIUM_PCB::ParseModelsData( const CFB::CompoundFileReader& aReader,
}
if( reader.GetRemainingBytes() != 0 )
{
THROW_IO_ERROR( "Models stream is not fully parsed" );
}
}
void ALTIUM_PCB::ParseNets6Data( const CFB::CompoundFileReader& aReader,
@ -1356,10 +1495,8 @@ void ALTIUM_PCB::ParseNets6Data( const CFB::CompoundFileReader& aReader,
}
if( reader.GetRemainingBytes() != 0 )
{
THROW_IO_ERROR( "Nets6 stream is not fully parsed" );
}
}
void ALTIUM_PCB::ParsePolygons6Data( const CFB::CompoundFileReader& aReader,
const CFB::COMPOUND_FILE_ENTRY* aEntry )
@ -1458,10 +1595,9 @@ void ALTIUM_PCB::ParsePolygons6Data( const CFB::CompoundFileReader& aReader,
zone->SetPriority( 1 );
// check if this is the outer zone by simply comparing the BBOX
const auto& cur_outer_plane = m_outer_plane.find( elem.layer );
if( cur_outer_plane == m_outer_plane.end()
|| zone->GetBoundingBox().Contains(
cur_outer_plane->second->GetBoundingBox() ) )
const auto& outer_plane = m_outer_plane.find( elem.layer );
if( outer_plane == m_outer_plane.end()
|| zone->GetBoundingBox().Contains( outer_plane->second->GetBoundingBox() ) )
{
m_outer_plane[elem.layer] = zone;
}
@ -1861,13 +1997,31 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader,
wxPoint arcStartOffset = wxPoint( KiROUND( std::cos( startradiant ) * elem.radius ),
-KiROUND( std::sin( startradiant ) * elem.radius ) );
SHAPE_ARC shapeArc( elem.center, elem.center + arcStartOffset, angle, elem.width );
arcStartOffset += elem.center;
// If it's a circle then add two 180-degree arcs
if( elem.startangle == 0. && elem.endangle == 360. )
angle = 180.;
SHAPE_ARC shapeArc( elem.center, arcStartOffset, angle, elem.width );
PCB_ARC* arc = new PCB_ARC( m_board, &shapeArc );
m_board->Add( arc, ADD_MODE::APPEND );
arc->SetWidth( elem.width );
arc->SetLayer( klayer );
arc->SetNetCode( GetNetCode( elem.net ) );
// Add second 180-degree arc for a circle
if( elem.startangle == 0. && elem.endangle == 360. )
{
shapeArc = SHAPE_ARC( elem.center, arcStartOffset, -angle, elem.width );
arc = new PCB_ARC( m_board, &shapeArc );
m_board->Add( arc, ADD_MODE::APPEND );
arc->SetWidth( elem.width );
arc->SetLayer( klayer );
arc->SetNetCode( GetNetCode( elem.net ) );
}
}
else
{

View File

@ -85,6 +85,7 @@ class BOARD;
class PCB_SHAPE;
class FOOTPRINT;
class ZONE;
class PCB_DIMENSION_BASE;
class PROGRESS_REPORTER;
@ -175,6 +176,7 @@ private:
// Helper Functions
void HelperParseDimensions6Linear( const ADIMENSION6& aElem );
void HelperParseDimensions6Radial( const ADIMENSION6& aElem );
void HelperParseDimensions6Leader( const ADIMENSION6& aElem );
void HelperParseDimensions6Datum( const ADIMENSION6& aElem );
void HelperParseDimensions6Center( const ADIMENSION6& aElem );
@ -189,6 +191,7 @@ private:
BOARD* m_board;
std::vector<FOOTPRINT*> m_components;
std::vector<ZONE*> m_polygons;
std::vector<PCB_DIMENSION_BASE*> m_radialDimensions;
std::map<wxString, wxString> m_models;
size_t m_num_nets;
std::map<ALTIUM_LAYER, PCB_LAYER_ID> m_layermap; // used to correctly map copper layers