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 \*****************************************************************************/
19 #include "math_bits.h"
22 #include <basis/astring.h>
23 #include <basis/contracts.h>
24 #include <basis/functions.h>
25 #include <structures/object_packers.h>
29 //! Contains all of our objects for geometry and avoids name clashes.
33 //! Represents a geometric point.
35 template <class numeric_type>
36 class point : public basis::packable, public virtual basis::root_object
39 point(numeric_type x = 0, numeric_type y = 0);
40 point(numeric_type r, double_angle theta);
42 DEFINE_CLASS_NAME("point");
44 void set(numeric_type x, numeric_type y);
45 void set(numeric_type r, double_angle theta);
47 numeric_type x() const { return _x; }
48 numeric_type y() const { return _y; }
50 numeric_type r() const;
51 double_angle theta() const;
53 point rotate(const double_angle &theta) const;
54 //!< Rotates the point by the angle "theta".
55 /*!< This rotates the position of the point around the origin in the
56 trigonometric standard manner; zero degrees is at the right, increasing
57 degree angles are counterclockwise from the x axis to the y to the
60 numeric_type distance(const point &p2) const;
61 //!< Returns the distance between `this' and the second point `p2'.
63 point operator - () const { return point<numeric_type>(-_x, -_y); }
64 //!< return the additive inverse of the vector
66 numeric_type magnitude() const;
67 //!< return the distance from the origin to this point.
69 point operator + (const point &arg2) const;
70 point operator - (const point &arg2) const;
71 point &operator += (const point &arg2);
72 point &operator -= (const point &arg2);
73 bool operator == (const point &arg2) const;
75 basis::astring text_form() const;
76 //!< Prints out the two values (x and y) held in the point.
78 bool from_text(const basis::astring &text);
79 //!< returns true if the "text" is successfully pulled into this point.
81 virtual void pack(basis::byte_array &packed_form) const;
82 virtual bool unpack(basis::byte_array &packed_form);
83 int packed_size() const;
92 // implementations below...
96 // - there is an odd breaking up of the expressions where we're taking a
97 // square root because ms visual studio 7 has a bug of some sort that
98 // convinces it that angle<int> is being used in there, although it's not.
99 // these lines use a temporary named "sumsquar" to deconfuse the compiler.
101 template <class numeric_type>
102 point<numeric_type>::point(numeric_type x, numeric_type y) { set(x, y); }
104 template <class numeric_type>
105 point<numeric_type>::point(numeric_type r, double_angle theta)
108 template <class numeric_type>
109 basis::astring point<numeric_type>::text_form() const
111 numeric_type temp = 0;
112 basis::astring specifier(numeric_specifier(temp));
113 basis::astring sprintf_template(basis::astring::SPRINTF, "(%s, %s)", specifier.s(), specifier.s());
114 return basis::astring(basis::astring::SPRINTF, sprintf_template.s(), x(), y());
117 template <class numeric_type>
118 void point<numeric_type>::set(numeric_type x, numeric_type y)
121 template <class numeric_type>
122 numeric_type point<numeric_type>::r() const
124 const double sumsquar = basis::square(x()) + basis::square(y());
125 return numeric_type(sqrt(sumsquar));
128 template <class numeric_type>
129 void point<numeric_type>::set(numeric_type r, double_angle theta)
130 { set(numeric_type(r * theta.cosine()), numeric_type(r * theta.sine())); }
132 template <class numeric_type>
133 numeric_type point<numeric_type>::distance(const point &p2) const
135 const double sumsquar = basis::square(p2.x() - x()) + basis::square(p2.y() - y());
136 return numeric_type(sqrt(sumsquar));
139 template <class numeric_type>
140 double_angle point<numeric_type>::theta() const
142 basis::outcome retval;
143 return double_angle::arctangent(y(), x(), retval);
146 template <class contents>
147 int point<contents>::packed_size() const
149 basis::byte_array temp;
152 return temp.length();
155 template <class contents>
156 void point<contents>::pack(basis::byte_array &packed_form) const
158 structures::attach(packed_form, _x);
159 structures::attach(packed_form, _y);
162 template <class contents>
163 bool point<contents>::unpack(basis::byte_array &packed_form)
165 if (!structures::detach(packed_form, _x)) return false;
166 if (!structures::detach(packed_form, _y)) return false;
170 template <class numeric_type>
171 numeric_type point<numeric_type>::magnitude() const
173 const double sumsquar = basis::square(x()) + basis::square(y());
174 return numeric_type(sqrt(sumsquar));
177 template <class numeric_type>
178 point<numeric_type> point<numeric_type>::operator + (const point &arg2) const
179 { return point<numeric_type>(x() + arg2.x(), y() + arg2.y()); }
181 template <class numeric_type>
182 point<numeric_type> point<numeric_type>::operator - (const point &arg2) const
183 { return point<numeric_type>(x() - arg2.x(), y() - arg2.y()); }
185 template <class numeric_type>
186 point<numeric_type> &point<numeric_type>::operator += (const point &arg2)
187 { _x += arg2.x(); _y += arg2.y(); return *this; }
189 template <class numeric_type>
190 point<numeric_type> &point<numeric_type>::operator -= (const point &arg2)
191 { _x -= arg2.x(); _y -= arg2.y(); return *this; }
193 template <class numeric_type>
194 bool point<numeric_type>::operator == (const point &arg2) const
196 // this bit should be part of the floating point stuff...
197 double epsilon = 1e-10;
198 return (basis::absolute_value(x() - arg2.x()) <= epsilon)
199 && (basis::absolute_value(y() - arg2.y()) <= epsilon);
202 template <class numeric_type>
203 point<numeric_type> point<numeric_type>::rotate
204 (const double_angle &theta) const
206 numeric_type tempX = x();
207 numeric_type tempY = y();
208 numeric_type temp1 = numeric_type(tempX * theta.cosine()
209 - tempY * theta.sine());
210 numeric_type temp2 = numeric_type(tempX * theta.sine()
211 + tempY * theta.cosine());
212 return point<numeric_type>(temp1, temp2);
215 template <class numeric_type>
216 bool point<numeric_type>::from_text(const basis::astring &_text)
218 numeric_type x = 0, y = 0;
219 basis::astring text(_text);
220 // chop junk off the front.
221 text = crop_non_numeric(text);
222 // scan the string for values.
224 // remove the number.
225 text = crop_numeric(text);
226 // chop off more junk.
227 text = crop_non_numeric(text);
228 // get the next number.