1 //------------------------------------------------------------------------
2 // EPI Angle type
3 //------------------------------------------------------------------------
4 //
5 // Copyright (c) 2004-2008 The EDGE Team.
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 //------------------------------------------------------------------------
18
19 #ifndef __EPI_ANGLE_CLASS__
20 #define __EPI_ANGLE_CLASS__
21
22 namespace epi
23 {
24
25 class angle_c
26 {
27 /* sealed class, value semantics */
28
29 private:
30 // binary angle measurement:
31 // 0 = EAST, 0.25 = NORTH, 0.5 = WEST, 0.75 = SOUTH.
32
33 u32_t bam;
34
angle_c(u32_t _bam,bool xxx)35 angle_c(u32_t _bam, bool xxx) : bam(_bam) { }
36 // xxx is a dummy argument, without it this method's signature
37 // becomes too similiar to the integer constructor below.
38
39 public:
angle_c()40 angle_c() : bam(0) { };
angle_c(const angle_c & rhs)41 angle_c(const angle_c& rhs) : bam(rhs.bam) { }
42
43 angle_c(int deg); // usable range is -360 .. +360
44 angle_c(float deg); //
45
46 static angle_c FromRadians(double rad); // range is -2pi .. +2pi
47 static angle_c FromVector(float x, float y);
48
49 float Degrees() const;
50 double Radians() const;
51
52 std::string ToStr(int precision = 1) const;
53
54 /* ---- read-only operations ---- */
55
Sin()56 inline float Sin() const { return sin(Radians()); }
Cos()57 inline float Cos() const { return cos(Radians()); }
Tan()58 inline float Tan() const { return tan(Radians()); }
59
60 static angle_c ATan(float slope);
61
getX()62 inline float getX() const { return Cos(); }
getY()63 inline float getY() const { return Sin(); }
64
65 angle_c Abs() const;
66 angle_c Dist(const angle_c& other) const;
67
Less180()68 inline bool Less180() const { return (bam & 0x80000000) ? false : true; }
More180()69 inline bool More180() const { return (bam & 0x80000000) ? true : false; }
Less90()70 inline bool Less90() const { return (bam & 0xC0000000) ? false : true; }
More90()71 inline bool More90() const { return (bam & 0xC0000000) ? true : false; }
72
73 inline bool operator< (const angle_c& rhs) const { return bam < rhs.bam; }
74 inline bool operator> (const angle_c& rhs) const { return bam > rhs.bam; }
75 inline bool operator>= (const angle_c& rhs) const { return bam >= rhs.bam; }
76 inline bool operator<= (const angle_c& rhs) const { return bam <= rhs.bam; }
77 inline bool operator== (const angle_c& rhs) const { return bam == rhs.bam; }
78 inline bool operator!= (const angle_c& rhs) const { return bam != rhs.bam; }
79
80 angle_c operator- () const;
81
82 angle_c operator+ (const angle_c& rhs) const;
83 angle_c operator- (const angle_c& rhs) const;
84 angle_c operator* (int factor) const;
85 angle_c operator/ (int factor) const;
86
87 /* ---- modifying operations ---- */
88
89 angle_c& operator= (const angle_c& rhs);
90
Add180()91 inline angle_c& Add180() { bam ^= 0x80000000; return *this; }
Add90()92 inline angle_c& Add90() { bam += 0x40000000; return *this; }
Sub90()93 inline angle_c& Sub90() { bam -= 0x40000000; return *this; }
94
95 angle_c& operator+= (const angle_c& rhs);
96 angle_c& operator-= (const angle_c& rhs);
97 angle_c& operator*= (int factor);
98 angle_c& operator/= (int factor);
99
100 /* ---- useful constants ---- */
101
Ang0()102 static inline angle_c Ang0() { return angle_c(0x00000000, false); }
Ang15()103 static inline angle_c Ang15() { return angle_c(0x0AAAAAAA, false); }
Ang30()104 static inline angle_c Ang30() { return angle_c(0x15555555, false); }
Ang45()105 static inline angle_c Ang45() { return angle_c(0x20000000, false); }
Ang60()106 static inline angle_c Ang60() { return angle_c(0x2AAAAAAA, false); }
Ang90()107 static inline angle_c Ang90() { return angle_c(0x40000000, false); }
Ang145()108 static inline angle_c Ang145() { return angle_c(0x60000000, false); }
Ang180()109 static inline angle_c Ang180() { return angle_c(0x80000000, false); }
Ang225()110 static inline angle_c Ang225() { return angle_c(0xA0000000, false); }
Ang270()111 static inline angle_c Ang270() { return angle_c(0xC0000000, false); }
Ang315()112 static inline angle_c Ang315() { return angle_c(0xE0000000, false); }
Ang360()113 static inline angle_c Ang360() { return angle_c(0xFFFFFFFF, false); }
114 };
115
116 //------------------------------------------------------------------------
117 // IMPLEMENTATION
118 //------------------------------------------------------------------------
119
angle_c(int deg)120 inline angle_c::angle_c(int deg) : bam(deg * 11930464 + deg * 7 / 10)
121 {
122 /* nothing needed */
123 }
124
angle_c(float deg)125 inline angle_c::angle_c(float deg) :
126 bam((u32_t) ((deg < 0 ? (deg + 360.0) : double(deg)) * 11930464.7084))
127 {
128 /* nothing needed */
129 }
130
FromRadians(double rad)131 inline angle_c angle_c::FromRadians(double rad)
132 {
133 if (rad < 0)
134 rad += M_PI * 2.0;
135
136 return angle_c((u32_t)(rad * 683565275.42), false);
137 }
138
FromVector(float x,float y)139 inline angle_c angle_c::FromVector(float x, float y)
140 {
141 if (x == 0)
142 return (y >= 0) ? Ang90() : Ang270();
143
144 double rad = atan2((double) y, (double) x);
145
146 return FromRadians(rad);
147 }
148
Degrees()149 inline float angle_c::Degrees() const
150 {
151 return double(bam) / 11930467.0;
152 }
153
Radians()154 inline double angle_c::Radians() const
155 {
156 return double(bam) / 683565275.42;
157 }
158
ATan(float slope)159 inline angle_c angle_c::ATan(float slope)
160 {
161 return FromRadians(atan(slope));
162 }
163
164 inline angle_c angle_c::operator- () const
165 {
166 return angle_c(bam ^ 0xFFFFFFFF, false);
167 }
168
169 inline angle_c angle_c::operator+ (const angle_c& rhs) const
170 {
171 return angle_c(bam + rhs.bam, false);
172 }
173
174 inline angle_c angle_c::operator- (const angle_c& rhs) const
175 {
176 return angle_c(bam - rhs.bam, false);
177 }
178
179 inline angle_c angle_c::operator* (int factor) const
180 {
181 return angle_c(bam * factor, false);
182 }
183
184 inline angle_c angle_c::operator/ (int factor) const
185 {
186 return angle_c(bam / factor, false);
187 }
188
Abs()189 inline angle_c angle_c::Abs() const
190 {
191 return angle_c(bam ^ (Less180() ? 0 : 0xFFFFFFFF), false);
192 }
193
Dist(const angle_c & other)194 inline angle_c angle_c::Dist(const angle_c &other) const
195 {
196 return (bam >= other.bam) ? angle_c(bam - other.bam, false) :
197 angle_c(other.bam - bam, false);
198 }
199
200 inline angle_c& angle_c::operator+= (const angle_c& rhs)
201 {
202 bam += rhs.bam;
203 return *this;
204 }
205
206 inline angle_c& angle_c::operator-= (const angle_c& rhs)
207 {
208 bam -= rhs.bam;
209 return *this;
210 }
211
212 inline angle_c& angle_c::operator*= (int factor)
213 {
214 bam *= factor;
215 return *this;
216 }
217
218 inline angle_c& angle_c::operator/= (int factor)
219 {
220 bam /= factor;
221 return *this;
222 }
223
224 inline angle_c& angle_c::operator= (const angle_c& rhs)
225 {
226 // no need to check for self assignment
227 bam = rhs.bam;
228 return *this;
229 }
230
231 } // namespace epi
232
233 #endif /* __EPI_ANGLE_CLASS__ */
234
235 //--- editor settings ---
236 // vi:ts=4:sw=4:noexpandtab
237