1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2020-2021 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com>
5  * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 /**
22  * @file cadstar_sch_archive_loader.h
23  * @brief Loads a csa file into a KiCad SCHEMATIC object
24  */
25 
26 #ifndef CADSTAR_SCH_ARCHIVE_LOADER_H_
27 #define CADSTAR_SCH_ARCHIVE_LOADER_H_
28 
29 #include <sch_plugins/cadstar/cadstar_sch_archive_parser.h>
30 
31 #include <layer_ids.h>          // SCH_LAYER_ID
32 #include <plotters/plotter.h>   // PLOT_DASH_TYPE
33 #include <pin_type.h>           // ELECTRICAL_PINTYPE
34 #include <sch_io_mgr.h>
35 #include <wx/filename.h>
36 
37 class BUS_ALIAS;
38 class EDA_TEXT;
39 class LABEL_SPIN_STYLE;
40 class LIB_FIELD;
41 class LIB_SYMBOL;
42 class SCH_SYMBOL;
43 class SCH_ITEM;
44 class SCH_FIELD;
45 class SCH_GLOBALLABEL;
46 class SCH_HIERLABEL;
47 class SCH_SHEET;
48 class SCH_SHEET_PATH;
49 class SCH_TEXT;
50 class SCHEMATIC;
51 
52 class CADSTAR_SCH_ARCHIVE_LOADER : public CADSTAR_SCH_ARCHIVE_PARSER
53 {
54 public:
55     // Size of tiny net labels when none present in original design
56     const int SMALL_LABEL_SIZE = KiROUND( (double) SCH_IU_PER_MM * 0.4 );
57 
CADSTAR_SCH_ARCHIVE_LOADER(wxString aFilename,REPORTER * aReporter,PROGRESS_REPORTER * aProgressReporter)58     explicit CADSTAR_SCH_ARCHIVE_LOADER( wxString aFilename, REPORTER* aReporter,
59                                          PROGRESS_REPORTER* aProgressReporter ) :
60             CADSTAR_SCH_ARCHIVE_PARSER( aFilename )
61     {
62         m_schematic = nullptr;
63         m_rootSheet = nullptr;
64         m_plugin = nullptr;
65         m_designCenter.x = 0;
66         m_designCenter.y = 0;
67         m_reporter = aReporter;
68         m_progressReporter = aProgressReporter;
69     }
70 
71 
~CADSTAR_SCH_ARCHIVE_LOADER()72     ~CADSTAR_SCH_ARCHIVE_LOADER()
73     {
74     }
75 
76     /**
77      * @brief Loads a CADSTAR PCB Archive file into the KiCad BOARD object given
78      * @param aSchematic Schematic to add the design onto
79      * @param aRootSheet Root sheet to add the design onto
80      */
81     void Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet,
82             SCH_PLUGIN::SCH_PLUGIN_RELEASER* aSchPlugin, const wxFileName& aLibraryFileName );
83 
84 
85 private:
86     typedef std::pair<BLOCK_ID, TERMINAL_ID> BLOCK_PIN_ID;
87     typedef std::pair<PART_ID, GATE_ID> PART_GATE_ID;
88 
89     /**
90      * Map between a terminal ID in a symbol definition to the pin number that should
91      * be imported into KiCad.
92      */
93     typedef std::map<TERMINAL_ID, wxString>  TERMINAL_TO_PINNUM_MAP;
94 
95     REPORTER*                        m_reporter;
96     SCHEMATIC*                       m_schematic;
97     SCH_SHEET*                       m_rootSheet;
98     SCH_PLUGIN::SCH_PLUGIN_RELEASER* m_plugin;
99     wxFileName                       m_libraryFileName;
100     wxPoint                          m_designCenter; ///< Used for calculating the required
101                                                      ///< offset to apply to the Cadstar design
102                                                      ///< so that it fits in KiCad canvas
103     std::map<LAYER_ID, SCH_SHEET*> m_sheetMap;       ///< Map between Cadstar and KiCad Sheets
104     std::map<BLOCK_PIN_ID, SCH_HIERLABEL*>
105                                  m_sheetPinMap; ///< Map between Cadstar and KiCad Sheets Pins
106     std::map<PART_ID, LIB_SYMBOL*> m_partMap;     ///< Map between Cadstar and KiCad Parts
107     std::map<PART_GATE_ID, SYMDEF_ID> m_partSymbolsMap; ///< Map holding the symbols loaded so far
108                                                         ///  for a particular PART_ID and GATE_ID
109     std::map<PART_ID, TERMINAL_TO_PINNUM_MAP> m_pinNumsMap; ///< Map of pin numbers in CADSTAR parts
110     std::map<wxString, LIB_SYMBOL*> m_powerSymLibMap; ///< Map of KiCad Power Symbol Library items
111     std::map<SYMBOL_ID, SCH_SYMBOL*>
112             m_powerSymMap; ///< Map between Cadstar and KiCad Power Symbols
113     std::map<SYMBOL_ID, SCH_GLOBALLABEL*>
114             m_globalLabelsMap; ///< Map between Cadstar and KiCad Global Labels
115     std::map<BUS_ID, std::shared_ptr<BUS_ALIAS>> m_busesMap; ///< Map of Cadstar and KiCad Buses
116 
117     void loadSheets();
118     void loadHierarchicalSheetPins();
119     void loadPartsLibrary();
120     void loadSchematicSymbolInstances();
121     void loadBusses();
122     void loadNets();
123     void loadFigures();
124     void loadTexts();
125     void loadDocumentationSymbols();
126     void loadTextVariables();
127 
128     //Helper Functions for loading sheets
129     void loadSheetAndChildSheets( LAYER_ID aCadstarSheetID, const wxPoint& aPosition,
130                                   wxSize aSheetSize, const SCH_SHEET_PATH& aParentSheet );
131 
132     void loadChildSheets( LAYER_ID aCadstarSheetID, const SCH_SHEET_PATH& aSheet );
133 
134     std::vector<LAYER_ID> findOrphanSheets();
135 
136     int getSheetNumber( LAYER_ID aCadstarSheetID );
137 
138     void loadItemOntoKiCadSheet( LAYER_ID aCadstarSheetID, SCH_ITEM* aItem );
139 
140     //Helper Functions for loading library items
141     void loadSymDefIntoLibrary( const SYMDEF_ID& aSymdefID, const PART* aCadstarPart,
142             const GATE_ID& aGateID, LIB_SYMBOL* aSymbol );
143 
144     void loadLibrarySymbolShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
145                                          wxPoint aSymbolOrigin, LIB_SYMBOL* aSymbol,
146                                          int aGateNumber, int aLineThickness );
147 
148     void applyToLibraryFieldAttribute( const ATTRIBUTE_LOCATION& aCadstarAttrLoc,
149             wxPoint aSymbolOrigin, LIB_FIELD* aKiCadField );
150 
151     //Helper Functions for loading symbols in schematic
152     SCH_SYMBOL* loadSchematicSymbol( const SYMBOL& aCadstarSymbol, const LIB_SYMBOL& aKiCadPart,
153             double& aComponentOrientationDeciDeg );
154 
155     void loadSymbolFieldAttribute( const ATTRIBUTE_LOCATION& aCadstarAttrLoc,
156                                    const double& aComponentOrientationDeciDeg, bool aIsMirrored,
157                                    SCH_FIELD* aKiCadField );
158 
159     int getComponentOrientation( double aOrientAngleDeciDeg, double& aReturnedOrientationDeciDeg );
160 
161     //Helper functions for loading nets
162     POINT getLocationOfNetElement( const NET_SCH& aNet, const NETELEMENT_ID& aNetElementID );
163 
164     wxString getNetName( const NET_SCH& aNet );
165 
166     //Helper functions for loading figures / graphical items
167     void loadGraphicStaightSegment( const wxPoint& aStartPoint, const wxPoint& aEndPoint,
168             const LINECODE_ID& aCadstarLineCodeID, const LAYER_ID& aCadstarSheetID,
169             const SCH_LAYER_ID& aKiCadSchLayerID, const wxPoint& aMoveVector = { 0, 0 },
170             const double& aRotationAngleDeciDeg = 0.0, const double& aScalingFactor = 1.0,
171             const wxPoint& aTransformCentre = { 0, 0 }, const bool& aMirrorInvert = false );
172 
173     void loadShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
174             LINECODE_ID aCadstarLineCodeID, LAYER_ID aCadstarSheetID, SCH_LAYER_ID aKiCadSchLayerID,
175             const wxPoint& aMoveVector = { 0, 0 }, const double& aRotationAngleDeciDeg = 0.0,
176             const double& aScalingFactor = 1.0, const wxPoint& aTransformCentre = { 0, 0 },
177             const bool& aMirrorInvert = false );
178 
179     void loadFigure( const FIGURE& aCadstarFigure, const LAYER_ID& aCadstarSheetIDOverride,
180             SCH_LAYER_ID aKiCadSchLayerID, const wxPoint& aMoveVector = { 0, 0 },
181             const double& aRotationAngleDeciDeg = 0.0, const double& aScalingFactor = 1.0,
182             const wxPoint& aTransformCentre = { 0, 0 }, const bool& aMirrorInvert = false );
183 
184     //Helper functions for loading text elements
185     void applyTextSettings( EDA_TEXT* aKiCadTextItem,
186                             const TEXTCODE_ID& aCadstarTextCodeID,
187                             const ALIGNMENT&     aCadstarAlignment,
188                             const JUSTIFICATION& aCadstarJustification,
189                             const long long aCadstarOrientAngle = 0,
190                             bool aMirrored = false );
191 
192     SCH_TEXT* getKiCadSchText( const TEXT& aCadstarTextElement );
193 
194 
195     //Helper Functions for obtaining CADSTAR elements from the parsed structures
196     SYMDEF_ID getSymDefFromName( const wxString& aSymdefName, const wxString& aSymDefAlternate );
197     bool      isAttributeVisible( const ATTRIBUTE_ID& aCadstarAttributeID );
198 
199     int            getLineThickness( const LINECODE_ID& aCadstarLineCodeID );
200     PLOT_DASH_TYPE getLineStyle( const LINECODE_ID& aCadstarLineCodeID );
201     PART           getPart( const PART_ID& aCadstarPartID );
202     ROUTECODE      getRouteCode( const ROUTECODE_ID& aCadstarRouteCodeID );
203     TEXTCODE       getTextCode( const TEXTCODE_ID& aCadstarTextCodeID );
204     int            getTextHeightFromTextCode( const TEXTCODE_ID& aCadstarTextCodeID );
205     wxString       getAttributeName( const ATTRIBUTE_ID& aCadstarAttributeID );
206 
207     PART::DEFINITION::PIN getPartDefinitionPin(
208             const PART& aCadstarPart, const GATE_ID& aGateID, const TERMINAL_ID& aTerminalID );
209 
210     //Helper Functions for obtaining individual elements as KiCad elements:
211     ELECTRICAL_PINTYPE getKiCadPinType( const PART::PIN_TYPE& aPinType );
212 
213     int              getKiCadUnitNumberFromGate( const GATE_ID& aCadstarGateID );
214     LABEL_SPIN_STYLE getSpinStyle( const long long& aCadstarOrientation, bool aMirror );
215     LABEL_SPIN_STYLE getSpinStyleDeciDeg( const double& aOrientationDeciDeg );
216     ALIGNMENT        mirrorX( const ALIGNMENT& aCadstarAlignment );
217     ALIGNMENT        rotate180( const ALIGNMENT& aCadstarAlignment );
218 
219     //General Graphical manipulation functions
220 
221     LIB_SYMBOL* getScaledLibPart( const LIB_SYMBOL* aSymbol, long long aScalingFactorNumerator,
222                                   long long aScalingFactorDenominator );
223 
224     void fixUpLibraryPins( LIB_SYMBOL* aSymbolToFix, int aGateNumber );
225 
226     std::pair<wxPoint, wxSize> getFigureExtentsKiCad( const FIGURE& aCadstarFigure );
227 
228     wxPoint getKiCadPoint( const wxPoint& aCadstarPoint );
229 
230     wxPoint getKiCadLibraryPoint( const wxPoint& aCadstarPoint, const wxPoint& aCadstarCentre );
231 
232     wxPoint applyTransform( const wxPoint& aPoint, const wxPoint& aMoveVector = { 0, 0 },
233             const double& aRotationAngleDeciDeg = 0.0, const double& aScalingFactor = 1.0,
234             const wxPoint& aTransformCentre = { 0, 0 }, const bool& aMirrorInvert = false );
235 
getKiCadLength(long long aCadstarLength)236     int getKiCadLength( long long aCadstarLength )
237     {
238         int mod = aCadstarLength % KiCadUnitDivider;
239         int absmod = sign( mod ) * mod;
240         int offset = 0;
241 
242         // Round half-way cases away from zero
243         if( absmod >= KiCadUnitDivider / 2 )
244             offset = sign( aCadstarLength );
245 
246         return ( aCadstarLength / KiCadUnitDivider ) + offset;
247     }
248 
249     /**
250      * @brief
251      * @param aCadstarAngle
252      * @return
253     */
getAngleTenthDegree(const long long & aCadstarAngle)254     double getAngleTenthDegree( const long long& aCadstarAngle )
255     {
256         // CADSTAR v6 (which outputted Schematic Format Version 8) and earlier used 1/10 degree
257         // as the unit for angles/orientations. It is assumed that CADSTAR version 7 (i.e. Schematic
258         // Format Version 9 and later) is the version that introduced 1/1000 degree for angles.
259         if( Header.Format.Version > 8 )
260         {
261             return (double) aCadstarAngle / 100.0;
262         }
263         else
264         {
265             return (double) aCadstarAngle;
266         }
267     }
268 
269     /**
270      * @brief
271      * @param aCadstarAngle
272      * @return
273      */
getAngleDegrees(const long long & aCadstarAngle)274     double getAngleDegrees( const long long& aCadstarAngle )
275     {
276         return getAngleTenthDegree( aCadstarAngle ) / 10.0;
277     }
278 
279 
getCadstarAngle(const double & aAngleTenthDegree)280     long long getCadstarAngle( const double& aAngleTenthDegree )
281     {
282         return KiROUND( ( aAngleTenthDegree / getAngleTenthDegree( aAngleTenthDegree ) )
283                         * aAngleTenthDegree );
284     }
285 
286     /**
287      * @brief
288      * @param aPoint
289      * @return Angle in decidegrees of the polar representation of the point, scaled 0..360
290      */
291     double getPolarAngle( const wxPoint& aPoint );
292 
293     /**
294      * @brief
295      * @param aPoint
296      * @return Radius of polar representation of the point
297      */
298     double getPolarRadius( const wxPoint& aPoint );
299 
300 }; // CADSTAR_SCH_ARCHIVE_LOADER
301 
302 
303 #endif // CADSTAR_SCH_ARCHIVE_LOADER_H_
304