00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00033
00034 #ifndef GROOVX_GEOM_RECT_H_UTC20050626084022_DEFINED
00035 #define GROOVX_GEOM_RECT_H_UTC20050626084022_DEFINED
00036
00037 #include "geom/span.h"
00038 #include "geom/vec2.h"
00039
00040 #include "rutz/algo.h"
00041 #include "rutz/error.h"
00042
00043 #include "rutz/debug.h"
00044 GVX_DBG_REGISTER
00045
00046 namespace geom
00047 {
00048
00049
00051
00052 template<class V>
00053 class rect
00054 {
00055 public:
00056
00057 rect() : xx(), yy() {}
00058
00059 rect(const geom::span<V>& x, const geom::span<V>& y) : xx(x), yy(y) {}
00060
00061 rect(const geom::vec2<V>& p1, const geom::vec2<V>& p2)
00062 { set_corners(p1, p2); }
00063
00064 rect(const rect<V>& i) : xx(i.xx), yy(i.yy) {}
00065
00066 template <class U>
00067 explicit rect(const rect<U>& other) :
00068 xx(other.x_span()), yy(other.y_span()) {}
00069
00070 rect<V>& operator=(const rect<V>& i)
00071 { xx = i.xx; yy = i.yy; return *this; }
00072
00074 static rect<V> ltrb(V l, V t, V r, V b)
00075 {
00076 return rect<V>().set_ltrb(l, t, r, b);
00077 }
00078
00080 static rect<V> lbwh(V l, V b, V w, V h)
00081 {
00082 return rect<V>().set_lbwh(l, b, w, h);
00083 }
00084
00086 static rect<V> lbwh(const geom::vec2<V>& xy, const geom::vec2<V>& wh)
00087 {
00088 return lbwh(xy.x(), xy.y(), wh.x(), wh.y());
00089 }
00090
00091
00092 void get_ltrb(V& L, V& T, V& R, V& B) const
00093 { L = xx.lo; T = yy.hi; R = xx.hi; B = yy.lo; }
00094 void get_lrbt(V& L, V& R, V& B, V& T) const
00095 { L = xx.lo; R = xx.hi; B = yy.lo; T = yy.hi; }
00096
00097 geom::vec2<V> bottom_left() const
00098 { return geom::vec2<V>(xx.lo, yy.lo); }
00099
00100 geom::vec2<V> bottom_right() const
00101 { return geom::vec2<V>(xx.hi, yy.lo); }
00102
00103 geom::vec2<V> top_left() const
00104 { return geom::vec2<V>(xx.lo, yy.hi); }
00105
00106 geom::vec2<V> top_right() const
00107 { return geom::vec2<V>(xx.hi, yy.hi); }
00108
00109 V width() const { return (xx.hi-xx.lo); }
00110 V height() const { return (yy.hi-yy.lo); }
00111
00112 geom::vec2<V> size() const { return geom::vec2<V>(width(), height()); }
00113
00114 V aspect() const { return width()/height(); }
00115
00116 geom::vec2<V> center() const { return geom::vec2<V>(center_x(), center_y()); }
00117
00118 V center_x() const { return xx.center(); }
00119 V center_y() const { return yy.center(); }
00120
00121 const span<V>& x_span() const { return xx; }
00122 const span<V>& y_span() const { return yy; }
00123
00124 const V& left() const { return xx.lo; }
00125 const V& right() const { return xx.hi; }
00126 const V& bottom() const { return yy.lo; }
00127 const V& top() const { return yy.hi; }
00128
00129 template <class U>
00130 bool contains(const geom::vec2<U>& pt) const
00131 { return xx.contains(pt.x()) && yy.contains(pt.y()); }
00132
00133
00134
00135
00136
00138 rect<V>& set_ltrb(V L, V T, V R, V B)
00139 {
00140 if (L > R)
00141 throw rutz::error("invalid rect (left > right)", SRC_POS);
00142
00143 if (B > T)
00144 throw rutz::error("invalid rect (bottom > top)", SRC_POS);
00145
00146 xx = span<V>(L,R);
00147 yy = span<V>(B,T);
00148 return *this;
00149 }
00150
00152 rect<V>& set_lrbt(V L, V R, V B, V T)
00153 {
00154 return this->set_ltrb(L,T,R,B);
00155 }
00156
00158 rect<V>& set_lbwh(V x, V y, V w, V h)
00159 {
00160 xx = span<V>(x, x+rutz::abs(w));
00161 yy = span<V>(y, y+rutz::abs(h));
00162 return *this;
00163 }
00164
00166 rect<V>& set_lbwh(const geom::vec2<V>& xy, const geom::vec2<V>& wh)
00167 {
00168 return set_lbwh(xy.x(), xy.y(), wh.x(), wh.y());
00169 }
00170
00172 rect<V>& set_corners(const geom::vec2<V>& p1, const geom::vec2<V>& p2)
00173 {
00174 xx = span<V>::from_any(p1.x(), p2.x());
00175 yy = span<V>::from_any(p1.y(), p2.y());
00176 return *this;
00177 }
00178
00179 void incr_width(V w) { xx = xx.incr_width(w); }
00180 void incr_height(V h) { yy = yy.incr_width(h); }
00181
00182 void set_width(V w) { xx = xx.with_width(w); }
00183 void set_height(V h) { yy = yy.with_width(h); }
00184
00185 void scale_x(V factor) { xx = xx.scaled_by(factor); }
00186 void scale_y(V factor) { yy = yy.scaled_by(factor); }
00187
00188 void translate(const geom::vec2<V>& dist)
00189 {
00190 xx = xx.shifted_by(dist.x());
00191 yy = yy.shifted_by(dist.y());
00192 }
00193
00194 void scale(const geom::vec2<V>& factors)
00195 {
00196 scale_x(factors.x());
00197 scale_y(factors.y());
00198 }
00199
00200 void set_center(const geom::vec2<V>& point)
00201 {
00202 geom::vec2<V> diff = point - center();
00203 translate(diff);
00204 }
00205
00206 bool is_void() const { return (xx.is_void() || yy.is_void()); }
00207
00208 rect<V> union_with(const rect<V>& other) const
00209 {
00210 return rect<V>(xx.union_with(other.x_span()),
00211 yy.union_with(other.y_span()));
00212 }
00213
00214 void debug_dump() const throw()
00215 {
00216 dbg_eval(0, left());
00217 dbg_eval(0, right());
00218 dbg_eval(0, bottom());
00219 dbg_eval_nl(0, top());
00220 }
00221
00222 private:
00223 geom::span<V> xx;
00224 geom::span<V> yy;
00225 };
00226
00227 typedef rect<double> rectd;
00228 typedef rect<int> recti;
00229
00230 }
00231
00232 static const char __attribute__((used)) vcid_groovx_geom_rect_h_utc20050626084022[] = "$Id: rect.h 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00233 #endif // !GROOVX_GEOM_RECT_H_UTC20050626084022_DEFINED