1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2019-2020 Reece R. Pollack <reece@his.com>
5  * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
23  */
24 
25 #ifndef ORIGIN_TRANSFORMS_H_
26 #define ORIGIN_TRANSFORMS_H_
27 
28 /**
29  * A class to perform either relative or absolute display origin
30  * transforms for a single axis of a point.
31  *
32  * The coordinate argument is transformed between an offset from
33  * the internal origin and an offset from the user-specified origin
34  * and coordinate direction.
35  *
36  * The functions are templated to allow use with any size scalar
37  * parameter: an int, a long long int, or a double.
38  */
39 class ORIGIN_TRANSFORMS
40 {
41 public:
42     /**
43      * The supported Display Origin Transform types
44      *
45      * Absolute coordinates require both translation and direction
46      * inversion. Relative coordinates require only direction inversion.
47      */
48     enum COORD_TYPES_T {
49         NOT_A_COORD,    //< A non-coordinate value, never transformed
50         ABS_X_COORD,    //< An absolute X coordinate
51         ABS_Y_COORD,    //< An absolute Y coordinate
52         REL_X_COORD,    //< A relative X coordinate
53         REL_Y_COORD,    //< A relative Y coordinate
54     };
55 
56     ORIGIN_TRANSFORMS();
57 
58     virtual ~ORIGIN_TRANSFORMS();
59 
60     virtual int ToDisplay( int           aValue,
61                            COORD_TYPES_T aCoordType ) const;
62 
63     virtual long long int ToDisplay( long long int aValue,
64                                      COORD_TYPES_T aCoordType ) const;
65 
66     virtual double ToDisplay( double        aValue,
67                               COORD_TYPES_T aCoordType ) const;
68 
69     virtual int FromDisplay( int           aValue,
70                              COORD_TYPES_T aCoordType ) const;
71 
72     virtual long long int FromDisplay( long long int aValue,
73                                        COORD_TYPES_T aCoordType ) const;
74 
75     virtual double FromDisplay( double        aValue,
76                                 COORD_TYPES_T aCoordType ) const;
77 
78 
79     template<class T>
ToDisplayAbs(const T & aValue)80     T ToDisplayAbs( const T& aValue ) const
81     {
82         T displayValue;
83 
84         displayValue.x = ToDisplay( aValue.x, ABS_X_COORD );
85         displayValue.y = ToDisplay( aValue.y, ABS_Y_COORD );
86         return displayValue;
87     }
88 
89     template<class T>
ToDisplayRel(const T & aValue)90     T ToDisplayRel( const T& aValue ) const
91     {
92         T displayValue;
93 
94         displayValue.x = ToDisplay( aValue.x, REL_X_COORD );
95         displayValue.y = ToDisplay( aValue.y, REL_Y_COORD );
96         return displayValue;
97     }
98 
99 
100     template<class T>
FromDisplayAbs(const T & aValue)101     T FromDisplayAbs( const T& aValue ) const
102     {
103         T displayValue;
104 
105         displayValue.x = FromDisplay( aValue.x, ABS_X_COORD );
106         displayValue.y = FromDisplay( aValue.y, ABS_Y_COORD );
107         return displayValue;
108     }
109 
110     template<class T>
FromDisplayRel(const T & aValue)111     T FromDisplayRel( const T& aValue ) const
112     {
113         T displayValue;
114 
115         displayValue.x = FromDisplay( aValue.x, REL_X_COORD );
116         displayValue.y = FromDisplay( aValue.y, REL_Y_COORD );
117         return displayValue;
118     }
119 
120 
121 protected:
122     template<class T> inline static
ToDisplayRel(T aInternalValue,bool aInvertAxis)123     T ToDisplayRel( T    aInternalValue,
124                     bool aInvertAxis )
125     {
126         T displayValue = aInternalValue;
127 
128        // Invert the direction if needed
129         if( aInvertAxis && (displayValue != static_cast<T>(0)) )
130             displayValue = -displayValue;
131 
132         return displayValue;
133     }
134 
135 
136     template<class T> inline static
FromDisplayRel(T aDisplayValue,bool aInvertAxis)137     T FromDisplayRel( T    aDisplayValue,
138                       bool aInvertAxis )
139     {
140         T internalValue = aDisplayValue;
141 
142        // Invert the direction if needed
143         if( aInvertAxis && (internalValue != static_cast<T>(0)) )
144             internalValue = -internalValue;
145 
146         return internalValue;
147     }
148 
149     template<class T> inline static
ToDisplayAbs(T aInternalValue,int aUserOrigin,bool aInvertAxis)150     T ToDisplayAbs( T    aInternalValue,
151                     int  aUserOrigin,
152                     bool aInvertAxis )
153     {
154         T displayValue = aInternalValue;
155 
156         // Make the value relative to the internal origin
157         displayValue -= aUserOrigin;
158 
159         // Invert the direction if needed
160         if( aInvertAxis && (displayValue != static_cast<T>(0)) )
161             displayValue = -displayValue;
162 
163         return displayValue;
164     }
165 
166     template<class T> inline static
FromDisplayAbs(T aDisplayValue,int aUserOrigin,bool aInvertAxis)167     T FromDisplayAbs( T    aDisplayValue,
168                       int  aUserOrigin,
169                       bool aInvertAxis )
170     {
171         T internalValue = aDisplayValue;
172 
173         // Invert the direction if needed
174         if( aInvertAxis && (internalValue != static_cast<T>(0)) )
175             internalValue = -internalValue;
176 
177         // Make the value relative to the internal origin
178         internalValue += aUserOrigin;
179 
180         return internalValue;
181     }
182 };
183 
184 #endif // ORIGIN_TRANSFORMS_H
185