4 /*****************************************************************************\
7 * Author : Chris Koeritz *
9 *******************************************************************************
10 * Copyright (c) 1992-$now By Author. This program is free software; you can *
11 * redistribute it and/or modify it under the terms of the GNU General Public *
12 * License as published by the Free Software Foundation; either version 2 of *
13 * the License or (at your option) any later version. This is online at: *
14 * http://www.fsf.org/copyleft/gpl.html *
15 * Please send any updates to: fred@gruntose.com *
16 \*****************************************************************************/
18 #include <basis/byte_array.h>
19 #include <basis/common_outcomes.h>
20 #include <basis/contracts.h>
21 #include <structures/object_packers.h>
27 //! Represents a geometric angle.
29 //! angles can be measured in degrees or radians in this class.
30 enum angular_units { DEGREES, RADIANS };
32 template <class contents>
33 class angle : public basis::packable
36 DEFINE_CLASS_NAME("angle");
38 angle(contents inital_rotation = 0, angular_units unit = RADIANS);
39 //!< constructs a new angle with "initial_rotation" in the "unit".
41 void set(contents a, angular_units unit);
42 //!< sets the angle to a new rotation "a" in the "unit".
43 contents get(angular_units unit) const;
44 //!< retrieves the current angular measure.
46 angle operator - (void) const;
47 //!< returns the negation of this angle.
49 angle operator + (const angle &to_add) const;
50 angle operator - (const angle &to_subtract) const;
51 angle operator * (contents to_multiply) const;
52 angle operator / (contents to_divide) const;
53 angle &operator += (const angle &to_add);
54 angle &operator -= (const angle &to_subtract);
55 angle &operator *= (contents to_multiply);
56 angle &operator /= (contents to_divide);
58 contents sine() const;
59 //!< returns the sin function of this angle.
60 contents cosine() const;
61 //!< returns the cos function of this angle.
62 contents tangent() const;
63 //!< returns the tan function of this angle.
65 static angle arctangent(contents opposite, contents adjacent,
66 basis::outcome &retval);
67 //!< returns the atan of the angle.
68 /*!< the outcome will be set to OKAY if the function operated successfully.
69 otherwise it will be set to BAD_INPUT. */
70 static angle arccosine(contents adjacent, contents hypotenuse,
71 basis::outcome &retval);
72 //!< returns the acos of the angle.
73 static angle arcsine(contents opposite, contents hypotenuse,
74 basis::outcome &retval);
75 //!< returns the asin of the angle.
77 virtual int packed_size() const;
78 virtual void pack(basis::byte_array &packed_form) const;
79 //!< packs the angle for shipping in bytes.
80 virtual bool unpack(basis::byte_array &packed_form);
81 //!< unpacks the angle from the "packed_form".
84 contents _theta; //!< the held angular measure.
86 contents to_internal(contents initial, angular_units unit) const;
87 //!< converts the angle into the units we use inside the class.
88 contents from_internal(contents initial, angular_units unit) const;
89 //!< converts the angle from our internal measure into "unit" measure.
94 //! double_angle provides a non-templated class for forward declarations.
96 class double_angle : public angle<double>
99 double_angle(double init = 0, angular_units unit = RADIANS)
100 : angle<double>(init, unit) {}
101 double_angle(const angle<double> &to_copy) : angle<double>(to_copy) {}
106 // implementation of larger methods below.
108 template <class contents>
109 angle<contents>::angle(contents a, angular_units unit) { set(a, unit); }
111 template <class contents>
112 angle<contents> angle<contents>::operator - (void) const
113 { angle<contents> to_return(*this); to_return *= -1; return to_return; }
115 template <class contents>
116 angle<contents> angle<contents>::operator + (const angle<contents> &a) const
117 { angle<contents> to_return(*this); to_return += a; return to_return; }
119 template <class contents>
120 angle<contents> angle<contents>::operator - (const angle<contents> &a) const
121 { angle<contents> to_return(*this); to_return -= a; return to_return; }
123 template <class contents>
124 angle<contents> angle<contents>::operator * (contents to_multiply) const
126 angle<contents> to_return(*this);
127 to_return *= to_multiply;
131 template <class contents>
132 angle<contents> angle<contents>::operator / (contents to_divide) const
133 { angle<contents> to_return(*this); to_return /= to_divide; return to_return; }
135 template <class contents>
136 angle<contents> &angle<contents>::operator += (const angle<contents> &a)
137 { _theta += a._theta; return *this; }
139 template <class contents>
140 angle<contents> &angle<contents>::operator -= (const angle<contents> &a)
141 { _theta -= a._theta; return *this; }
143 template <class contents>
144 angle<contents> &angle<contents>::operator *= (contents f)
145 { _theta *= f; return *this; }
147 template <class contents>
148 angle<contents> &angle<contents>::operator /= (contents f)
149 { _theta /= f; return *this; }
151 template <class contents>
152 contents angle<contents>::sine() const { return sin(_theta); }
154 template <class contents>
155 contents angle<contents>::cosine() const { return cos(_theta); }
157 template <class contents>
158 contents angle<contents>::tangent() const { return tan(_theta); }
160 template <class contents>
161 int angle<contents>::packed_size() const
163 basis::byte_array temp;
166 return temp.length();
169 template <class contents>
170 void angle<contents>::pack(basis::byte_array &packed_form) const
171 { structures::attach(packed_form, _theta); }
173 template <class contents>
174 bool angle<contents>::unpack(basis::byte_array &packed_form)
175 { return structures::detach(packed_form, _theta); }
177 template <class contents>
178 contents angle<contents>::to_internal(contents a, angular_units unit) const
181 case RADIANS: return a;
182 case DEGREES: return a * PI_APPROX / 180.0;
187 template <class contents>
188 contents angle<contents>::from_internal(contents a, angular_units unit) const
191 case RADIANS: return a;
192 case DEGREES: return a * 180.0 / PI_APPROX;
197 template <class contents>
198 void angle<contents>::set(contents a, angular_units unit)
199 { _theta = to_internal(a, unit); }
201 template <class contents>
202 contents angle<contents>::get(angular_units unit) const
203 { return from_internal(_theta, unit); }
205 template <class contents>
206 angle<contents> angle<contents>::arccosine(contents adjacent,
207 contents hypotenuse, basis::outcome &retval)
209 contents d = adjacent / hypotenuse;
210 retval = basis::common::BAD_INPUT;
211 bounds_return(d, -1.0, 1.0, angle<contents>());
212 retval = basis::common::OKAY;
213 return angle<contents>(acos(d), RADIANS);
216 template <class contents>
217 angle<contents> angle<contents>::arcsine(contents opposite, contents hypotenuse,
218 basis::outcome &retval)
220 contents d = opposite / hypotenuse;
221 retval = basis::common::BAD_INPUT;
222 bounds_return(d, -1.0, 1.0, angle<contents>());
223 retval = basis::common::OKAY;
224 return angle<contents>(asin(d), RADIANS);
227 template <class contents>
228 angle<contents> angle<contents>::arctangent(contents opposite, contents adjacent,
229 basis::outcome &retval)
231 retval = basis::common::BAD_INPUT;
232 if ( (adjacent == 0.0) && (opposite == 0.0) ) return angle<contents>();
233 retval = basis::common::OKAY;
234 return angle<contents>(atan2(opposite, adjacent), RADIANS);