KiCad PCB EDA Suite
Loading...
Searching...
No Matches
eda_angle.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifndef EDA_ANGLE_H
21#define EDA_ANGLE_H
22
23#include <cassert>
24#include <cmath>
25#include <math/vector2d.h> // for VECTOR2I
26
27
29{
33};
34
35
37{
38public:
46 EDA_ANGLE( double aValue, EDA_ANGLE_T aAngleType )
47 {
48 switch( aAngleType )
49 {
50 case RADIANS_T:
51 m_value = aValue / DEGREES_TO_RADIANS;
52 break;
53
55 m_value = aValue / 10.0;
56 break;
57
58 default:
59 m_value = aValue;
60 }
61 }
62
67 constexpr EDA_ANGLE( double aAngleInDegrees ) : m_value(aAngleInDegrees) {}
68
69 explicit EDA_ANGLE( const VECTOR2D& aVector )
70 {
71 if( aVector.x == 0.0 && aVector.y == 0.0 )
72 {
73 m_value = 0.0;
74 }
75 else if( aVector.y == 0.0 )
76 {
77 if( aVector.x >= 0 )
78 m_value = 0.0;
79 else
80 m_value = -180.0;
81 }
82 else if( aVector.x == 0.0 )
83 {
84 if( aVector.y >= 0.0 )
85 m_value = 90.0;
86 else
87 m_value = -90.0;
88 }
89 else if( aVector.x == aVector.y )
90 {
91 if( aVector.x >= 0.0 )
92 m_value = 45.0;
93 else
94 m_value = -180.0 + 45.0;
95 }
96 else if( aVector.x == -aVector.y )
97 {
98 if( aVector.x >= 0.0 )
99 m_value = -45.0;
100 else
101 m_value = 180.0 - 45.0;
102 }
103 else
104 {
105 *this = EDA_ANGLE( atan2( aVector.y, aVector.x ), RADIANS_T );
106 }
107 }
108
110 m_value( 0.0 )
111 {}
112
113 inline double AsDegrees() const { return m_value; }
114
115 inline int AsTenthsOfADegree() const { return KiROUND( m_value * 10.0 ); }
116
117 inline double AsRadians() const { return m_value * DEGREES_TO_RADIANS; }
118
119 static constexpr double DEGREES_TO_RADIANS = M_PI / 180.0;
120
125 bool IsCardinal() const;
126
131 bool IsCardinal90() const;
132
133 bool IsZero() const
134 {
135 return m_value == 0.0;
136 }
137
138 bool IsHorizontal() const
139 {
140 return m_value == 0.0 || m_value == 180.0;
141 }
142
143 bool IsVertical() const
144 {
145 return m_value == 90.0 || m_value == 270.0;
146 }
147
148 bool IsParallelTo( EDA_ANGLE aAngle ) const
149 {
150 EDA_ANGLE thisNormalized = *this;
151
152 // Normalize90 is inclusive on both ends [-90, +90]
153 // but we need it to be (-90, +90] for this test to work
154 thisNormalized.Normalize90();
155 if( thisNormalized.AsDegrees() == -90.0 )
156 thisNormalized = EDA_ANGLE( 90.0, DEGREES_T );
157
158 aAngle.Normalize90();
159 if( aAngle.AsDegrees() == -90.0 )
160 aAngle = EDA_ANGLE( 90.0, DEGREES_T );
161
162 return ( thisNormalized.AsDegrees() == aAngle.AsDegrees() );
163 }
164
166 {
167 return EDA_ANGLE( -AsDegrees(), DEGREES_T );
168 }
169
170 double Sin() const
171 {
172 EDA_ANGLE test = *this;
173 test.Normalize();
174
175 if( test.m_value == 0.0 || test.m_value == 180.0 )
176 return 0.0;
177 else if( test.m_value == 45.0 || test.m_value == 135.0 )
178 return M_SQRT1_2; // sqrt(2)/2
179 else if( test.m_value == 225.0 || test.m_value == 315.0 )
180 return -M_SQRT1_2;
181 else if( test.m_value == 90.0 )
182 return 1.0;
183 else if( test.m_value == 270.0 )
184 return -1.0;
185 else
186 return sin( AsRadians() );
187 }
188
189 double Cos() const
190 {
191 EDA_ANGLE test = *this;
192 test.Normalize();
193
194 if( test.m_value == 0.0 )
195 return 1.0;
196 else if( test.m_value == 180.0 )
197 return -1.0;
198 else if( test.m_value == 90.0 || test.m_value == 270.0 )
199 return 0.0;
200 else if( test.m_value == 45.0 || test.m_value == 315.0 )
201 return M_SQRT1_2; // sqrt(2)/2
202 else if( test.m_value == 135.0 || test.m_value == 225.0 )
203 return -M_SQRT1_2;
204 else
205 return cos( AsRadians() );
206 }
207
208 double Tan() const { return tan( AsRadians() ); }
209
210 static EDA_ANGLE Arccos( double x ) { return EDA_ANGLE( acos( x ), RADIANS_T ); }
211
212 static EDA_ANGLE Arcsin( double x ) { return EDA_ANGLE( asin( x ), RADIANS_T ); }
213
214 static EDA_ANGLE Arctan( double x ) { return EDA_ANGLE( atan( x ), RADIANS_T ); }
215
216 static EDA_ANGLE Arctan2( double y, double x )
217 {
218 return EDA_ANGLE( atan2( y, x ), RADIANS_T );
219 }
220
222 {
223 while( m_value < -0.0 )
224 m_value += 360.0;
225
226 while( m_value >= 360.0 )
227 m_value -= 360.0;
228
229 return *this;
230 }
231
233 {
234 EDA_ANGLE ret( *this );
235 return ret.Normalize();
236 }
237
239 {
240 while( m_value <= -360.0 )
241 m_value += 360.0;
242
243 while( m_value > 0.0 )
244 m_value -= 360.0;
245
246 return *this;
247 }
248
250 {
251 while( m_value < -90.0 )
252 m_value += 180.0;
253
254 while( m_value > 90.0 )
255 m_value -= 180.0;
256
257 return *this;
258 }
259
261 {
262 while( m_value <= -180.0 )
263 m_value += 360.0;
264
265 while( m_value > 180.0 )
266 m_value -= 360.0;
267
268 return *this;
269 }
270
272 {
273 while( m_value < -360.0 )
274 m_value += 360.0;
275
276 while( m_value >= 360.0 )
277 m_value -= 360.0;
278
279 return *this;
280 }
281
282 EDA_ANGLE KeepUpright() const;
283
284 EDA_ANGLE Round( int digits ) const
285 {
286 EDA_ANGLE angle( *this );
287 double rounded = KiROUND( angle.AsDegrees() * pow( 10.0, digits ) ) / pow( 10.0, digits );
288 angle = EDA_ANGLE( rounded, DEGREES_T );
289 return angle;
290 }
291
293 {
294 *this = EDA_ANGLE( AsDegrees() + aAngle.AsDegrees(), DEGREES_T );
295 return *this;
296 }
297
299 {
300 *this = EDA_ANGLE( AsDegrees() - aAngle.AsDegrees(), DEGREES_T );
301 return *this;
302 }
303
304private:
305 double m_value;
306
307};
308
309
310inline EDA_ANGLE operator-( const EDA_ANGLE& aAngle )
311{
312 return aAngle.Invert();
313}
314
315
316inline EDA_ANGLE operator-( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
317{
318 return EDA_ANGLE( aAngleA.AsDegrees() - aAngleB.AsDegrees(), DEGREES_T );
319}
320
321
322inline EDA_ANGLE operator+( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
323{
324 return EDA_ANGLE( aAngleA.AsDegrees() + aAngleB.AsDegrees(), DEGREES_T );
325}
326
327
328inline EDA_ANGLE operator*( const EDA_ANGLE& aAngleA, double aOperator )
329{
330 return EDA_ANGLE( aAngleA.AsDegrees() * aOperator, DEGREES_T );
331}
332
333
334inline EDA_ANGLE operator/( const EDA_ANGLE& aAngleA, double aOperator )
335{
336 return EDA_ANGLE( aAngleA.AsDegrees() / aOperator, DEGREES_T );
337}
338
339
340inline double operator/( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aOperator )
341{
342 return aAngleA.AsDegrees() / aOperator.AsDegrees();
343}
344
345
346inline bool operator==( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
347{
348 return aAngleA.AsDegrees() == aAngleB.AsDegrees();
349}
350
351
352inline bool operator!=( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
353{
354 return aAngleA.AsDegrees() != aAngleB.AsDegrees();
355}
356
357
358inline bool operator>( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
359{
360 return aAngleA.AsDegrees() > aAngleB.AsDegrees();
361}
362
363
364inline bool operator<( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
365{
366 return aAngleA.AsDegrees() < aAngleB.AsDegrees();
367}
368
369
370inline bool operator<=( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
371{
372 return aAngleA.AsDegrees() <= aAngleB.AsDegrees();
373}
374
375
376inline bool operator>=( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
377{
378 return aAngleA.AsDegrees() >= aAngleB.AsDegrees();
379}
380
381
382inline std::ostream& operator<<( std::ostream& aStream, const EDA_ANGLE& aAngle )
383{
384 return aStream << aAngle.AsDegrees();
385}
386
387
388namespace std
389{
390inline EDA_ANGLE abs( const EDA_ANGLE& aAngle )
391{
392 return EDA_ANGLE( std::abs( aAngle.AsDegrees() ), DEGREES_T );
393}
394}
395
396
397static constexpr EDA_ANGLE ANGLE_HORIZONTAL{ 0 };
398static constexpr EDA_ANGLE ANGLE_VERTICAL{ 90 };
399static constexpr EDA_ANGLE FULL_CIRCLE{ 360 };
400
401static constexpr EDA_ANGLE ANGLE_0{ 0 };
402static constexpr EDA_ANGLE ANGLE_45{ 45 };
403static constexpr EDA_ANGLE ANGLE_90{ 90 };
404static constexpr EDA_ANGLE ANGLE_135{ 135 };
405static constexpr EDA_ANGLE ANGLE_180{ 180 };
406static constexpr EDA_ANGLE ANGLE_270{ 270 };
407static constexpr EDA_ANGLE ANGLE_360{ 360 };
408
409
410#endif // EDA_ANGLE_H
EDA_ANGLE Normalize()
Definition: eda_angle.h:221
EDA_ANGLE NormalizeNegative()
Definition: eda_angle.h:238
double Sin() const
Definition: eda_angle.h:170
EDA_ANGLE Normalize90()
Definition: eda_angle.h:249
double Tan() const
Definition: eda_angle.h:208
constexpr EDA_ANGLE(double aAngleInDegrees)
Construct an EDA_ANGLE in degrees.
Definition: eda_angle.h:67
int AsTenthsOfADegree() const
Definition: eda_angle.h:115
bool IsParallelTo(EDA_ANGLE aAngle) const
Definition: eda_angle.h:148
double AsDegrees() const
Definition: eda_angle.h:113
EDA_ANGLE Invert() const
Definition: eda_angle.h:165
bool IsZero() const
Definition: eda_angle.h:133
bool IsHorizontal() const
Definition: eda_angle.h:138
bool IsCardinal() const
Definition: eda_angle.cpp:40
EDA_ANGLE Normalize180()
Definition: eda_angle.h:260
static EDA_ANGLE Arctan2(double y, double x)
Definition: eda_angle.h:216
EDA_ANGLE KeepUpright() const
Definition: eda_angle.cpp:23
EDA_ANGLE Normalize720()
Definition: eda_angle.h:271
double AsRadians() const
Definition: eda_angle.h:117
bool IsVertical() const
Definition: eda_angle.h:143
EDA_ANGLE & operator-=(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:298
EDA_ANGLE Round(int digits) const
Definition: eda_angle.h:284
EDA_ANGLE & operator+=(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:292
EDA_ANGLE(const VECTOR2D &aVector)
Definition: eda_angle.h:69
EDA_ANGLE(double aValue, EDA_ANGLE_T aAngleType)
Angles can be created in degrees, 1/10ths of a degree, or radians, and read as any of the angle types...
Definition: eda_angle.h:46
static constexpr double DEGREES_TO_RADIANS
Definition: eda_angle.h:119
bool IsCardinal90() const
Definition: eda_angle.cpp:54
double Cos() const
Definition: eda_angle.h:189
double m_value
value in degrees
Definition: eda_angle.h:305
static EDA_ANGLE Arctan(double x)
Definition: eda_angle.h:214
static EDA_ANGLE Arcsin(double x)
Definition: eda_angle.h:212
EDA_ANGLE Normalized() const
Definition: eda_angle.h:232
static EDA_ANGLE Arccos(double x)
Definition: eda_angle.h:210
EDA_ANGLE operator/(const EDA_ANGLE &aAngleA, double aOperator)
Definition: eda_angle.h:334
bool operator>(const EDA_ANGLE &aAngleA, const EDA_ANGLE &aAngleB)
Definition: eda_angle.h:358
bool operator>=(const EDA_ANGLE &aAngleA, const EDA_ANGLE &aAngleB)
Definition: eda_angle.h:376
EDA_ANGLE operator*(const EDA_ANGLE &aAngleA, double aOperator)
Definition: eda_angle.h:328
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:401
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:403
bool operator<=(const EDA_ANGLE &aAngleA, const EDA_ANGLE &aAngleB)
Definition: eda_angle.h:370
EDA_ANGLE_T
Definition: eda_angle.h:29
@ TENTHS_OF_A_DEGREE_T
Definition: eda_angle.h:30
@ RADIANS_T
Definition: eda_angle.h:32
@ DEGREES_T
Definition: eda_angle.h:31
EDA_ANGLE operator-(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:310
bool operator<(const EDA_ANGLE &aAngleA, const EDA_ANGLE &aAngleB)
Definition: eda_angle.h:364
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition: eda_angle.h:398
bool operator==(const EDA_ANGLE &aAngleA, const EDA_ANGLE &aAngleB)
Definition: eda_angle.h:346
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition: eda_angle.h:397
static constexpr EDA_ANGLE ANGLE_45
Definition: eda_angle.h:402
static constexpr EDA_ANGLE ANGLE_270
Definition: eda_angle.h:406
static constexpr EDA_ANGLE FULL_CIRCLE
Definition: eda_angle.h:399
static constexpr EDA_ANGLE ANGLE_360
Definition: eda_angle.h:407
static constexpr EDA_ANGLE ANGLE_180
Definition: eda_angle.h:405
EDA_ANGLE operator+(const EDA_ANGLE &aAngleA, const EDA_ANGLE &aAngleB)
Definition: eda_angle.h:322
static constexpr EDA_ANGLE ANGLE_135
Definition: eda_angle.h:404
bool operator!=(const EDA_ANGLE &aAngleA, const EDA_ANGLE &aAngleB)
Definition: eda_angle.h:352
std::ostream & operator<<(std::ostream &aStream, const EDA_TEXT &aText)
Definition: eda_text.cpp:1170
STL namespace.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:390
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:121