CADSTAR PCB Archive Importer: Parse HEADER and ASSIGNMENTS->CODEDEFS sections

This commit is contained in:
Roberto Fernandez Bautista 2020-07-18 10:04:22 +01:00 committed by Seth Hillbrand
parent 86bf592bac
commit 4fcba4d619
6 changed files with 1367 additions and 135 deletions

View File

@ -25,6 +25,40 @@
#include <cadstar_common.h>
void CADSTAR_COMMON::EVALUE::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "E" ) );
if( ( !CADSTAR_COMMON::GetAttributeID( aNode, 0 ).ToLong( &Base ) )
|| ( !CADSTAR_COMMON::GetAttributeID( aNode, 1 ).ToLong( &Exponent ) ) )
THROW_PARSING_IO_ERROR( wxT( "Base and Exponent" ),
wxString::Format(
"%s->%s", aNode->GetParent()->GetName(), aNode->GetParent()->GetName() ) );
}
double CADSTAR_COMMON::EVALUE::GetDouble()
{
return Base * std::pow( 10.0, Exponent );
}
void CADSTAR_COMMON::InsertAttributeAtEnd( XNODE* aNode, wxString aValue )
{
wxString result, paramName = "attr0";
int i = 0;
while( aNode->GetAttribute( paramName, &result ) )
{
paramName = wxT( "attr" );
paramName << i++;
}
aNode->AddAttribute( paramName, aValue );
}
XNODE* CADSTAR_COMMON::LoadArchiveFile( const wxString& aFileName, FILE_TYPE aType )
{
KEYWORD emptyKeywords[1] = {};
@ -80,6 +114,8 @@ XNODE* CADSTAR_COMMON::LoadArchiveFile( const wxString& aFileName, FILE_TYPE aTy
if( iNode )
{
//we will add it as attribute as well as child node
InsertAttributeAtEnd( iNode, str );
iNode->AddChild( cNode );
}
else if( !cadstarFileCheckDone )
@ -99,16 +135,7 @@ XNODE* CADSTAR_COMMON::LoadArchiveFile( const wxString& aFileName, FILE_TYPE aTy
if( !str.IsEmpty() )
{
wxString result, paramName = "attr0";
int i = 0;
while( iNode->GetAttribute( paramName, &result ) )
{
paramName = wxT( "attr" );
paramName << i++;
}
iNode->AddAttribute( paramName, str );
InsertAttributeAtEnd( iNode, str );
}
}
else
@ -130,6 +157,7 @@ XNODE* CADSTAR_COMMON::LoadArchiveFile( const wxString& aFileName, FILE_TYPE aTy
}
else
{
//no data?
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
}
@ -138,15 +166,54 @@ XNODE* CADSTAR_COMMON::LoadArchiveFile( const wxString& aFileName, FILE_TYPE aTy
wxString CADSTAR_COMMON::GetAttributeID( XNODE* aNode, unsigned int aID )
{
wxString attrName = "attr";
wxString attrName, retVal;
attrName = "attr";
attrName << aID;
return aNode->GetAttribute( attrName, wxEmptyString );
if( !aNode->GetAttribute( attrName, &retVal ) )
THROW_MISSING_PARAMETER_IO_ERROR( std::to_string( aID ), aNode->GetName() );
return retVal;
}
void CADSTAR_COMMON::CheckNoChildNodes( XNODE* aNode, wxString aLocation )
long CADSTAR_COMMON::GetAttributeIDLong( XNODE* aNode, unsigned int aID )
{
long retVal;
if( !CADSTAR_COMMON::GetAttributeID( aNode, aID ).ToLong( &retVal ) )
THROW_PARSING_IO_ERROR( std::to_string( aID ), aNode->GetName() );
return retVal;
}
void CADSTAR_COMMON::CheckNoChildNodes( XNODE* aNode )
{
if( aNode->GetChildren() )
{
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aLocation );
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
}
}
void CADSTAR_COMMON::CheckNoNextNodes( XNODE* aNode )
{
if( aNode->GetNext() )
{
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetNext()->GetName(), aNode->GetParent()->GetName() );
}
}
void CADSTAR_COMMON::ParseChildEValue( XNODE* aNode, CADSTAR_COMMON::EVALUE& aValueToParse )
{
if( aNode->GetChildren()->GetName() == wxT( "E" ) )
{
aValueToParse.Parse( aNode->GetChildren() );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
}
}

View File

@ -60,6 +60,20 @@ enum class FILE_TYPE
};
/**
* @brief Represents a floating value in E notation
*/
struct EVALUE
{
long Base = 0;
long Exponent = 0;
void Parse( XNODE* aNode );
double GetDouble();
};
extern void InsertAttributeAtEnd( XNODE* aNode, wxString aValue );
/**
* @brief Reads a CADSTAR Archive file (S-parameter format)
* @param aFileName
@ -72,20 +86,51 @@ enum class FILE_TYPE
extern XNODE* LoadArchiveFile(
const wxString& aFileName, FILE_TYPE aType = FILE_TYPE::PCB_ARCHIVE );
/**
* @brief
* @param aNode
* @param aID
* @return returns the value of attribute "attrX" in aNode where 'X' is aID
* @throws IO_ERROR if attribute does not exist
*/
extern wxString GetAttributeID( XNODE* aNode, unsigned int aID );
/**
* @brief
* @param aNode
* @param aID
* @return returns the value of attribute "attrX" in aNode where 'X' is aID
* @throws IO_ERROR if attribute does not exist
*/
extern long GetAttributeIDLong( XNODE* aNode, unsigned int aID );
/**
* @brief
* @param aNode
* @throw IO_ERROR if a child node was found
*/
extern void CheckNoChildNodes( XNODE* aNode, wxString aLocation );
extern void CheckNoChildNodes( XNODE* aNode );
/**
* @brief
* @param aNode
* @throw IO_ERROR if a node adjacent to aNode was found
*/
extern void CheckNoNextNodes( XNODE* aNode );
/**
* @brief
* @param aNode with a child node containing an EVALUE
* @param aValueToParse
* @throw IO_ERROR if unable to parse or node is not an EVALUE
*/
extern void ParseChildEValue( XNODE* aNode, EVALUE& aValueToParse );
} // namespace CADSTAR_COMMON

View File

@ -37,10 +37,9 @@ void CADSTAR_PCB::Load( CPA_FILE* aCPAfile )
void CADSTAR_PCB::loadBoardStackup( CPA_FILE* aCPAfile )
{
std::map<CPA_LAYER_ID, CPA_LAYER>& cpaLayers = aCPAfile->Assignments.Layerdefs.Layers;
std::map<CPA_MATERIAL_ID, CPA_MATERIAL>& cpaMaterials =
aCPAfile->Assignments.Layerdefs.Materials;
std::vector<CPA_LAYER_ID>& cpaLayerStack = aCPAfile->Assignments.Layerdefs.LayerStack;
std::map<CPA_ID, CPA_LAYER>& cpaLayers = aCPAfile->Assignments.Layerdefs.Layers;
std::map<CPA_ID, CPA_MATERIAL>& cpaMaterials = aCPAfile->Assignments.Layerdefs.Materials;
std::vector<CPA_ID>& cpaLayerStack = aCPAfile->Assignments.Layerdefs.LayerStack;
unsigned numElectricalAndPowerLayers = 0;
BOARD_DESIGN_SETTINGS& designSettings = mBoard->GetDesignSettings();
BOARD_STACKUP& stackup = designSettings.GetStackupDescriptor();
@ -207,9 +206,7 @@ void CADSTAR_PCB::loadBoardStackup( CPA_FILE* aCPAfile )
//TODO add Resistivity when KiCad supports it
}
int unitMultiplier = 10; //assume CPA_FILE uses HUNDREDTH MICRON as its unit
//TODO: read units from CPA_FILE header and change unitMultiplier
// Also, add unitMultiplier somewhere in CPA_FILE
int unitMultiplier = aCPAfile->KiCadUnitMultiplier;
tempKiCadLayer->SetThickness( curLayer.Thickness * unitMultiplier, dielectricSublayer );
wxASSERT( layerTypeName != wxEmptyString );
@ -234,6 +231,7 @@ void CADSTAR_PCB::loadBoardStackup( CPA_FILE* aCPAfile )
tempKiCadLayer->GetBrdLayerId(), tempKiCadLayer->GetLayerName() ) );
//TODO set layer names for other CADSTAR layers when KiCad supports custom
//layer names on non-copper layers
mCopperLayers.insert( std::make_pair( curLayer.PhysicalLayer, curLayer.ID ) );
}
//TODO map kicad layer to CADSTAR layer in mLayermap
}

View File

@ -45,7 +45,8 @@ public:
private:
BOARD* mBoard;
std::map<CPA_LAYER_ID, PCB_LAYER_ID> mLayermap;
std::map<CPA_ID, PCB_LAYER_ID> mLayermap; //<Map between Cadstar and KiCad Layers
std::map<CPA_PHYSICAL_LAYER, CPA_ID> mCopperLayers;
void loadBoardStackup( CPA_FILE* aCPAfile );
PCB_LAYER_ID getKiCadCopperLayerID( unsigned int aLayerNum );
};

View File

@ -34,6 +34,26 @@ void CPA_FILE::Parse()
XNODE* tempNode = fileRootNode->GetChildren();
for( ; tempNode && ( tempNode->GetName() != wxT( "HEADER" ) ); tempNode = tempNode->GetNext() )
;
if( !tempNode )
THROW_MISSING_NODE_IO_ERROR( wxT( "HEADER" ), wxT( "CADSTARPCB" ) );
//TODO try.. catch + throw again with more detailed error information
Header.Parse( tempNode );
switch( Header.Resolution )
{
case CPA_RESOLUTION::HUNDREDTH_MICRON:
KiCadUnitMultiplier = 10;
break;
default:
wxASSERT_MSG( true, wxT( "Unknown File Resolution" ) );
break;
}
for( ; tempNode && ( tempNode->GetName() != wxT( "ASSIGNMENTS" ) );
tempNode = tempNode->GetNext() )
;
@ -43,14 +63,19 @@ void CPA_FILE::Parse()
tempNode = tempNode->GetChildren();
for( ; tempNode && ( tempNode->GetName() != wxT( "LAYERDEFS" ) );
tempNode = tempNode->GetNext() )
;
if( !tempNode )
THROW_MISSING_NODE_IO_ERROR( wxT( "LAYERDEFS" ), wxT( "ASSIGNMENTS" ) );
for( ; tempNode; tempNode = tempNode->GetNext() )
{
if( tempNode->GetName() == wxT( "LAYERDEFS" ) )
//TODO try.. catch + throw again with more detailed error information
Assignments.Layerdefs.Parse( tempNode );
else if( tempNode->GetName() == wxT( "CODEDEFS" ) )
Assignments.Codedefs.Parse( tempNode );
//TODO parse technology, grids,etc
}
//Todo - This is just for testing. Remove this block & delete fileRootNode.
{
@ -64,57 +89,51 @@ void CPA_FILE::Parse()
//TODO need to parse everything else!
}
void CPA_LAYERDEFS::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "LAYERDEFS" ) );
XNODE * iNode, *cNode;
wxXmlAttribute* xmlAttribute = NULL;
iNode = aNode->GetChildren();
XNODE* cNode = aNode->GetChildren();
if( !iNode )
if( !cNode )
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "LAYERSTACK" ), wxT( "LAYERDEFS" ) );
for( ; iNode; iNode = iNode->GetNext() )
for( ; cNode; cNode = cNode->GetNext() )
{
wxString nodeName = iNode->GetName();
wxString nodeName = cNode->GetName();
if( nodeName == wxT( "LAYERSTACK" ) )
{
xmlAttribute = iNode->GetAttributes();
xmlAttribute = cNode->GetAttributes();
for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
{
LayerStack.push_back( xmlAttribute->GetValue() );
}
if( cNode = iNode->GetChildren() ) //Shouldn't have any children
{
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), nodeName );
}
CADSTAR_COMMON::CheckNoChildNodes( cNode );
}
else if( nodeName == wxT( "MATERIAL" ) )
{
CPA_MATERIAL material;
material.Parse( iNode );
//TODO try.. catch + throw again with more detailed error information
material.Parse( cNode );
Materials.insert( std::make_pair( material.ID, material ) );
}
else if( nodeName == wxT( "LAYER" ) )
{
CPA_LAYER layer;
layer.Parse( iNode );
//TODO try.. catch + throw again with more detailed error information
layer.Parse( cNode );
Layers.insert( std::make_pair( layer.ID, layer ) );
}
else if( nodeName == wxT( "SWAPPAIR" ) )
{
wxString layerId = CADSTAR_COMMON::GetAttributeID( iNode, 0 );
wxString swapLayerId = CADSTAR_COMMON::GetAttributeID( iNode, 1 );
if( layerId.IsEmpty() || swapLayerId.IsEmpty() )
{
THROW_MISSING_PARAMETER_IO_ERROR(
wxT( "ID" ), wxString::Format( "SWAPPAIR %s,%s", layerId, swapLayerId ) );
}
wxString layerId = CADSTAR_COMMON::GetAttributeID( cNode, 0 );
wxString swapLayerId = CADSTAR_COMMON::GetAttributeID( cNode, 1 );
Layers[layerId].SwapLayerID = swapLayerId;
}
@ -126,39 +145,122 @@ void CPA_LAYERDEFS::Parse( XNODE* aNode )
}
void CPAParseEValue( XNODE* aNode, CPA_EVALUE& aValue, wxString location )
void CPA_CODEDEFS::Parse( XNODE* aNode )
{
if( aNode->GetChildren()->GetName() == wxT( "E" ) )
wxASSERT( aNode->GetName() != wxT( "CODEDEFS" ) );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
aValue.Parse( aNode->GetChildren() );
wxString nodeName = cNode->GetName();
if( nodeName == wxT( "LINECODE" ) )
{
CPA_LINECODE linecode;
//TODO try.. catch + throw again with more detailed error information
linecode.Parse( cNode );
LineCodes.insert( std::make_pair( linecode.ID, linecode ) );
}
else if( nodeName == wxT( "HATCHCODE" ) )
{
CPA_HATCHCODE hatchcode;
//TODO try.. catch + throw again with more detailed error information
hatchcode.Parse( cNode );
HatchCodes.insert( std::make_pair( hatchcode.ID, hatchcode ) );
}
else if( nodeName == wxT( "TEXTCODE" ) )
{
CPA_TEXTCODE textcode;
//TODO try.. catch + throw again with more detailed error information
textcode.Parse( cNode );
TextCodes.insert( std::make_pair( textcode.ID, textcode ) );
}
else if( nodeName == wxT( "ROUTECODE" ) )
{
CPA_ROUTECODE routecode;
//TODO try.. catch + throw again with more detailed error information
routecode.Parse( cNode );
RouteCodes.insert( std::make_pair( routecode.ID, routecode ) );
}
else if( nodeName == wxT( "COPPERCODE" ) )
{
CPA_COPPERCODE coppercode;
//TODO try.. catch + throw again with more detailed error information
coppercode.Parse( cNode );
CopperCodes.insert( std::make_pair( coppercode.ID, coppercode ) );
}
else if( nodeName == wxT( "SPACINGCODE" ) )
{
CPA_SPACINGCODE spacingcode;
//TODO try.. catch + throw again with more detailed error information
spacingcode.Parse( cNode );
SpacingCodes.push_back( spacingcode );
}
else if( nodeName == wxT( "PADCODE" ) )
{
CPA_PADCODE padcode;
//TODO try.. catch + throw again with more detailed error information
padcode.Parse( cNode );
PadCodes.insert( std::make_pair( padcode.ID, padcode ) );
}
else if( nodeName == wxT( "VIACODE" ) )
{
CPA_VIACODE viacode;
//TODO try.. catch + throw again with more detailed error information
viacode.Parse( cNode );
ViaCodes.insert( std::make_pair( viacode.ID, viacode ) );
}
else if( nodeName == wxT( "LAYERPAIR" ) )
{
CPA_LAYERPAIR layerpair;
//TODO try.. catch + throw again with more detailed error information
layerpair.Parse( cNode );
LayerPairs.insert( std::make_pair( layerpair.ID, layerpair ) );
}
else if( nodeName == wxT( "ATTRNAME" ) )
{
CPA_ATTRNAME attrname;
//TODO try.. catch + throw again with more detailed error information
attrname.Parse( cNode );
AttributeNames.insert( std::make_pair( attrname.ID, attrname ) );
}
else if( nodeName == wxT( "NETCLASS" ) )
{
CPA_NETCLASS netclass;
//TODO try.. catch + throw again with more detailed error information
netclass.Parse( cNode );
NetClasses.insert( std::make_pair( netclass.ID, netclass ) );
}
else if( nodeName == wxT( "SPCCLASSNAME" ) )
{
CPA_SPCCLASSNAME spcclassname;
//TODO try.. catch + throw again with more detailed error information
spcclassname.Parse( cNode );
SpacingClassNames.insert( std::make_pair( spcclassname.ID, spcclassname ) );
}
else if( nodeName == wxT( "SPCCLASSSPACE" ) )
{
CPA_SPCCLASSSPACE spcclassspace;
//TODO try.. catch + throw again with more detailed error information
spcclassspace.Parse( cNode );
SpacingClasses.push_back( spcclassspace );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), location );
THROW_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
}
}
}
void CPAParseNameAndID( XNODE* aNode, wxString& aName, wxString& aID )
{
aID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
aName = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
if( aID.IsEmpty() )
THROW_MISSING_PARAMETER_IO_ERROR(
wxT( "ID" ), wxString::Format( "%s %s", aNode->GetName(), aName ) );
if( aName.IsEmpty() )
THROW_MISSING_PARAMETER_IO_ERROR(
wxT( "Name" ), wxString::Format( "%s %s", aNode->GetName(), aID ) );
}
void CPA_MATERIAL::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "MATERIAL" ) );
//Process Name & ID
CPAParseNameAndID( aNode, Name, ID );
ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
//Process Type
wxString sType = CADSTAR_COMMON::GetAttributeID( aNode, 2 );
@ -190,19 +292,21 @@ void CPA_MATERIAL::Parse( XNODE* aNode )
for( ; iNode; iNode = iNode->GetNext() )
{
wxString nodeName = iNode->GetName();
wxString location = wxString::Format( "MATERIAL %s->%s", Name, nodeName );
if( nodeName == wxT( "RELPERMIT" ) )
{
CPAParseEValue( iNode, Permittivity, location );
//TODO try.. catch + throw again with more detailed error information
CADSTAR_COMMON::ParseChildEValue( iNode, Permittivity );
}
else if( nodeName == wxT( "LOSSTANGENT" ) )
{
CPAParseEValue( iNode, LossTangent, location );
//TODO try.. catch + throw again with more detailed error information
CADSTAR_COMMON::ParseChildEValue( iNode, LossTangent );
}
else if( nodeName == wxT( "RESISTIVITY" ) )
{
CPAParseEValue( iNode, Resistivity, location );
//TODO try.. catch + throw again with more detailed error information
CADSTAR_COMMON::ParseChildEValue( iNode, Resistivity );
}
else
{
@ -211,12 +315,14 @@ void CPA_MATERIAL::Parse( XNODE* aNode )
}
}
void CPA_LAYER::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "LAYER" ) );
//Process Name & ID
CPAParseNameAndID( aNode, Name, ID );
ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
auto processLayerMaterialDetails = [&]() {
@ -230,13 +336,7 @@ void CPA_LAYER::Parse( XNODE* aNode )
//Process material ID and layer width
MaterialId = CADSTAR_COMMON::GetAttributeID( tempNode, 0 );
if( MaterialId.IsEmpty() )
THROW_PARSING_IO_ERROR(
wxT( "Material ID" ), wxString::Format( "LAYER %s->MAKE", Name ) );
if( !CADSTAR_COMMON::GetAttributeID( tempNode, 1 ).ToLong( &Thickness ) )
THROW_PARSING_IO_ERROR(
wxT( "Thickness" ), wxString::Format( "LAYER %s->MAKE", Name ) );
Thickness = CADSTAR_COMMON::GetAttributeIDLong( tempNode, 1 );
XNODE* childOfTempNode = tempNode->GetChildren();
@ -412,18 +512,649 @@ void CPA_LAYER::Parse( XNODE* aNode )
}
}
void CPA_EVALUE::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "E" ) );
if( ( !CADSTAR_COMMON::GetAttributeID( aNode, 0 ).ToLong( &Base ) )
|| ( !CADSTAR_COMMON::GetAttributeID( aNode, 1 ).ToLong( &Exponent ) ) )
THROW_PARSING_IO_ERROR( wxT( "Base and Exponent" ),
wxString::Format(
"%s->%s", aNode->GetParent()->GetName(), aNode->GetParent()->GetName() ) );
void CPA_FORMAT::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "FORMAT" ) );
Type = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
SomeInt = CADSTAR_COMMON::GetAttributeIDLong( aNode, 1 );
Version = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 );
}
double CPA_EVALUE::GetDouble()
void CPA_TIMESTAMP::Parse( XNODE* aNode )
{
return Base * std::pow( 10.0, Exponent );
wxASSERT( aNode->GetName() == wxT( "TIMESTAMP" ) );
if( !CADSTAR_COMMON::GetAttributeID( aNode, 0 ).ToLong( &Year )
|| !CADSTAR_COMMON::GetAttributeID( aNode, 1 ).ToLong( &Month )
|| !CADSTAR_COMMON::GetAttributeID( aNode, 2 ).ToLong( &Day )
|| !CADSTAR_COMMON::GetAttributeID( aNode, 3 ).ToLong( &Hour )
|| !CADSTAR_COMMON::GetAttributeID( aNode, 4 ).ToLong( &Minute )
|| !CADSTAR_COMMON::GetAttributeID( aNode, 5 ).ToLong( &Second ) )
THROW_PARSING_IO_ERROR( wxT( "TIMESTAMP" ), wxString::Format( "HEADER" ) );
}
void CPA_HEADER::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "HEADER" ) );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString nodeName = cNode->GetName();
if( nodeName == wxT( "FORMAT" ) )
//TODO try.. catch + throw again with more detailed error information
Format.Parse( cNode );
else if( nodeName == wxT( "JOBFILE" ) )
JobFile = CADSTAR_COMMON::GetAttributeID( cNode, 0 );
else if( nodeName == wxT( "JOBTITLE" ) )
JobTitle = CADSTAR_COMMON::GetAttributeID( cNode, 0 );
else if( nodeName == wxT( "GENERATOR" ) )
Generator = CADSTAR_COMMON::GetAttributeID( cNode, 0 );
else if( nodeName == wxT( "RESOLUTION" ) )
{
XNODE* subNode = cNode->GetChildren();
if( ( subNode->GetName() == wxT( "METRIC" ) )
&& ( CADSTAR_COMMON::GetAttributeID( subNode, 0 ) == wxT( "HUNDREDTH" ) )
&& ( CADSTAR_COMMON::GetAttributeID( subNode, 1 ) == wxT( "MICRON" ) ) )
{
Resolution = CPA_RESOLUTION::HUNDREDTH_MICRON;
}
else //TODO Need to find out if there are other possible resolutions. Logically
// there must be other base units that could be used, such as "IMPERIAL INCH"
// or "METRIC MM" but so far none of settings in CADSTAR generated a different
// output resolution to "HUNDREDTH MICRON"
THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), wxT( "HEADER->RESOLUTION" ) );
}
else if( nodeName == wxT( "TIMESTAMP" ) )
//TODO try.. catch + throw again with more detailed error information
Timestamp.Parse( cNode );
else
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "HEADER" ) );
}
}
void CPA_LINECODE::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "LINECODE" ) );
//Process Name & ID
ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
if( !CADSTAR_COMMON::GetAttributeID( aNode, 2 ).ToLong( &Width ) )
THROW_PARSING_IO_ERROR( wxT( "Line Width" ), wxString::Format( "LINECODE -> %s", Name ) );
XNODE* cNode = aNode->GetChildren();
if( cNode->GetName() != wxT( "STYLE" ) )
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxString::Format( "LINECODE -> %s", Name ) );
wxString styleStr = CADSTAR_COMMON::GetAttributeID( cNode, 0 );
if( styleStr == wxT( "SOLID" ) )
Style = CPA_LINESTYLE::SOLID;
else if( styleStr == wxT( "DASH" ) )
Style = CPA_LINESTYLE::DASH;
else if( styleStr == wxT( "DASHDOT" ) )
Style = CPA_LINESTYLE::DASHDOT;
else if( styleStr == wxT( "DASHDOTDOT" ) )
Style = CPA_LINESTYLE::DASHDOTDOT;
else if( styleStr == wxT( "DOT" ) )
Style = CPA_LINESTYLE::DOT;
else
THROW_UNKNOWN_PARAMETER_IO_ERROR( wxString::Format( "STYLE %s", styleStr ),
wxString::Format( "LINECODE -> %s", Name ) );
}
void CPA_HATCH::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "HATCH" ) );
Step = CADSTAR_COMMON::GetAttributeIDLong( aNode, 0 );
LineWidth = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 );
XNODE* cNode = aNode->GetChildren();
if( !cNode || cNode->GetName() != wxT( "ORIENT" ) )
THROW_MISSING_NODE_IO_ERROR( wxT( "ORIENT" ), wxT( "HATCH" ) );
OrientAngle = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
}
void CPA_HATCHCODE::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "HATCHCODE" ) );
//Process Name & ID
ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
wxString location = wxString::Format( "HATCHCODE -> %s", Name );
for( ; cNode; cNode = cNode->GetNext() )
{
if( cNode->GetName() != wxT( "HATCH" ) )
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), location );
CPA_HATCH hatch;
//TODO try.. catch + throw again with more detailed error information
hatch.Parse( cNode );
Hatches.push_back( hatch );
}
}
void CPA_FONT::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "FONT" ) );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Modifier1 = CADSTAR_COMMON::GetAttributeIDLong( aNode, 1 );
Modifier2 = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "ITALIC" ) )
Italic = true;
else if( cNodeName == wxT( "KERNING" ) )
KerningPairs = true;
else
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
void CPA_TEXTCODE::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "TEXTCODE" ) );
//Process Name & ID
ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
LineWidth = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 );
Height = CADSTAR_COMMON::GetAttributeIDLong( aNode, 3 );
Width = CADSTAR_COMMON::GetAttributeIDLong( aNode, 4 );
XNODE* cNode = aNode->GetChildren();
if( cNode )
{
if( cNode->GetName() == wxT( "FONT" ) )
//TODO try.. catch + throw again with more detailed error information
Font.Parse( cNode );
else
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
}
}
void CPA_ROUTECODE::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "ROUTECODE" ) );
//Process Name & ID
ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
OptimalWidth = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "NECKWIDTH" ) )
NeckedWidth = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
else if( cNodeName == wxT( "MINWIDTH" ) )
MinWidth = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
else if( cNodeName == wxT( "MAXWIDTH" ) )
MaxWidth = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
else
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
void CPA_COPREASSIGN::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "COPREASSIGN" ) );
LayerID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
CopperWidth = CADSTAR_COMMON::GetAttributeIDLong( aNode, 1 );
}
void CPA_COPPERCODE::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "COPPERCODE" ) );
//Process Name & ID
ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
CopperWidth = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
if( cNode->GetName() == wxT( "COPREASSIGN" ) )
{
//TODO try.. catch + throw again with more detailed error information
CPA_COPREASSIGN reassign;
reassign.Parse( cNode );
Reassigns.push_back( reassign );
}
else
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
}
}
void CPA_SPACINGCODE::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "SPACINGCODE" ) );
Code = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Spacing = CADSTAR_COMMON::GetAttributeIDLong( aNode, 1 );
}
bool CPA_PAD_SHAPE::IsShape( XNODE* aNode )
{
wxString aNodeName = aNode->GetName();
if( aNodeName == wxT( "ANNULUS" ) || aNodeName == wxT( "BULLET" ) || aNodeName == wxT( "ROUND" )
|| aNodeName == wxT( "DIAMOND" ) || aNodeName == wxT( "FINGER" )
|| aNodeName == wxT( "OCTAGON" ) || aNodeName == wxT( "RECTANGLE" )
|| aNodeName == wxT( "ROUNDED" ) || aNodeName == wxT( "SQUARE" ) )
return true;
else
return false;
}
void CPA_PAD_SHAPE::Parse( XNODE* aNode )
{
wxASSERT( IsShape( aNode ) );
wxString aNodeName = aNode->GetName();
if( aNodeName == wxT( "ANNULUS" ) )
ShapeType = CPA_SHAPE_TYPE::ANNULUS;
else if( aNodeName == wxT( "BULLET" ) )
ShapeType = CPA_SHAPE_TYPE::BULLET;
else if( aNodeName == wxT( "ROUND" ) )
ShapeType = CPA_SHAPE_TYPE::CIRCLE;
else if( aNodeName == wxT( "DIAMOND" ) )
ShapeType = CPA_SHAPE_TYPE::DIAMOND;
else if( aNodeName == wxT( "FINGER" ) )
ShapeType = CPA_SHAPE_TYPE::FINGER;
else if( aNodeName == wxT( "OCTAGON" ) )
ShapeType = CPA_SHAPE_TYPE::OCTAGON;
else if( aNodeName == wxT( "RECTANGLE" ) )
ShapeType = CPA_SHAPE_TYPE::RECTANGLE;
else if( aNodeName == wxT( "ROUNDED" ) )
ShapeType = CPA_SHAPE_TYPE::ROUNDED_RECT;
else if( aNodeName == wxT( "SQUARE" ) )
ShapeType = CPA_SHAPE_TYPE::SQUARE;
else
wxASSERT( true );
switch( ShapeType )
{
case CPA_SHAPE_TYPE::ANNULUS:
Size = CADSTAR_COMMON::GetAttributeIDLong( aNode, 0 );
InternalFeature = CADSTAR_COMMON::GetAttributeIDLong( aNode, 1 );
break;
case CPA_SHAPE_TYPE::ROUNDED_RECT:
InternalFeature = CADSTAR_COMMON::GetAttributeIDLong( aNode, 3 );
//Fall through
case CPA_SHAPE_TYPE::BULLET:
case CPA_SHAPE_TYPE::FINGER:
case CPA_SHAPE_TYPE::RECTANGLE:
RightLength = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 );
LeftLength = CADSTAR_COMMON::GetAttributeIDLong( aNode, 1 );
//Fall through
case CPA_SHAPE_TYPE::SQUARE:
if( aNode->GetChildren() )
{
if( aNode->GetChildren()->GetName() == wxT( "ORIENT" ) )
{
OrientAngle = CADSTAR_COMMON::GetAttributeIDLong( aNode->GetChildren(), 0 );
}
else
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
CADSTAR_COMMON::CheckNoNextNodes( aNode->GetChildren() );
}
//Fall through
case CPA_SHAPE_TYPE::CIRCLE:
Size = CADSTAR_COMMON::GetAttributeIDLong( aNode, 0 );
break;
}
}
void CPA_PADREASSIGN::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "PADREASSIGN" ) );
LayerID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
if( CPA_PAD_SHAPE::IsShape( aNode->GetChildren() ) )
//TODO try.. catch + throw again with more detailed error information
Shape.Parse( aNode->GetChildren() );
else
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
CADSTAR_COMMON::CheckNoNextNodes( aNode->GetChildren() );
}
void CPA_PADCODE::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "PADCODE" ) );
//Process Name & ID
ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
wxString location = wxString::Format( "PADCODE -> %s", Name );
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( CPA_PAD_SHAPE::IsShape( cNode ) )
//TODO try.. catch + throw again with more detailed error information
Shape.Parse( cNode );
else if( cNodeName == wxT( "CLEARANCE" ) )
ReliefClearance = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
else if( cNodeName == wxT( "RELIEFWIDTH" ) )
ReliefWidth = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
else if( cNodeName == wxT( "DRILL" ) )
{
DrillDiameter = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
XNODE* subNode = cNode->GetChildren();
for( ; subNode; subNode = subNode->GetNext() )
{
wxString subNodeName = subNode->GetName();
if( subNodeName == wxT( "NONPLATED" ) )
Plated = false;
else if( subNodeName == wxT( "OVERSIZE" ) )
DrillOversize = CADSTAR_COMMON::GetAttributeIDLong( subNode, 0 );
else
THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
}
}
else if( cNodeName == wxT( "DRILLLENGTH" ) )
SlotLength = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
else if( cNodeName == wxT( "DRILLORIENTATION" ) )
SlotOrientation = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
else if( cNodeName == wxT( "DRILLXOFFSET" ) )
DrillXoffset = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
else if( cNodeName == wxT( "DRILLYOFFSET" ) )
DrillYoffset = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
else if( cNodeName == wxT( "PADREASSIGN" ) )
{
//TODO try.. catch + throw again with more detailed error information
CPA_PADREASSIGN reassign;
reassign.Parse( cNode );
Reassigns.push_back( reassign );
}
else
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
}
}
void CPA_VIAREASSIGN::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "VIAREASSIGN" ) );
LayerID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
if( CPA_PAD_SHAPE::IsShape( aNode->GetChildren() ) )
//TODO try.. catch + throw again with more detailed error information
Shape.Parse( aNode->GetChildren() );
else
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
CADSTAR_COMMON::CheckNoNextNodes( aNode->GetChildren() );
}
void CPA_VIACODE::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "VIACODE" ) );
//Process Name & ID
ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
wxString location = wxString::Format( "VIACODE -> %s", Name );
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( CPA_PAD_SHAPE::IsShape( cNode ) )
//TODO try.. catch + throw again with more detailed error information
Shape.Parse( cNode );
else if( cNodeName == wxT( "CLEARANCE" ) )
ReliefClearance = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
else if( cNodeName == wxT( "RELIEFWIDTH" ) )
ReliefWidth = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
else if( cNodeName == wxT( "DRILL" ) )
{
DrillDiameter = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 );
XNODE* subNode = cNode->GetChildren();
for( ; subNode; subNode = subNode->GetNext() )
{
wxString subNodeName = subNode->GetName();
if( subNodeName == wxT( "OVERSIZE" ) )
DrillOversize = CADSTAR_COMMON::GetAttributeIDLong( subNode, 0 );
else
THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
}
}
else if( cNodeName == wxT( "VIAREASSIGN" ) )
{
//TODO try.. catch + throw again with more detailed error information
CPA_VIAREASSIGN reassign;
reassign.Parse( cNode );
Reassigns.push_back( reassign );
}
else
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
}
}
void CPA_LAYERPAIR::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "LAYERPAIR" ) );
//Process Name & ID
ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
PhysicalLayerStart = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 );
PhysicalLayerEnd = CADSTAR_COMMON::GetAttributeIDLong( aNode, 3 );
wxString location = wxString::Format( "LAYERPAIR -> %s", Name );
if( aNode->GetChildren() )
{
if( aNode->GetChildren()->GetName() == wxT( "VIACODEREF" ) )
{
ViacodeID = CADSTAR_COMMON::GetAttributeID( aNode->GetChildren(), 0 );
}
else
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), location );
CADSTAR_COMMON::CheckNoNextNodes( aNode->GetChildren() );
}
}
void CPA_ATTRNAME::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "ATTRNAME" ) );
//Process Name & ID
ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
wxString location = wxString::Format( "ATTRNAME -> %s", Name );
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "ATTROWNER" ) )
{
wxString attOwnerVal = CADSTAR_COMMON::GetAttributeID( cNode, 0 );
if( attOwnerVal == wxT( "ALL_ITEMS" ) )
AttributeOwner = CPA_ATTROWNER::ALL_ITEMS;
else if( attOwnerVal == wxT( "AREA" ) )
AttributeOwner = CPA_ATTROWNER::AREA;
else if( attOwnerVal == wxT( "BOARD" ) )
AttributeOwner = CPA_ATTROWNER::BOARD;
else if( attOwnerVal == wxT( "COMPONENT" ) )
AttributeOwner = CPA_ATTROWNER::COMPONENT;
else if( attOwnerVal == wxT( "CONNECTION" ) )
AttributeOwner = CPA_ATTROWNER::CONNECTION;
else if( attOwnerVal == wxT( "COPPER" ) )
AttributeOwner = CPA_ATTROWNER::COPPER;
else if( attOwnerVal == wxT( "DOCSYMBOL" ) )
AttributeOwner = CPA_ATTROWNER::DOCSYMBOL;
else if( attOwnerVal == wxT( "FIGURE" ) )
AttributeOwner = CPA_ATTROWNER::FIGURE;
else if( attOwnerVal == wxT( "NET" ) )
AttributeOwner = CPA_ATTROWNER::NET;
else if( attOwnerVal == wxT( "NETCLASS" ) )
AttributeOwner = CPA_ATTROWNER::NETCLASS;
else if( attOwnerVal == wxT( "PART" ) )
AttributeOwner = CPA_ATTROWNER::PART;
else if( attOwnerVal == wxT( "PART_DEFINITION" ) )
AttributeOwner = CPA_ATTROWNER::PART_DEFINITION;
else if( attOwnerVal == wxT( "PIN" ) )
AttributeOwner = CPA_ATTROWNER::PIN;
else if( attOwnerVal == wxT( "SYMDEF" ) )
AttributeOwner = CPA_ATTROWNER::SYMDEF;
else if( attOwnerVal == wxT( "TEMPLATE" ) )
AttributeOwner = CPA_ATTROWNER::TEMPLATE;
else if( attOwnerVal == wxT( "TESTPOINT" ) )
AttributeOwner = CPA_ATTROWNER::TESTPOINT;
else
THROW_UNKNOWN_PARAMETER_IO_ERROR( attOwnerVal, location );
}
else if( cNodeName == wxT( "ATTRUSAGE" ) )
{
wxString attUsageVal = CADSTAR_COMMON::GetAttributeID( cNode, 0 );
if( attUsageVal == wxT( "BOTH" ) )
AttributeUsage = CPA_ATTRUSAGE::BOTH;
else if( attUsageVal == wxT( "COMPONENT" ) )
AttributeUsage = CPA_ATTRUSAGE::COMPONENT;
else if( attUsageVal == wxT( "PART_DEFINITION" ) )
AttributeUsage = CPA_ATTRUSAGE::PART_DEFINITION;
else if( attUsageVal == wxT( "PART_LIBRARY" ) )
AttributeUsage = CPA_ATTRUSAGE::PART_LIBRARY;
else if( attUsageVal == wxT( "SYMBOL" ) )
AttributeUsage = CPA_ATTRUSAGE::SYMBOL;
else
THROW_UNKNOWN_PARAMETER_IO_ERROR( attUsageVal, location );
}
else if( cNodeName == wxT( "NOTRANSFER" ) )
NoTransfer = true;
else
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
}
}
void CPA_ATTRIBUTE_VALUE::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "ATTR" ) );
AttributeID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Value = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
}
void CPA_NETCLASS::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "NETCLASS" ) );
//Process Name & ID
ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
wxString location = wxString::Format( "NETCLASS -> %s", Name );
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "ATTR" ) )
{
//TODO try.. catch + throw again with more detailed error information
CPA_ATTRIBUTE_VALUE attribute_val;
attribute_val.Parse( cNode );
Attributes.push_back( attribute_val );
}
else
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
}
}
void CPA_SPCCLASSNAME::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "SPCCLASSNAME" ) );
//Process Name & ID
ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
}
void CPA_SPCCLASSSPACE::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "SPCCLASSSPACE" ) );
SpacingClassID1 = CADSTAR_COMMON::GetAttributeID( aNode, 0 );
SpacingClassID2 = CADSTAR_COMMON::GetAttributeID( aNode, 1 );
LayerID = CADSTAR_COMMON::GetAttributeID( aNode, 2 );
Spacing = CADSTAR_COMMON::GetAttributeIDLong( aNode, 3 );
}

View File

@ -28,23 +28,68 @@
#include <cadstar_common.h>
#include <map>
#include <vector>
/**
* @brief Represents a floating value in E notation
*/
struct CPA_EVALUE
const long CPA_UNDEFINED = -1; //<Undefined Parameter
typedef wxString CPA_ID;
//=================================
// HEADER
//=================================
struct CPA_FORMAT
{
long Base = 0;
long Exponent = 0;
wxString Type;
long SomeInt; //<unsure what this parameter is used for
long Version; //<Archive version number (e.g. 21 => CADSTAR 2018.0 and 2019.0 arhive,
// 20=> CADSTAR 18.0 archive, 19=> CADSTAR 17.0 archive, etc.)
void Parse( XNODE* aNode );
double GetDouble();
};
typedef wxString CPA_MATERIAL_ID;
struct CPA_TIMESTAMP
{
long Year;
long Month;
long Day;
long Hour;
long Minute;
long Second;
void Parse( XNODE* aNode );
};
//Note: there are possibly several other resolutions, but HUNDREDTH MICRON is only one known
enum class CPA_RESOLUTION
{
HUNDREDTH_MICRON
};
struct CPA_HEADER
{
CPA_FORMAT Format;
wxString JobFile;
wxString JobTitle;
wxString Generator;
CPA_RESOLUTION Resolution;
CPA_TIMESTAMP Timestamp;
void Parse( XNODE* aNode );
};
//=================================
// ASSIGNMENTS
//=================================
//.................................
// ASSIGNMENTS -> LAYERDEFS
//.................................
typedef wxString CPA_LAYER_ID;
/**
* @brief subset of CPA_LAYER_TYPE - for materials only
@ -56,18 +101,20 @@ enum class CPA_MATERIAL_LAYER_TYPE
NON_ELECTRICAL
};
struct CPA_MATERIAL
{
CPA_MATERIAL_ID ID;
CPA_ID ID;
wxString Name;
CPA_MATERIAL_LAYER_TYPE Type; //<Type of layer appropriate for the material being set up
CPA_EVALUE Permittivity;
CPA_EVALUE LossTangent;
CPA_EVALUE Resistivity; //< x10^-8 ohm*metre
CADSTAR_COMMON::EVALUE Permittivity;
CADSTAR_COMMON::EVALUE LossTangent;
CADSTAR_COMMON::EVALUE Resistivity; //< x10^-8 ohm*metre
void Parse( XNODE* aNode );
};
enum class CPA_LAYER_TYPE
{
UNDEFINED, //< Only used for error detection
@ -84,6 +131,7 @@ enum class CPA_LAYER_TYPE
DOC
};
enum class CPA_LAYER_SUBTYPE
{
LAYERSUBTYPE_NONE,
@ -94,6 +142,7 @@ enum class CPA_LAYER_SUBTYPE
LAYERSUBTYPE_PASTE
};
enum class CPA_ROUTING_BIAS
{
UNBIASED, //<Keyword "UNBIASED" (default)
@ -103,6 +152,7 @@ enum class CPA_ROUTING_BIAS
OBSTACLE //<Keyword "OBSTACLE"
};
enum class CPA_EMBEDDING
{
NONE,
@ -110,38 +160,379 @@ enum class CPA_EMBEDDING
BELOW
};
typedef long CPA_PHYSICAL_LAYER;
struct CPA_LAYER
{
CPA_LAYER_ID ID;
CPA_ID ID;
wxString Name;
CPA_LAYER_TYPE Type = CPA_LAYER_TYPE::UNDEFINED;
CPA_LAYER_SUBTYPE SubType = CPA_LAYER_SUBTYPE::LAYERSUBTYPE_NONE;
long PhysicalLayer = 0; //< If 0, no physical layer is assigned
// (e.g. documentation and construction layers)
CPA_LAYER_ID SwapLayerID = wxEmptyString; //< If empty, no swap layer
CPA_PHYSICAL_LAYER PhysicalLayer = CPA_UNDEFINED; //< If CPA_UNDEFINED, no physical layer is
// assigned (e.g. documentation and
// construction layers)
CPA_ID SwapLayerID = wxEmptyString; //< If empty, no swap layer
CPA_ROUTING_BIAS RoutingBias = CPA_ROUTING_BIAS::UNBIASED;
long Thickness = 0; //< Note: Units of length are defined in file header
CPA_MATERIAL_ID MaterialId;
CPA_ID MaterialId;
CPA_EMBEDDING Embedding = CPA_EMBEDDING::NONE;
void Parse( XNODE* aNode );
};
struct CPA_LAYERDEFS
{
std::map<CPA_MATERIAL_ID, CPA_MATERIAL> Materials;
std::map<CPA_LAYER_ID, CPA_LAYER> Layers;
std::vector<CPA_LAYER_ID> LayerStack;
std::map<CPA_ID, CPA_MATERIAL> Materials;
std::map<CPA_ID, CPA_LAYER> Layers;
std::vector<CPA_ID> LayerStack;
void Parse( XNODE* aNode );
};
//.................................
// ASSIGNMENTS -> CODEDEFS
//.................................
enum class CPA_LINESTYLE
{
SOLID,
DASH,
DASHDOT,
DASHDOTDOT,
DOT
};
struct CPA_LINECODE
{
CPA_ID ID;
wxString Name;
long Width;
CPA_LINESTYLE Style;
void Parse( XNODE* aNode );
};
struct CPA_HATCH
{
long Step;
long LineWidth;
long OrientAngle; //< 1/1000 of a Degree
void Parse( XNODE* aNode );
};
struct CPA_HATCHCODE
{
CPA_ID ID;
wxString Name;
std::vector<CPA_HATCH> Hatches;
void Parse( XNODE* aNode );
};
const long CPA_FONT_NORMAL = 400;
const long CPA_FONT_BOLD = 700;
struct CPA_FONT
{
wxString Name = wxT( "CADSTAR" );
long Modifier1 = CPA_FONT_NORMAL; //< It seems this is related to weight. 400=Normal, 700=Bold.
long Modifier2 = 0; //< It seems this is always 0 regardless of settings
bool KerningPairs = false; //< From CADSTAR Help: "Kerning Pairs is for causing the system to
//automatically reduce the spacing between certain pairs of
//characters in order to improve the appearance of the text"
bool Italic = false;
void Parse( XNODE* aNode );
};
struct CPA_TEXTCODE
{
CPA_ID ID;
wxString Name;
long LineWidth;
long Height;
long Width; //< Defaults to 0 if using system fonts or, if using CADSTAR font, default to
//equal height (1:1 aspect ratio). Allows for system fonts to be rendered in
//a different aspect ratio.
CPA_FONT Font;
void Parse( XNODE* aNode );
};
struct CPA_ROUTECODE
{
CPA_ID ID;
wxString Name;
long OptimalWidth;
long MinWidth;
long MaxWidth;
long NeckedWidth;
void Parse( XNODE* aNode );
};
struct CPA_COPREASSIGN
{
CPA_ID LayerID;
long CopperWidth;
void Parse( XNODE* aNode );
};
struct CPA_COPPERCODE
{
CPA_ID ID;
wxString Name;
long CopperWidth;
std::vector<CPA_COPREASSIGN> Reassigns;
void Parse( XNODE* aNode );
};
struct CPA_SPACINGCODE
{
wxString Code;
long Spacing;
void Parse( XNODE* aNode );
};
enum class CPA_SHAPE_TYPE
{
ANNULUS,
BULLET,
CIRCLE, //<Keyword "ROUND"
DIAMOND,
FINGER,
OCTAGON,
RECTANGLE,
ROUNDED_RECT, //<Keyword "ROUNDED"
SQUARE
};
struct CPA_PAD_SHAPE
{
CPA_SHAPE_TYPE ShapeType;
long Size = CPA_UNDEFINED;
long LeftLength = CPA_UNDEFINED;
long RightLength = CPA_UNDEFINED;
long InternalFeature = CPA_UNDEFINED;
long OrientAngle = 0; //< 1/1000 of a Degree
static bool IsShape( XNODE* aNode );
void Parse( XNODE* aNode );
};
struct CPA_PADREASSIGN
{
CPA_ID LayerID;
CPA_PAD_SHAPE Shape;
void Parse( XNODE* aNode ); //TODO Implement
};
struct CPA_PADCODE
{
CPA_ID ID;
wxString Name;
CPA_PAD_SHAPE Shape;
long ReliefClearance = CPA_UNDEFINED; //< if undefined inherits from design
long ReliefWidth = CPA_UNDEFINED; //< if undefined inherits from design
bool Plated = true;
long DrillDiameter = CPA_UNDEFINED;
long DrillOversize = CPA_UNDEFINED;
long SlotLength = CPA_UNDEFINED;
long SlotOrientation = CPA_UNDEFINED;
long DrillXoffset = CPA_UNDEFINED;
long DrillYoffset = CPA_UNDEFINED;
std::vector<CPA_PADREASSIGN> Reassigns;
void Parse( XNODE* aNode );
};
struct CPA_VIAREASSIGN
{
CPA_ID LayerID;
CPA_PAD_SHAPE Shape;
void Parse( XNODE* aNode );
};
struct CPA_VIACODE
{
CPA_ID ID;
wxString Name;
CPA_PAD_SHAPE Shape;
long ReliefClearance = CPA_UNDEFINED; //< if undefined inherits from design
long ReliefWidth = CPA_UNDEFINED; //< if undefined inherits from design
long DrillDiameter = CPA_UNDEFINED;
long DrillOversize = CPA_UNDEFINED;
std::vector<CPA_VIAREASSIGN> Reassigns;
void Parse( XNODE* aNode );
};
struct CPA_LAYERPAIR
{
CPA_ID ID;
wxString Name;
CPA_PHYSICAL_LAYER PhysicalLayerStart;
CPA_PHYSICAL_LAYER PhysicalLayerEnd;
CPA_ID ViacodeID;
void Parse( XNODE* aNode );
};
enum class CPA_ATTROWNER
{
ALL_ITEMS,
AREA,
BOARD,
COMPONENT,
CONNECTION,
COPPER,
DOCSYMBOL,
FIGURE,
NET,
NETCLASS,
PART, //< Only library Attributes
PART_DEFINITION, //< Only library Attributes
PIN,
SYMDEF,
TEMPLATE,
TESTPOINT
};
enum class CPA_ATTRUSAGE
{
BOTH, //< From CADSTAR Help: Assigned to both Schematic symbols and PCB components,
// and displayed on Schematic and PCB designs.
COMPONENT, //< From CADSTAR Help: Assigned to PCB components and displayed on PCB designs
PART_DEFINITION, //< From CADSTAR Help: Assigned to Parts library Definitions and displayed
// by the Library searcher
PART_LIBRARY, //< From CADSTAR Help: Only used by non-Cadstar applicationws
SYMBOL, //< From CADSTAR Help: Assigned to Schematic Symbols and displayed on
// Schematic Designs
UNDEFINED //< Note: It seems that some attribute have no "ATTRUSAGE" defined. It appears
// that the attributes that fall under this category arethe ones associated
// with the design itself (i.e. not inherited from the library)
};
/**
* @brief NOTE from CADSTAR help: To convert a Part Definition Attribute into a hyperlink, prefix
* the attribute name with "Link "
*/
struct CPA_ATTRNAME
{
CPA_ID ID;
wxString Name;
CPA_ATTROWNER AttributeOwner = CPA_ATTROWNER::ALL_ITEMS;
CPA_ATTRUSAGE AttributeUsage = CPA_ATTRUSAGE::UNDEFINED;
bool NoTransfer = false; //< True="All Design Types", False="Current Design Type"
// "All Design Types" Description from CADSTAR Help: "The selected
// attribute name will beavailable when any design is displayed"
// "Current Design Type" From CADSTAR Help: This restricts the
// availability of the selectedattribute name to the current design.
void Parse( XNODE* aNode );
};
struct CPA_ATTRIBUTE_VALUE
{
CPA_ID AttributeID;
wxString Value;
void Parse( XNODE* aNode );
};
struct CPA_NETCLASS
{
CPA_ID ID;
wxString Name;
std::vector<CPA_ATTRIBUTE_VALUE> Attributes;
void Parse( XNODE* aNode );
};
struct CPA_SPCCLASSNAME
{
CPA_ID ID;
wxString Name;
void Parse( XNODE* aNode );
};
const CPA_ID CPA_NO_SPACE_CLASS_ID = wxT( "NO_SPACE_CLASS" ); //< Default spacing class
struct CPA_SPCCLASSSPACE
{
CPA_ID SpacingClassID1;
CPA_ID SpacingClassID2;
CPA_ID LayerID; //< Normally LAY0, which corresponds to (All Layers)
long Spacing;
void Parse( XNODE* aNode );
};
struct CPA_CODEDEFS
{
std::map<CPA_ID, CPA_LINECODE> LineCodes;
std::map<CPA_ID, CPA_HATCHCODE> HatchCodes;
std::map<CPA_ID, CPA_TEXTCODE> TextCodes;
std::map<CPA_ID, CPA_ROUTECODE> RouteCodes;
std::map<CPA_ID, CPA_COPPERCODE> CopperCodes;
std::vector<CPA_SPACINGCODE> SpacingCodes; //<Design Rules. E.g. "A_A" = Comp to Comp
std::map<CPA_ID, CPA_PADCODE> PadCodes;
std::map<CPA_ID, CPA_VIACODE> ViaCodes;
std::map<CPA_ID, CPA_LAYERPAIR> LayerPairs; //< Default vias to use between pairs of layers
std::map<CPA_ID, CPA_ATTRNAME> AttributeNames;
std::map<CPA_ID, CPA_NETCLASS> NetClasses;
std::map<CPA_ID, CPA_SPCCLASSNAME> SpacingClassNames;
std::vector<CPA_SPCCLASSSPACE> SpacingClasses;
void Parse( XNODE* aNode ); //TODO Implement
};
struct CPA_ASSIGNMENTS
{
CPA_LAYERDEFS Layerdefs;
//Todo Add codedefs, technology, grids, etc.
CPA_CODEDEFS Codedefs;
//TODO Add technology, grids, etc.
};
//=================================
// CPA_FILE
//=================================
/**
* @brief Represents a CADSTAR PCB Archive (CPA) file
*/
@ -161,13 +552,12 @@ public:
wxString Filename;
CPA_HEADER Header;
CPA_ASSIGNMENTS Assignments;
//Todo Add Header, Library, Defaults, etc..
};
//TODO Add Library, Defaults, Parts, etc..
//Helper Functions
void CPAParseEValue( XNODE* aNode, CPA_EVALUE& aValue, wxString location );
void CPAParseNameAndID( XNODE* aNode, wxString& aName, wxString& aID );
int KiCadUnitMultiplier; //<Use this value to convert units in this CPA file to KiCad units
};
#endif // CADSTAR_PCB_ARCHIVE_PARSER_H_