00001 #ifndef RECTANGLE_WARPER_CLASS
00002 #define RECTANGLE_WARPER_CLASS
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00019
00028 #include "rectangle.h"
00029
00030 #include <basis/astring.h>
00031
00032 namespace geometric {
00033
00034 template <class numeric_type>
00035 class rectangle_warper
00036 {
00037 public:
00039
00045 enum origin_vertex { BOTTOM_LEFT, TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT };
00046
00047 rectangle_warper(const rectangle<numeric_type> &system_1,
00048 const rectangle<numeric_type> &system_2,
00049 origin_vertex system_1_origin = BOTTOM_LEFT,
00050 origin_vertex system_2_origin = BOTTOM_LEFT);
00052
00056 ~rectangle_warper();
00057
00058 point<numeric_type> to_system_1(const point<numeric_type> &in_system_2) const;
00060
00064 point<numeric_type> to_system_2(const point<numeric_type> &in_system_1) const;
00066
00070 rectangle<numeric_type> to_system_1
00071 (const rectangle<numeric_type> &in_system_2) const;
00073 rectangle<numeric_type> to_system_2
00074 (const rectangle<numeric_type> &in_system_1) const;
00076
00077 rectangle<numeric_type> system_1() const { return _system_1; }
00078 rectangle<numeric_type> system_2() const { return _system_2; }
00079 origin_vertex origin_1() const { return _vert_1; }
00080 origin_vertex origin_2() const { return _vert_2; }
00081
00082 void system_1(const rectangle<numeric_type> &to_set,
00083 origin_vertex origin_corner = BOTTOM_LEFT);
00084 void system_2(const rectangle<numeric_type> &to_set,
00085 origin_vertex origin_corner = BOTTOM_LEFT);
00086
00087 basis::astring text_form() const;
00089
00090 basis::astring vertex_name(origin_vertex v) const;
00092
00093 enum vertical_component { RW_BOTTOM, RW_TOP };
00094 enum horizontal_component { RW_LEFT, RW_RIGHT };
00095
00096 void separate_vertical(origin_vertex v, vertical_component &to_set) const;
00097 void separate_horizontal(origin_vertex v, horizontal_component &to_set) const;
00099
00100 private:
00101 rectangle<numeric_type> _system_1;
00102 rectangle<numeric_type> _system_2;
00103 origin_vertex _vert_1;
00104 origin_vertex _vert_2;
00105
00106 point<numeric_type> scale_point(const rectangle<numeric_type> &source,
00107 const rectangle<numeric_type> &target,
00108 origin_vertex v1, origin_vertex v2,
00109 const point<numeric_type> &old) const;
00110 rectangle<numeric_type> scale_rectangle(const rectangle<numeric_type> &source,
00111 const rectangle<numeric_type> &target,
00112 origin_vertex v1, origin_vertex v2,
00113 const rectangle<numeric_type> &old) const;
00114 rectangle<numeric_type> flip_accordingly
00115 (const rectangle<numeric_type> &to_flip, origin_vertex to_flip_origin,
00116 origin_vertex target_origin) const;
00118
00121 };
00122
00124
00125
00126
00127 template <class numeric_type>
00128 rectangle_warper<numeric_type>::rectangle_warper
00129 (const rectangle<numeric_type> &system_1,
00130 const rectangle<numeric_type> &system_2,
00131 origin_vertex v1, origin_vertex v2)
00132 : _system_1(system_1), _system_2(system_2), _vert_1(v1), _vert_2(v2)
00133 {}
00134
00135 template <class numeric_type>
00136 rectangle_warper<numeric_type>::~rectangle_warper() {}
00137
00138 template <class numeric_type>
00139 void rectangle_warper<numeric_type>::system_1
00140 (const rectangle<numeric_type> &to_set, origin_vertex v)
00141 { _system_1 = to_set; _vert_1 = v; }
00142
00143 template <class numeric_type>
00144 void rectangle_warper<numeric_type>::system_2
00145 (const rectangle<numeric_type> &to_set, origin_vertex v)
00146 { _system_2 = to_set; _vert_2 = v; }
00147
00148 template <class numeric_type>
00149 point<numeric_type> rectangle_warper<numeric_type>::to_system_1
00150 (const point<numeric_type> &in_system_2) const
00151 { return scale_point(_system_2, _system_1, _vert_2, _vert_1, in_system_2); }
00152
00153 template <class numeric_type>
00154 point<numeric_type> rectangle_warper<numeric_type>::to_system_2
00155 (const point<numeric_type> &in_system_1) const
00156 { return scale_point(_system_1, _system_2, _vert_1, _vert_2, in_system_1); }
00157
00158 template <class numeric_type>
00159 rectangle<numeric_type> rectangle_warper<numeric_type>::to_system_1
00160 (const rectangle<numeric_type> &in_system_2) const
00161 {
00162 return scale_rectangle(_system_2, _system_1, _vert_2, _vert_1,
00163 in_system_2);
00164 }
00165
00166 template <class numeric_type>
00167 rectangle<numeric_type> rectangle_warper<numeric_type>::to_system_2
00168 (const rectangle<numeric_type> &in_system_1) const
00169 {
00170 return scale_rectangle(_system_1, _system_2, _vert_1, _vert_2,
00171 in_system_1);
00172 }
00173
00174 template <class numeric_type>
00175 void rectangle_warper<numeric_type>::separate_vertical
00176 (origin_vertex v, vertical_component &to_set) const
00177 {
00178 if ( (v == BOTTOM_LEFT) || (v == BOTTOM_RIGHT) ) to_set = RW_BOTTOM;
00179 to_set = RW_TOP;
00180 }
00181
00182 template <class numeric_type>
00183 void rectangle_warper<numeric_type>::separate_horizontal
00184 (origin_vertex v, horizontal_component &to_set) const
00185 {
00186 if ( (v == BOTTOM_LEFT) || (v == TOP_LEFT) ) to_set = RW_LEFT;
00187 to_set = RW_RIGHT;
00188 }
00189
00190 template <class numeric_type>
00191 rectangle<numeric_type> rectangle_warper<numeric_type>::flip_accordingly
00192 (const rectangle<numeric_type> &to_flip, origin_vertex flipo,
00193 origin_vertex targo) const
00194 {
00195
00196 if (flipo == targo) return to_flip;
00197 numeric_type x1(to_flip.vertex_1().x());
00198 numeric_type y1(to_flip.vertex_1().y());
00199 numeric_type x2(to_flip.vertex_2().x());
00200 numeric_type y2(to_flip.vertex_2().y());
00201 horizontal_component horiz1;
00202 separate_horizontal(flipo, horiz1);
00203 horizontal_component horiz2;
00204 separate_horizontal(targo, horiz2);
00205 bool flip_x = bool(horiz1 != horiz2);
00206 vertical_component vert1;
00207 separate_vertical(flipo, vert1);
00208 vertical_component vert2;
00209 separate_vertical(targo, vert2);
00210 bool flip_y = bool(vert1 != vert2);
00211 if (flip_x) swap_values(x1, x2);
00212 if (flip_y) swap_values(y1, y2);
00213
00214 return rectangle<numeric_type>(x1, y1, x2, y2);
00215 }
00216
00217 template <class numeric_type>
00218 rectangle<numeric_type> rectangle_warper<numeric_type>::scale_rectangle
00219 (const rectangle<numeric_type> &source,
00220 const rectangle<numeric_type> &target, origin_vertex source_origin,
00221 origin_vertex target_origin, const rectangle<numeric_type> &old) const
00222 {
00223 rectangle<numeric_type> s = rectangle<numeric_type>
00224 (flip_accordingly(source, source_origin, BOTTOM_LEFT));
00225 numeric_type width_source = s.vertex_2().x() - s.vertex_1().x();
00226 numeric_type height_source = s.vertex_2().y() - s.vertex_1().y();
00227 if ( !width_source || !height_source ) {
00228
00229
00230 return old;
00231 }
00232 rectangle<numeric_type> t(flip_accordingly(target, target_origin, BOTTOM_LEFT));
00233 numeric_type width_target = t.vertex_2().x() - t.vertex_1().x();
00234 numeric_type height_target = t.vertex_2().y() - t.vertex_1().y();
00235 numeric_type x_scale = width_target / width_source;
00236 numeric_type y_scale = height_target / height_source;
00237
00238
00239
00240 rectangle<numeric_type> o(flip_accordingly(old, source_origin, BOTTOM_LEFT));
00241
00242 rectangle<numeric_type> to_return = flip_accordingly(rectangle<numeric_type>
00243 ((o.vertex_1().x() - s.vertex_1().x()) * x_scale + t.vertex_1().x(),
00244 (o.vertex_1().y() - s.vertex_1().y()) * y_scale + t.vertex_1().y(),
00245 (o.vertex_2().x() - s.vertex_1().x()) * x_scale + t.vertex_1().x(),
00246 (o.vertex_2().y() - s.vertex_1().y()) * y_scale + t.vertex_1().y()),
00247 BOTTOM_LEFT, target_origin);
00248
00249
00250
00251 return to_return;
00252 }
00253
00254 template <class numeric_type>
00255 point<numeric_type> rectangle_warper<numeric_type>::scale_point
00256 (const rectangle<numeric_type> &source, const rectangle<numeric_type> &target,
00257 origin_vertex source_origin, origin_vertex target_origin,
00258 const point<numeric_type> &old) const
00259 {
00260
00261 return scale_rectangle(source, target, source_origin, target_origin,
00262 rectangle<numeric_type>(old, old)).vertex_1();
00263 }
00264
00265 template <class numeric_type>
00266 basis::astring rectangle_warper<numeric_type>::vertex_name(origin_vertex v) const
00267 {
00268 basis::astring name("unknown");
00269 switch (v) {
00270 case BOTTOM_LEFT: name = "bottom-left"; break;
00271 case BOTTOM_RIGHT: name = "bottom-right"; break;
00272 case TOP_LEFT: name = "top-left"; break;
00273 case TOP_RIGHT: name = "top-right"; break;
00274 }
00275 return name;
00276 }
00277
00278 template <class numeric_type>
00279 basis::astring rectangle_warper<numeric_type>::text_form() const
00280 {
00281 return basis::astring("<warps from: ") + _system_1.text_form()
00282 + basis::astring(" with vertex at ") + vertex_name(_vert_1)
00283 + basis::astring(" into ") + _system_2.text_form()
00284 + basis::astring(" with vertex at ") + vertex_name(_vert_2)
00285 + basis::astring(">");
00286 }
00287
00288 }
00289
00290 #endif
00291