/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2020-2021 Roberto Fernandez Bautista * 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 . */ /** * @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 #include // SCH_LAYER_ID #include // PLOT_DASH_TYPE #include // ELECTRICAL_PINTYPE #include #include #include #include struct CADSTAR_PART_ENTRY; class BUS_ALIAS; class EDA_TEXT; class SPIN_STYLE; class LIB_FIELD; 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 LoadPartsLib( const wxString& aFilename ); const std::vector& 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_PIN_ID; typedef std::pair 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_TO_PINNUM_MAP; typedef std::map 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 m_sheetMap; ///< Cadstar->KiCad Sheets std::map m_sheetPinMap; ///< Cadstar->KiCad Sheet Pins std::map m_partMap; ///< Cadstar->KiCad Parts std::map m_powerSymMap; ///< Cadstar->KiCad Power Symbols std::map m_powerSymLibMap; ///< NetName->KiCad Power Lib Symbol std::map m_globalLabelsMap; ///< Cadstar->KiCad Global Labels std::map> m_busesMap; ///< Cadstar->KiCad Buses std::map m_pinNumsMap; ///< Cadstar Part->KiCad Pin number map std::map m_symDefTerminalsMap; /** * Cache storing symbol names and alternates to symdef IDs */ std::map, SYMDEF_ID> m_SymDefNamesCache; /** * Cache storing symbol names (default alternate) to symdef IDs */ std::map 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> m_symDefMap; std::vector m_loadedSymbols; ///< Loaded symbols so far std::map 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 loadLibPart( const CADSTAR_PART_ENTRY& aPart ); void copySymbolItems( std::unique_ptr& aSourceSym, std::unique_ptr& 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 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& aKiCadSymbol, const wxString& aFootprintName, const wxString& aFootprintAlternate ); void loadLibrarySymbolShapeVertices( const std::vector& aCadstarVertices, VECTOR2I aSymbolOrigin, LIB_SYMBOL* aSymbol, int aGateNumber, int aLineThickness ); void applyToLibraryFieldAttribute( const ATTRIBUTE_LOCATION& aCadstarAttrLoc, VECTOR2I aSymbolOrigin, LIB_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& 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 ); 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 ); PLOT_DASH_TYPE 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 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 LIB_FIELD* addNewFieldToSymbol( const wxString& aFieldName, std::unique_ptr& aKiCadSymbol ); }; // CADSTAR_SCH_ARCHIVE_LOADER #endif // CADSTAR_SCH_ARCHIVE_LOADER_H_