CADSTAR PCB Archive Importer: Load TEMPLATEs, COPPERs and NETs (including Tracks and Vias)

This commit is contained in:
Roberto Fernandez Bautista 2020-08-31 23:09:29 +01:00 committed by Seth Hillbrand
parent 05de678f4e
commit 866c069873
7 changed files with 974 additions and 156 deletions

View File

@ -47,6 +47,17 @@ void CADSTAR_ARCHIVE_PARSER::POINT::Parse( XNODE* aNode )
}
void CADSTAR_ARCHIVE_PARSER::LONGPOINT::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "PT" ) );
x = GetXmlAttributeIDLong( aNode, 0 );
y = GetXmlAttributeIDLong( aNode, 1 );
}
bool CADSTAR_ARCHIVE_PARSER::VERTEX::IsVertex( XNODE* aNode )
{
wxString aNodeName = aNode->GetName();
@ -241,7 +252,7 @@ long CADSTAR_ARCHIVE_PARSER::GetXmlAttributeIDLong( XNODE* aNode, unsigned int a
void CADSTAR_ARCHIVE_PARSER::CheckNoChildNodes( XNODE* aNode )
{
if( aNode->GetChildren() )
if( aNode && aNode->GetChildren() )
{
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
}
@ -250,7 +261,7 @@ void CADSTAR_ARCHIVE_PARSER::CheckNoChildNodes( XNODE* aNode )
void CADSTAR_ARCHIVE_PARSER::CheckNoNextNodes( XNODE* aNode )
{
if( aNode->GetNext() )
if( aNode && aNode->GetNext() )
{
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetNext()->GetName(), aNode->GetParent()->GetName() );
}

View File

@ -82,6 +82,15 @@ public:
void Parse( XNODE* aNode );
};
struct LONGPOINT
{
long x = UNDEFINED_VALUE;
long y = UNDEFINED_VALUE;
void Parse( XNODE* aNode );
};
enum class VERTEX_TYPE
{

File diff suppressed because it is too large Load Diff

View File

@ -28,19 +28,33 @@
#include <cadstar_pcb_archive_parser.h>
#include <class_board.h>
#include <set>
class BOARD;
class CADSTAR_PCB_ARCHIVE_LOADER : public CADSTAR_PCB_ARCHIVE_PARSER
{
public:
explicit CADSTAR_PCB_ARCHIVE_LOADER( wxString aFilename ) : CADSTAR_PCB_ARCHIVE_PARSER( aFilename )
explicit CADSTAR_PCB_ARCHIVE_LOADER( wxString aFilename )
: CADSTAR_PCB_ARCHIVE_PARSER( aFilename )
{
mBoard = nullptr;
mDesignCenter.x = 0;
mDesignCenter.y = 0;
mBoard = nullptr;
mDesignCenter.x = 0;
mDesignCenter.y = 0;
mDoneCopperWarning = false;
mNumNets = 0;
}
~CADSTAR_PCB_ARCHIVE_LOADER()
{
for( std::pair<SYMDEF_ID, MODULE*> libItem : mLibraryMap )
{
MODULE* mod = libItem.second;
if( mod )
delete mod;
}
}
/**
* @brief Loads a CADSTAR PCB Archive file into the KiCad BOARD object given
@ -54,12 +68,27 @@ private:
///< Populated by loadBoardStackup().
std::map<SYMDEF_ID, MODULE*> mLibraryMap; ///< Map between Cadstar and KiCad
///< components in the library. Populated
///< by loadComponentLibrary().
///< by loadComponentLibrary(). Owns the
///< MODULE objects.
std::map<COMPONENT_ID, MODULE*> mComponentMap; ///< Map between Cadstar and KiCad
///< components on the board. Does NOT own
///< the MODULE objects (these should have
///< been loaded to mBoard).
std::map<NET_ID, NETINFO_ITEM*> mNetMap; ///< Map between Cadstar and KiCad Nets
std::map<PHYSICAL_LAYER_ID, LAYER_ID> mCopperLayers; ///< Map of CADSTAR Physical layers to
///< CADSTAR Layer IDs
std::vector<LAYER_ID> mPowerPlaneLayers; ///< List of layers that are marked as
///< power plane in CADSTAR. This is used
///< by "loadtemplates"
wxPoint mDesignCenter; ///< Used for calculating the required
///< offset to apply to the Cadstar design
///< so that it fits in KiCad canvas
std::set<HATCHCODE_ID> mHatchcodesTested; ///< Used by checkAndLogHatchCode() to
///< avoid multiple duplicate warnings
bool mDoneCopperWarning; ///< Used by loadCoppers() to avoid
///< multiple duplicate warnings
int mNumNets; ///< Number of nets loaded so far
// Functions for loading individual elements:
void loadBoardStackup();
@ -68,6 +97,9 @@ private:
void loadFigures();
void loadAreas();
void loadComponents();
void loadTemplates();
void loadCoppers();
void loadNets();
// Helper functions for loading:
void logBoardStackupWarning(
@ -75,6 +107,8 @@ private:
void loadLibraryFigures( const SYMDEF& aComponent, MODULE* aModule );
void loadLibraryPads( const SYMDEF& aComponent, MODULE* aModule );
void loadComponentAttributes( const COMPONENT& aComponent, MODULE* aModule );
void loadNetTracks( const NET_ID& aCadstarNetID, const NET::ROUTE& aCadstarRoute );
void loadNetVia( const NET_ID& aCadstarNetID, const NET::VIA& aCadstarVia );
/**
* @brief
@ -114,7 +148,7 @@ private:
/**
* @brief Returns a vector of pointers to DRAWSEGMENT objects. Caller owns the objects.
* @param aCadstarVertices *
* @param aCadstarVertices
* @param aContainer to draw on (e.g. mBoard). Can be nullptr.
* @return
*/
@ -122,6 +156,15 @@ private:
const std::vector<VERTEX>& aCadstarVertices,
BOARD_ITEM_CONTAINER* aContainer = nullptr );
/**
* @brief Returns a pointer to a DRAWSEGMENT object. Caller owns the object.
* @param aCadstarStartPoint
* @param aCadstarVertex
* @param aContainer to draw on (e.g. mBoard). Can be nullptr.
* @return
*/
DRAWSEGMENT* getDrawSegmentFromVertex( const POINT& aCadstarStartPoint,
const VERTEX& aCadstarVertex, BOARD_ITEM_CONTAINER* aContainer = nullptr );
/**
* @brief
@ -150,6 +193,22 @@ private:
*/
SHAPE_LINE_CHAIN getLineChainFromDrawsegments( const std::vector<DRAWSEGMENT*> aDrawSegments );
/**
* @brief Returns a vector of pointers to TRACK/ARC objects. Caller owns the objects
* @param aDrawsegments
* @param aParentContainer sets this as the parent of each TRACK object and Add()s it to the parent
* @param aNet sets all the tracks to this net, unless nullptr
* @param aLayerOverride Sets all tracks to this layer, or, if it is UNDEFINED_LAYER, uses the layers
* in the DrawSegments
* @param aWidthOverride Sets all tracks to this width, or, if it is UNDEFINED_LAYER, uses the width
* in the DrawSegments
* @return
*/
std::vector<TRACK*> makeTracksFromDrawsegments( const std::vector<DRAWSEGMENT*> aDrawsegments,
BOARD_ITEM_CONTAINER* aParentContainer, NETINFO_ITEM* aNet = nullptr,
const PCB_LAYER_ID& aLayerOverride = PCB_LAYER_ID::UNDEFINED_LAYER,
int aWidthOverride = -1 );
/**
* @brief Adds a CADSTAR Attribute to a KiCad module
* @param aCadstarAttrLoc
@ -170,11 +229,11 @@ private:
int getLineThickness( const LINECODE_ID& aCadstarLineCodeID );
TEXTCODE getTextCode( const TEXTCODE_ID& aCadstarTextCodeID );
PADCODE getPadCode( const PADCODE_ID& aCadstarPadCodeID );
COPPERCODE getCopperCode( const COPPERCODE_ID& aCadstaCopperCodeID );
TEXTCODE getTextCode( const TEXTCODE_ID& aCadstarTextCodeID );
PADCODE getPadCode( const PADCODE_ID& aCadstarPadCodeID );
VIACODE getViaCode( const VIACODE_ID& aCadstarViaCodeID );
LAYERPAIR getLayerPair( const LAYERPAIR_ID& aCadstarLayerPairID );
wxString getAttributeName( const ATTRIBUTE_ID& aCadstarAttributeID );
@ -184,6 +243,13 @@ private:
PART getPart( const PART_ID& aCadstarPartID );
HATCHCODE getHatchCode( const HATCHCODE_ID& aCadstarHatchcodeID );
void checkAndLogHatchCode( const HATCHCODE_ID& aCadstarHatchcodeID );
MODULE* getModuleFromCadstarID( const COMPONENT_ID& aCadstarComponentID );
double getHatchCodeAngleDegrees( const HATCHCODE_ID& aCadstarHatchcodeID );
int getKiCadHatchCodeThickness( const HATCHCODE_ID& aCadstarHatchcodeID );
int getKiCadHatchCodeGap( const HATCHCODE_ID& aCadstarHatchcodeID );
/**
* @brief Scales, offsets and inverts y axis to make the point usable directly in KiCad
* @param aCadstarPoint
@ -206,11 +272,21 @@ private:
* @param aCadstarAngle
* @return
*/
double getKiCadAngle( const long long& aCadstarAngle )
double getAngleTenthDegree( const long long& aCadstarAngle )
{
return (double) aCadstarAngle / 100.0;
}
/**
* @brief
* @param aCadstarAngle
* @return
*/
double getAngleDegrees( const long long& aCadstarAngle )
{
return (double) aCadstarAngle / 1000.0;
}
/**
* @brief
* @param aPoint
@ -218,6 +294,14 @@ private:
*/
double getPolarAngle( wxPoint aPoint );
/**
* @brief Searches mNetMap and returns the NETINFO_ITEM pointer if exists. Otherwise
* creates a new one and adds it to mBoard.
* @param aCadstarNetID
* @return
*/
NETINFO_ITEM* getKiCadNet( const NET_ID& aCadstarNetID );
/**
* @brief

View File

@ -268,9 +268,9 @@ void CADSTAR_PCB_ARCHIVE_PARSER::RULESET::Parse( XNODE* aNode )
AreaViaCodeID = GetXmlAttributeIDString( cNode, 0 );
else if( nodeName == wxT( "SPACINGCODE" ) )
{
SPACINGCODE scode;
scode.Parse( cNode );
SpacingCodes.push_back( scode );
SPACINGCODE spacingcode;
spacingcode.Parse( cNode );
SpacingCodes.insert( std::make_pair( spacingcode.ID, spacingcode ) );
}
else
THROW_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
@ -322,7 +322,7 @@ void CADSTAR_PCB_ARCHIVE_PARSER::CODEDEFS::Parse( XNODE* aNode )
{
SPACINGCODE spacingcode;
spacingcode.Parse( cNode );
SpacingCodes.push_back( spacingcode );
SpacingCodes.insert( std::make_pair( spacingcode.ID, spacingcode ) );
}
else if( nodeName == wxT( "RULESET" ) )
{
@ -883,7 +883,7 @@ void CADSTAR_PCB_ARCHIVE_PARSER::SPACINGCODE::Parse( XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "SPACINGCODE" ) );
Code = GetXmlAttributeIDString( aNode, 0 );
ID = GetXmlAttributeIDString( aNode, 0 );
Spacing = GetXmlAttributeIDLong( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
@ -1390,8 +1390,7 @@ void CADSTAR_PCB_ARCHIVE_PARSER::TECHNOLOGY_SECTION::Parse( XNODE* aNode )
ViaGrid = GetXmlAttributeIDLong( cNode, 0 );
else if( cNodeName == wxT( "DESIGNORIGIN" ) )
{
std::vector<POINT> pts = ParseAllChildPoints( cNode, true, 1 );
DesignOrigin = pts[0];
DesignOrigin.Parse( cNode->GetChildren() );
}
else if( cNodeName == wxT( "DESIGNAREA" ) )
{
@ -1400,13 +1399,11 @@ void CADSTAR_PCB_ARCHIVE_PARSER::TECHNOLOGY_SECTION::Parse( XNODE* aNode )
}
else if( cNodeName == wxT( "DESIGNREF" ) )
{
std::vector<POINT> pts = ParseAllChildPoints( cNode, true, 1 );
DesignRef = pts[0];
DesignOrigin.Parse( cNode->GetChildren() );
}
else if( cNodeName == wxT( "DESIGNLIMIT" ) )
{
std::vector<POINT> pts = ParseAllChildPoints( cNode, true, 1 );
DesignLimit = pts[0];
DesignLimit.Parse( cNode->GetChildren() );
}
else if( cNodeName == wxT( "BACKOFFJCTS" ) )
BackOffJunctions = true;

View File

@ -26,9 +26,8 @@
#ifndef CADSTAR_PCB_ARCHIVE_PARSER_H_
#define CADSTAR_PCB_ARCHIVE_PARSER_H_
#include <boost/serialization/strong_typedef.hpp>
#include <plugins/cadstar/cadstar_archive_parser.h>
#include <map>
#include <plugins/cadstar/cadstar_archive_parser.h>
#include <vector>
@ -39,10 +38,6 @@
#define UNDEFINED_MATERIAL_ID ( MATERIAL_ID ) wxEmptyString
#define UNDEFINED_PHYSICAL_LAYER ( PHYSICAL_LAYER_ID ) - 1
/**
* Default spacing class for all nets
*/
#define NO_SPACE_CLASS_ID ( SPACING_CLASS_ID ) wxT( "NO_SPACE_CLASS" )
/**
* Component Name Attribute ID - typically used for placement of designators on silk screen.
@ -86,6 +81,7 @@ public:
typedef wxString COPPERCODE_ID;
typedef wxString PADCODE_ID;
typedef wxString VIACODE_ID;
typedef wxString SPACINGCODE_ID;
typedef wxString LAYERPAIR_ID;
typedef wxString ATTRIBUTE_ID;
typedef wxString NETCLASS_ID;
@ -394,7 +390,45 @@ public:
void Parse( XNODE* aNode );
};
wxString Code; //TODO convert to an enum class containing all valid spacings
/**
* @brief Possible spacing rules:
* - A_A = Component Placement to Component Placement
* - C_B = Copper to Board
* - C_C = Copper to Copper
* - H_H = Hole to Hole
* - OT_P = Optimal Route to Pad (Optional Rule)
* - OT_T = Optimal Route to Route (Optional Rule)
* - OT_V = Optimal Route to Via (Optional Rule)
* - P_B = Pad to Board
* - P_C = Pad to Copper
* - P_P = Pad to Pad
* - P_S = Pad to SMD pad (Optional Rule)
* - P_V = Pad to Via
* - T_B = Route to Board outline
* - T_C = Route to Copper
* - T_P = Route to Pad
* - T_T = Route to Route
* - T_S = Route to SMD Pad (Optional Rule)
* - T_V = Route to Via
* - S_B = SMD Pad to Board (Optional Rule)
* - S_C = SMD Pad to Copper (Optional Rule)
* - S_S = SMD Pad to SMD Pad (Optional Rule)
* - L_B = Test Land to Board
* - L_O = Test Land to Component
* - L_L = Test Land to Test Land
* - V_B = Via to Board
* - V_C = Via to Copper
* - V_S = Via to SMD Pad (Optional Rule)
* - V_V = Via to Via
*
* Other design rules are in:
* TECHNOLOGY->MAXMITER = Maximum Mitre (This parameter is not actually checked in Cadstar)
* TECHNOLOGY->MINMITER = Minimum Mitre (This parameter is not actually checked in Cadstar)
* TECHNOLOGY->MINUNNECKED = Minimum Thicker Track Length
* TECHNOLOGY->MINNECKED = Minimum Thinner Track Length
* TECHNOLOGY->MINROUTEWIDTH = Thin Route Width
*/
SPACINGCODE_ID ID;
long Spacing;
std::vector<REASSIGN> Reassigns; ///< Can have different spacings on differnt layers
@ -720,23 +754,24 @@ public:
///< will be used when inserting new vias within an area that
///< has been assigned this rule set. ("VIACODEREF")
std::vector<SPACINGCODE> SpacingCodes; ///< Overrides these spacing rules in the specific
///< area.
std::map<SPACINGCODE_ID, SPACINGCODE>
SpacingCodes; ///< Overrides these spacing rules in the specific
///< area.
void Parse( XNODE* aNode );
};
struct CODEDEFS
{
std::map<LINECODE_ID, LINECODE> LineCodes;
std::map<HATCHCODE_ID, HATCHCODE> HatchCodes;
std::map<TEXTCODE_ID, TEXTCODE> TextCodes;
std::map<ROUTECODE_ID, ROUTECODE> RouteCodes;
std::map<COPPERCODE_ID, COPPERCODE> CopperCodes;
std::vector<SPACINGCODE> SpacingCodes; ///< Spacing Design Rules
std::map<RULESET_ID, RULESET> Rulesets; ///< Used for area design rules
std::map<PADCODE_ID, PADCODE> PadCodes;
std::map<VIACODE_ID, VIACODE> ViaCodes;
std::map<LINECODE_ID, LINECODE> LineCodes;
std::map<HATCHCODE_ID, HATCHCODE> HatchCodes;
std::map<TEXTCODE_ID, TEXTCODE> TextCodes;
std::map<ROUTECODE_ID, ROUTECODE> RouteCodes;
std::map<COPPERCODE_ID, COPPERCODE> CopperCodes;
std::map<SPACINGCODE_ID, SPACINGCODE> SpacingCodes; ///< Spacing Design Rules
std::map<RULESET_ID, RULESET> Rulesets; ///< Used for area design rules
std::map<PADCODE_ID, PADCODE> PadCodes;
std::map<VIACODE_ID, VIACODE> ViaCodes;
std::map<LAYERPAIR_ID, LAYERPAIR>
LayerPairs; ///< Default vias to use between pairs of layers
@ -790,10 +825,10 @@ public:
long TrackGrid; ///< Grid for Routes (equal X and Y steps)
long ViaGrid; ///< Grid for Vias (equal X and Y steps)
POINT DesignOrigin;
LONGPOINT DesignOrigin;
std::pair<POINT, POINT> DesignArea;
POINT DesignRef; ///< Appears to be 0,0 always
POINT DesignLimit;
LONGPOINT DesignRef; ///< Appears to be 0,0 always
LONGPOINT DesignLimit;
bool BackOffJunctions = false;
bool BackOffWidthChange = false;
@ -1064,9 +1099,9 @@ public:
{
// The default alignment for TEXT_LOCATION (when "NO_ALIGNMENT" is selected) is
// Bottom left, matching CADSTAR's default behaviour
Alignment= ALIGNMENT::BOTTOMLEFT;
Alignment = ALIGNMENT::BOTTOMLEFT;
}
ATTRIBUTE_ID AttributeID;
ATTRIBUTE_ID AttributeID;
void Parse( XNODE* aNode );
};
@ -1850,13 +1885,20 @@ public:
///< aperture etc ...) used on a plotting machine"
///< (param1)
long ClearanceWidth; ///< (param2)
long SliverWidth; ///< (param3)
long AdditionalIsolation; ///< (param4)
long ThermalReliefPadsAngle; ///< Disabled when !ThermalReliefOnPads (param5)
long ClearanceWidth; ///< Specifies the space around pads when pouring
///< (i.e. Thermal relief clearance)
long SliverWidth; ///< Minimum width of copper that may be created
long AdditionalIsolation; ///< This is the gap to apply in routes and pads
///< in addition to the existing pad-to-copper or
///< route-to-copper spacing (see SPACINGCODE.ID)
long ThermalReliefPadsAngle; ///< Orientation for the thermal reliefs. Disabled when !ThermalReliefOnPads (param5)
long ThermalReliefViasAngle; ///< Disabled when !ThermalReliefOnVias (param6)
long MinIsolatedCopper = UNDEFINED_VALUE; ///< Disabled when UNDEFINED_VALUE (param7)
long MinDisjointCopper = UNDEFINED_VALUE; ///< Disabled when UNDEFINED_VALUE (param8)
long MinIsolatedCopper = UNDEFINED_VALUE; ///< The value is the length of one side of
///< a notional square. Disabled when
///< UNDEFINED_VALUE
long MinDisjointCopper = UNDEFINED_VALUE; ///< The value is the length of one side of
///< a notional square. Disabled when
///< UNDEFINED_VALUE
bool ThermalReliefOnPads = true; ///< false when subnode "NOPINRELIEF" is present
bool ThermalReliefOnVias = true; ///< false when subnode "NOVIARELIEF" is present

View File

@ -27,6 +27,7 @@
#include <cadstar_pcb_archive_loader.h>
#include <cadstar_pcb_archive_plugin.h>
#include <class_board.h>
#include <properties.h>
CADSTAR_PCB_ARCHIVE_PLUGIN::CADSTAR_PCB_ARCHIVE_PLUGIN()
@ -62,5 +63,26 @@ BOARD* CADSTAR_PCB_ARCHIVE_PLUGIN::Load(
CADSTAR_PCB_ARCHIVE_LOADER tempPCB( aFileName );
tempPCB.Load( m_board );
//center the board:
if( aProperties )
{
UTF8 page_width;
UTF8 page_height;
if( aProperties->Value( "page_width", &page_width )
&& aProperties->Value( "page_height", &page_height ) )
{
EDA_RECT bbbox = m_board->GetBoardEdgesBoundingBox();
int w = atoi( page_width.c_str() );
int h = atoi( page_height.c_str() );
int desired_x = ( w - bbbox.GetWidth() ) / 2;
int desired_y = ( h - bbbox.GetHeight() ) / 2;
m_board->Move( wxPoint( desired_x - bbbox.GetX(), desired_y - bbbox.GetY() ) );
}
}
return m_board;
}