348 lines
14 KiB
C++
348 lines
14 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2020-2021 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com>
|
|
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation, either version 3 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* @file cadstar_sch_archive_loader.h
|
|
* @brief Loads a csa file into a KiCad SCHEMATIC object
|
|
*/
|
|
|
|
#ifndef CADSTAR_SCH_ARCHIVE_LOADER_H_
|
|
#define CADSTAR_SCH_ARCHIVE_LOADER_H_
|
|
|
|
#include <sch_io/cadstar/cadstar_sch_archive_parser.h>
|
|
|
|
#include <layer_ids.h> // SCH_LAYER_ID
|
|
#include <plotters/plotter.h> // LINE_STYLE
|
|
#include <pin_type.h> // ELECTRICAL_PINTYPE
|
|
|
|
#include <memory>
|
|
#include <map>
|
|
|
|
#include <wx/filename.h>
|
|
#include <wx/string.h>
|
|
|
|
struct CADSTAR_PART_ENTRY;
|
|
class BUS_ALIAS;
|
|
class EDA_TEXT;
|
|
class SPIN_STYLE;
|
|
class LIB_SYMBOL;
|
|
class REPORTER;
|
|
class SCH_SYMBOL;
|
|
class SCH_ITEM;
|
|
class SCH_FIELD;
|
|
class SCH_GLOBALLABEL;
|
|
class SCH_HIERLABEL;
|
|
class SCH_SHEET;
|
|
class SCH_SHEET_PATH;
|
|
class SCH_TEXT;
|
|
class SCHEMATIC;
|
|
|
|
class CADSTAR_SCH_ARCHIVE_LOADER : public CADSTAR_SCH_ARCHIVE_PARSER
|
|
{
|
|
public:
|
|
// Size of tiny net labels when none present in original design
|
|
const int SMALL_LABEL_SIZE = KiROUND( (double) SCH_IU_PER_MM * 0.4 );
|
|
const double ARC_ACCURACY = SCH_IU_PER_MM * 0.01; // 0.01mm
|
|
|
|
explicit CADSTAR_SCH_ARCHIVE_LOADER( wxString aFilename, REPORTER* aReporter,
|
|
PROGRESS_REPORTER* aProgressReporter ) :
|
|
CADSTAR_SCH_ARCHIVE_PARSER( aFilename )
|
|
{
|
|
m_schematic = nullptr;
|
|
m_rootSheet = nullptr;
|
|
m_designCenter.x = 0;
|
|
m_designCenter.y = 0;
|
|
m_reporter = aReporter;
|
|
m_progressReporter = aProgressReporter;
|
|
|
|
// Assume that the PCB footprint library name will be the same as the schematic filename
|
|
wxFileName schFilename( Filename );
|
|
m_footprintLibName = schFilename.GetName();
|
|
}
|
|
|
|
|
|
~CADSTAR_SCH_ARCHIVE_LOADER()
|
|
{
|
|
}
|
|
|
|
std::vector<LIB_SYMBOL*> LoadPartsLib( const wxString& aFilename );
|
|
|
|
const std::vector<LIB_SYMBOL*>& GetLoadedSymbols() const { return m_loadedSymbols; }
|
|
|
|
void SetFpLibName( const wxString& aLibName ) { m_footprintLibName = aLibName; };
|
|
|
|
|
|
/**
|
|
* @brief Loads a CADSTAR Schematic Archive file into the KiCad SCHEMATIC object given
|
|
* @param aSchematic Schematic to add the design onto
|
|
* @param aRootSheet Root sheet to add the design onto
|
|
*/
|
|
void Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet );
|
|
|
|
|
|
private:
|
|
typedef std::pair<BLOCK_ID, TERMINAL_ID> BLOCK_PIN_ID;
|
|
typedef std::pair<PART_ID, GATE_ID> PART_GATE_ID;
|
|
|
|
/**
|
|
* Map between a terminal ID in a symbol definition to the pin number that should
|
|
* be imported into KiCad.
|
|
*/
|
|
typedef std::map<TERMINAL_ID, wxString> TERMINAL_TO_PINNUM_MAP;
|
|
|
|
typedef std::map<wxString, TERMINAL_ID> PINNUM_TO_TERMINAL_MAP;
|
|
|
|
REPORTER* m_reporter;
|
|
SCHEMATIC* m_schematic;
|
|
SCH_SHEET* m_rootSheet;
|
|
wxString m_footprintLibName; ///< Name of the footprint library to prepend all footprints with
|
|
|
|
/**
|
|
* Required for calculating the offset to apply to the Cadstar design so that it fits
|
|
* in the KiCad canvas
|
|
*/
|
|
VECTOR2I m_designCenter;
|
|
|
|
std::map<LAYER_ID, SCH_SHEET*> m_sheetMap; ///< Cadstar->KiCad Sheets
|
|
std::map<BLOCK_PIN_ID, SCH_HIERLABEL*> m_sheetPinMap; ///< Cadstar->KiCad Sheet Pins
|
|
std::map<PART_ID, LIB_SYMBOL*> m_partMap; ///< Cadstar->KiCad Parts
|
|
std::map<SYMBOL_ID, SCH_SYMBOL*> m_powerSymMap; ///< Cadstar->KiCad Power Symbols
|
|
std::map<wxString, LIB_SYMBOL*> m_powerSymLibMap; ///< NetName->KiCad Power Lib Symbol
|
|
std::map<SYMBOL_ID, SCH_GLOBALLABEL*> m_globalLabelsMap; ///< Cadstar->KiCad Global Labels
|
|
std::map<BUS_ID, std::shared_ptr<BUS_ALIAS>> m_busesMap; ///< Cadstar->KiCad Buses
|
|
std::map<PART_ID, TERMINAL_TO_PINNUM_MAP> m_pinNumsMap; ///< Cadstar Part->KiCad Pin number map
|
|
std::map<SYMDEF_ID, PINNUM_TO_TERMINAL_MAP> m_symDefTerminalsMap;
|
|
|
|
/**
|
|
* Cache storing symbol names and alternates to symdef IDs
|
|
*/
|
|
std::map<std::pair<wxString, wxString>, SYMDEF_ID> m_SymDefNamesCache;
|
|
|
|
/**
|
|
* Cache storing symbol names (default alternate) to symdef IDs
|
|
*/
|
|
std::map<wxString, SYMDEF_ID> m_DefaultSymDefNamesCache;
|
|
|
|
/**
|
|
* Cadstar->KiCad Lib Symbols loaded so far. Note that in CADSTAR each symbol represents just a
|
|
* gate, so the LIB_SYMBOLs contained here are not imported directly - they are just an interim
|
|
* step.
|
|
*/
|
|
std::map<SYMDEF_ID, std::unique_ptr<const LIB_SYMBOL>> m_symDefMap;
|
|
|
|
std::vector<LIB_SYMBOL*> m_loadedSymbols; ///< Loaded symbols so far
|
|
std::map<PART_GATE_ID, SYMDEF_ID> m_partSymbolsMap; ///< Map holding the symbols loaded so far
|
|
/// for a particular PART_ID and GATE_ID
|
|
|
|
void loadSheets();
|
|
void loadHierarchicalSheetPins();
|
|
void loadPartsLibrary();
|
|
void loadSchematicSymbolInstances();
|
|
void loadBusses();
|
|
void loadNets();
|
|
void loadFigures();
|
|
void loadTexts();
|
|
void loadDocumentationSymbols();
|
|
void loadTextVariables();
|
|
|
|
std::unique_ptr<LIB_SYMBOL> loadLibPart( const CADSTAR_PART_ENTRY& aPart );
|
|
|
|
void copySymbolItems( std::unique_ptr<LIB_SYMBOL>& aSourceSym,
|
|
std::unique_ptr<LIB_SYMBOL>& aDestSym, int aDestUnit,
|
|
bool aOverrideFields = true );
|
|
|
|
//Helper Functions for loading sheets
|
|
void loadSheetAndChildSheets( LAYER_ID aCadstarSheetID, const VECTOR2I& aPosition,
|
|
VECTOR2I aSheetSize, const SCH_SHEET_PATH& aParentSheet );
|
|
|
|
void loadChildSheets( LAYER_ID aCadstarSheetID, const SCH_SHEET_PATH& aSheet );
|
|
|
|
std::vector<LAYER_ID> findOrphanSheets();
|
|
|
|
int getSheetNumber( LAYER_ID aCadstarSheetID );
|
|
|
|
void loadItemOntoKiCadSheet( LAYER_ID aCadstarSheetID, SCH_ITEM* aItem );
|
|
|
|
//Helper Functions for loading library items
|
|
const LIB_SYMBOL* loadSymdef( const SYMDEF_ID& aSymdefID );
|
|
|
|
void loadSymbolGateAndPartFields( const SYMDEF_ID& aSymdefID, const PART& aCadstarPart,
|
|
const GATE_ID& aGateID, LIB_SYMBOL* aSymbol );
|
|
|
|
void setFootprintOnSymbol( std::unique_ptr<LIB_SYMBOL>& aKiCadSymbol,
|
|
const wxString& aFootprintName,
|
|
const wxString& aFootprintAlternate );
|
|
|
|
void loadLibrarySymbolShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
|
|
const VECTOR2I& aSymbolOrigin, LIB_SYMBOL* aSymbol,
|
|
int aGateNumber, int aLineThickness );
|
|
|
|
void applyToLibraryFieldAttribute( const ATTRIBUTE_LOCATION& aCadstarAttrLoc,
|
|
const VECTOR2I& aSymbolOrigin, SCH_FIELD* aKiCadField );
|
|
|
|
//Helper Functions for loading symbols in schematic
|
|
SCH_SYMBOL* loadSchematicSymbol( const SYMBOL& aCadstarSymbol, const LIB_SYMBOL& aKiCadPart,
|
|
EDA_ANGLE& aComponentOrientation );
|
|
|
|
|
|
void loadSymbolFieldAttribute( const ATTRIBUTE_LOCATION& aCadstarAttrLoc,
|
|
const EDA_ANGLE& aComponentOrientation, bool aIsMirrored,
|
|
SCH_FIELD* aKiCadField );
|
|
|
|
int getComponentOrientation( const EDA_ANGLE& aOrientAngle, EDA_ANGLE& aReturnedOrientation );
|
|
|
|
//Helper functions for loading nets
|
|
POINT getLocationOfNetElement( const NET_SCH& aNet, const NETELEMENT_ID& aNetElementID );
|
|
|
|
wxString getNetName( const NET_SCH& aNet );
|
|
|
|
//Helper functions for loading figures / graphical items
|
|
void loadShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
|
|
LINECODE_ID aCadstarLineCodeID, LAYER_ID aCadstarSheetID,
|
|
SCH_LAYER_ID aKiCadSchLayerID, const VECTOR2I& aMoveVector = { 0, 0 },
|
|
const EDA_ANGLE& aRotation = ANGLE_0,
|
|
const double& aScalingFactor = 1.0,
|
|
const VECTOR2I& aTransformCentre = { 0, 0 },
|
|
const bool& aMirrorInvert = false );
|
|
|
|
void loadFigure( const FIGURE& aCadstarFigure, const LAYER_ID& aCadstarSheetIDOverride,
|
|
SCH_LAYER_ID aKiCadSchLayerID, const VECTOR2I& aMoveVector = { 0, 0 },
|
|
const EDA_ANGLE& aRotation = ANGLE_0, const double& aScalingFactor = 1.0,
|
|
const VECTOR2I& aTransformCentre = { 0, 0 },
|
|
const bool& aMirrorInvert = false );
|
|
|
|
//Helper functions for loading text elements
|
|
void applyTextCodeIfExists( EDA_TEXT* aKiCadTextItem, const TEXTCODE_ID& aCadstarTextCodeID );
|
|
|
|
void applyTextSettings( EDA_TEXT* aKiCadTextItem,
|
|
const TEXTCODE_ID& aCadstarTextCodeID,
|
|
const ALIGNMENT& aCadstarAlignment,
|
|
const JUSTIFICATION& aCadstarJustification,
|
|
const long long aCadstarOrientAngle = 0,
|
|
bool aMirrored = false,
|
|
bool aInvertY = false );
|
|
|
|
SCH_TEXT* getKiCadSchText( const TEXT& aCadstarTextElement );
|
|
|
|
|
|
//Helper Functions for obtaining CADSTAR elements from the parsed structures
|
|
SYMDEF_ID getSymDefFromName( const wxString& aSymdefName, const wxString& aSymDefAlternate );
|
|
bool isAttributeVisible( const ATTRIBUTE_ID& aCadstarAttributeID );
|
|
|
|
int getLineThickness( const LINECODE_ID& aCadstarLineCodeID );
|
|
LINE_STYLE getLineStyle( const LINECODE_ID& aCadstarLineCodeID );
|
|
PART getPart( const PART_ID& aCadstarPartID );
|
|
ROUTECODE getRouteCode( const ROUTECODE_ID& aCadstarRouteCodeID );
|
|
TEXTCODE getTextCode( const TEXTCODE_ID& aCadstarTextCodeID );
|
|
int getTextHeightFromTextCode( const TEXTCODE_ID& aCadstarTextCodeID );
|
|
wxString getAttributeName( const ATTRIBUTE_ID& aCadstarAttributeID );
|
|
|
|
PART::DEFINITION::PIN getPartDefinitionPin( const PART& aCadstarPart, const GATE_ID& aGateID,
|
|
const TERMINAL_ID& aTerminalID );
|
|
|
|
//Helper Functions for obtaining individual elements as KiCad elements:
|
|
ELECTRICAL_PINTYPE getKiCadPinType( const CADSTAR_PIN_TYPE& aPinType );
|
|
|
|
int getKiCadUnitNumberFromGate( const GATE_ID& aCadstarGateID );
|
|
SPIN_STYLE getSpinStyle( const long long& aCadstarOrientation, bool aMirror );
|
|
SPIN_STYLE getSpinStyle( const EDA_ANGLE& aOrientation );
|
|
ALIGNMENT mirrorX( const ALIGNMENT& aCadstarAlignment );
|
|
ALIGNMENT rotate180( const ALIGNMENT& aCadstarAlignment );
|
|
|
|
//General Graphical manipulation functions
|
|
|
|
LIB_SYMBOL* getScaledLibPart( const LIB_SYMBOL* aSymbol, long long aScalingFactorNumerator,
|
|
long long aScalingFactorDenominator );
|
|
|
|
void fixUpLibraryPins( LIB_SYMBOL* aSymbolToFix, int aGateNumber );
|
|
|
|
std::pair<VECTOR2I, VECTOR2I> getFigureExtentsKiCad( const FIGURE& aCadstarFigure );
|
|
|
|
VECTOR2I getKiCadPoint( const VECTOR2I& aCadstarPoint );
|
|
|
|
VECTOR2I getKiCadLibraryPoint( const VECTOR2I& aCadstarPoint, const VECTOR2I& aCadstarCentre );
|
|
|
|
VECTOR2I applyTransform( const VECTOR2I& aPoint, const VECTOR2I& aMoveVector = { 0, 0 },
|
|
const EDA_ANGLE& aRotation = ANGLE_0,
|
|
const double& aScalingFactor = 1.0,
|
|
const VECTOR2I& aTransformCentre = { 0, 0 },
|
|
const bool& aMirrorInvert = false );
|
|
|
|
void checkDesignLimits();
|
|
|
|
int getKiCadLength( long long aCadstarLength )
|
|
{
|
|
int mod = aCadstarLength % KiCadUnitDivider;
|
|
int absmod = sign( mod ) * mod;
|
|
int offset = 0;
|
|
|
|
// Round half-way cases away from zero
|
|
if( absmod >= KiCadUnitDivider / 2 )
|
|
offset = sign( aCadstarLength );
|
|
|
|
return ( aCadstarLength / KiCadUnitDivider ) + offset;
|
|
}
|
|
|
|
EDA_ANGLE getAngle( const long long& aCadstarAngle )
|
|
{
|
|
// CADSTAR v6 (which outputted Schematic Format Version 8) and earlier used 1/10 degree
|
|
// as the unit for angles/orientations. It is assumed that CADSTAR version 7 (i.e. Schematic
|
|
// Format Version 9 and later) is the version that introduced 1/1000 degree for angles.
|
|
if( Header.Format.Version > 8 )
|
|
{
|
|
return EDA_ANGLE( (double) aCadstarAngle / 1000.0, DEGREES_T );
|
|
}
|
|
else
|
|
{
|
|
return EDA_ANGLE( (double) aCadstarAngle, TENTHS_OF_A_DEGREE_T );
|
|
}
|
|
}
|
|
|
|
long long getCadstarAngle( const EDA_ANGLE& aAngle )
|
|
{
|
|
// CADSTAR v6 (which outputted Schematic Format Version 8) and earlier used 1/10 degree
|
|
// as the unit for angles/orientations. It is assumed that CADSTAR version 7 (i.e. Schematic
|
|
// Format Version 9 and later) is the version that introduced 1/1000 degree for angles.
|
|
if( Header.Format.Version > 8 )
|
|
{
|
|
return KiROUND( aAngle.AsDegrees() * 1000.0 );
|
|
}
|
|
else
|
|
{
|
|
return aAngle.AsTenthsOfADegree();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief
|
|
* @param aPoint
|
|
* @return Radius of polar representation of the point
|
|
*/
|
|
double getPolarRadius( const VECTOR2I& aPoint );
|
|
|
|
|
|
static SCH_FIELD* addNewFieldToSymbol( const wxString& aFieldName,
|
|
std::unique_ptr<LIB_SYMBOL>& aKiCadSymbol );
|
|
|
|
}; // CADSTAR_SCH_ARCHIVE_LOADER
|
|
|
|
|
|
#endif // CADSTAR_SCH_ARCHIVE_LOADER_H_
|