00001 #ifndef RECTANGLE_IMPLEMENTATION
00002 #define RECTANGLE_IMPLEMENTATION
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "point.cpp"
00019 #include "rectangle.h"
00020
00021 #include <basis/function.h>
00022
00023 namespace geometric {
00024
00025 template <class numeric_type>
00026 rectangle<numeric_type>::rectangle(const point<numeric_type> &lb, const point<numeric_type> &rt)
00027 : _vertex_1(lb), _vertex_2(rt) {}
00028
00029 template <class numeric_type>
00030 rectangle<numeric_type>::rectangle(numeric_type left, numeric_type bottom, numeric_type right, numeric_type top)
00031 : _vertex_1(point<numeric_type>(left, bottom)),
00032 _vertex_2(point<numeric_type>(right, top)) {}
00033
00034 template <class numeric_type>
00035 point<numeric_type> rectangle<numeric_type>::vertex_1() const
00036 { return _vertex_1; }
00037
00038 template <class numeric_type>
00039 point<numeric_type> rectangle<numeric_type>::vertex_2() const
00040 { return _vertex_2; }
00041
00042 template <class numeric_type>
00043 void rectangle<numeric_type>::vertex_1(const point<numeric_type> &to_set)
00044 { _vertex_1 = to_set; }
00045
00046 template <class numeric_type>
00047 void rectangle<numeric_type>::vertex_2(const point<numeric_type> &to_set)
00048 { _vertex_2 = to_set; }
00049
00050 template <class numeric_type>
00051 numeric_type rectangle<numeric_type>::height() const
00052 { return absolute_value(_vertex_2.y() - _vertex_1.y()); }
00053
00054 template <class numeric_type>
00055 numeric_type rectangle<numeric_type>::width() const
00056 { return absolute_value(_vertex_2.x() - _vertex_1.x()); }
00057
00058 template <class numeric_type>
00059 numeric_type rectangle<numeric_type>::minimum_x() const
00060 { return minimum(_vertex_1.x(), _vertex_2.x()); }
00061
00062 template <class numeric_type>
00063 numeric_type rectangle<numeric_type>::minimum_y() const
00064 { return minimum(_vertex_1.y(), _vertex_2.y()); }
00065
00066 template <class numeric_type>
00067 numeric_type rectangle<numeric_type>::maximum_x() const
00068 { return maximum(_vertex_1.x(), _vertex_2.x()); }
00069
00070 template <class numeric_type>
00071 numeric_type rectangle<numeric_type>::maximum_y() const
00072 { return maximum(_vertex_1.y(), _vertex_2.y()); }
00073
00074 template <class numeric_type>
00075 rectangle<numeric_type> rectangle<numeric_type>::order() const
00076 {
00077 numeric_type x1 = _vertex_1.x();
00078 numeric_type x2 = _vertex_2.x();
00079 numeric_type y1 = _vertex_1.y();
00080 numeric_type y2 = _vertex_2.y();
00081 flip_increasing(x1, x2);
00082 flip_increasing(y1, y2);
00083 return rectangle<numeric_type>(x1, y1, x2, y2);
00084 }
00085
00086 template <class numeric_type>
00087 point<numeric_type> rectangle<numeric_type>::top_left() const
00088 {
00089 rectangle temp(order());
00090 return point<numeric_type>(temp.vertex_1().x(), temp.vertex_2().y());
00091 }
00092
00093 template <class numeric_type>
00094 point<numeric_type> rectangle<numeric_type>::bottom_left() const
00095 {
00096 rectangle temp(order());
00097 return point<numeric_type>(temp.vertex_1().x(), temp.vertex_1().y());
00098 }
00099
00100 template <class numeric_type>
00101 point<numeric_type> rectangle<numeric_type>::top_right() const
00102 {
00103 rectangle temp(order());
00104 return point<numeric_type>(temp.vertex_2().x(), temp.vertex_2().y());
00105 }
00106
00107 template <class numeric_type>
00108 point<numeric_type> rectangle<numeric_type>::bottom_right() const
00109 {
00110 rectangle temp(order());
00111 return point<numeric_type>(temp.vertex_2().x(), temp.vertex_1().y());
00112 }
00113
00114 template <class numeric_type>
00115 point<numeric_type> rectangle<numeric_type>::center() const
00116 {
00117 return point<numeric_type>(numeric_type((_vertex_1.x()
00118 + _vertex_2.x()) / 2.0), numeric_type((_vertex_1.y()
00119 + _vertex_2.y()) / 2.0));
00120 }
00121
00122 template <class numeric_type>
00123 bool rectangle<numeric_type>::inside(const point<numeric_type> &to_check) const
00124 {
00125 rectangle<numeric_type> ordered_me = this->order();
00126 return bool( (to_check.x() >= ordered_me._vertex_1.x())
00127 && (to_check.x() <= ordered_me._vertex_2.x())
00128 && (to_check.y() >= ordered_me._vertex_1.y())
00129 && (to_check.y() <= ordered_me._vertex_2.y()) );
00130 }
00131
00132 template <class numeric_type>
00133 bool rectangle<numeric_type>::operator == (const rectangle &to_compare) const
00134 {
00135 point<numeric_type> min1(minimum_x(), minimum_y());
00136 point<numeric_type> max1(maximum_x(), maximum_y());
00137 point<numeric_type> min2(to_compare.minimum_x(), to_compare.minimum_y());
00138 point<numeric_type> max2(to_compare.maximum_x(), to_compare.maximum_y());
00139 if ( (min1 == min2) && (max1 == max2) ) return true;
00140 else return false;
00141 }
00142
00143 template <class numeric_type>
00144 bool rectangle<numeric_type>::operator != (const rectangle &to_compare) const
00145 { return (bool)!(*this == to_compare); }
00146
00147 template <class numeric_type>
00148 rectangle<numeric_type> &rectangle<numeric_type>::operator += (const point<numeric_type> &p)
00149 { _vertex_1 += p; _vertex_2 += p; return *this; }
00150
00151 template <class numeric_type>
00152 rectangle<numeric_type> &rectangle<numeric_type>::operator -= (const point<numeric_type> &p)
00153 { _vertex_1 -= p; _vertex_2 -= p; return *this; }
00154
00155 template <class numeric_type>
00156 rectangle<numeric_type> rectangle<numeric_type>::operator + (const point<numeric_type> &p) const
00157 {
00158 rectangle to_return(*this);
00159 to_return += p;
00160 return to_return;
00161 }
00162
00163 template <class contents>
00164 void rectangle<contents>::pack(byte_array &packed_form) const
00165 {
00166 _vertex_1.pack(packed_form);
00167 _vertex_2.pack(packed_form);
00168 }
00169
00170 template <class contents>
00171 bool rectangle<contents>::unpack(byte_array &packed_form)
00172 {
00173 if (!_vertex_1.unpack(packed_form)) return false;
00174 if (!_vertex_2.unpack(packed_form)) return false;
00175 return true;
00176 }
00177
00178 template <class numeric_type>
00179 rectangle<numeric_type> rectangle<numeric_type>::operator - (const point<numeric_type> &p) const
00180 {
00181 rectangle to_return(*this);
00182 to_return -= p;
00183 return to_return;
00184 }
00185
00186 template <class numeric_type>
00187 void rectangle<numeric_type>::encompass(const rectangle &to_adjust_to)
00188 {
00189 if (to_adjust_to._vertex_1.x() < _vertex_1.x())
00190 _vertex_1.set(to_adjust_to._vertex_1.x(), _vertex_1.y());
00191 if (to_adjust_to._vertex_1.y() < _vertex_1.y())
00192 _vertex_1.set(_vertex_1.x(), to_adjust_to._vertex_1.y());
00193 if (to_adjust_to._vertex_2.x() > _vertex_2.x())
00194 _vertex_2.set(to_adjust_to._vertex_2.x(), _vertex_2.y());
00195 if (to_adjust_to._vertex_2.y() > _vertex_2.y())
00196 _vertex_2.set(_vertex_2.x(), to_adjust_to._vertex_2.y());
00197 }
00198
00199 template <class numeric_type>
00200 bool rectangle<numeric_type>::disjoint(const rectangle &r2) const
00201 {
00202 if ( (maximum_x() < r2.minimum_x())
00203 || (minimum_x() > r2.maximum_x())
00204 || (maximum_y() < r2.minimum_y())
00205 || (minimum_y() > r2.maximum_y()) ) return true;
00206 else return false;
00207 }
00208
00209 template <class numeric_type>
00210 bool rectangle<numeric_type>::intersect(const rectangle &r2) const
00211 { return bool(!disjoint(r2)); }
00212
00213 template <class numeric_type>
00214 bool rectangle<numeric_type>::join_intersecting(const rectangle &r2, rectangle &result)
00215 {
00216 if (disjoint(r2)) return false;
00217 result = *this;
00218 result.encompass(r2);
00219 return true;
00220 }
00221
00222 template <class numeric_type>
00223 bool rectangle<numeric_type>::intersection(const rectangle &r2, rectangle &result)
00224 {
00225 if (disjoint(r2)) return false;
00226 result = rectangle<numeric_type>(maximum(minimum_x(), r2.minimum_x()),
00227 maximum(minimum_y(), r2.minimum_y()),
00228 minimum(maximum_x(), r2.maximum_x()),
00229 minimum(maximum_y(), r2.maximum_y()));
00230 return true;
00231 }
00232
00233 template <class numeric_type>
00234 istring rectangle<numeric_type>::text_form() const
00235 {
00236 return istring("[") + _vertex_1.text_form() + istring(" ")
00237 + _vertex_2.text_form() + istring("]");
00238 }
00239
00240 template <class numeric_type>
00241 bool rectangle<numeric_type>::from_text(const istring &_text)
00242 {
00243 numeric_type nums[4] = { 0, 0, 0, 0 };
00244
00245 istring spec(numeric_specifier(nums[0]));
00246
00247 istring text(_text);
00248 for (int i = 0; i < 4; i++) {
00249 text = crop_non_numeric(text);
00250 nums[i] = text.convert(nums[i]);
00251 text = crop_numeric(text);
00252 }
00253 vertex_1(point<numeric_type>(nums[0], nums[1]));
00254 vertex_2(point<numeric_type>(nums[2], nums[3]));
00255 return true;
00256 }
00257
00258 }
00259
00260 #endif
00261