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