00001
00002
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
00032
00033 #ifndef _ROTATEDBOX_H
00034 #define _ROTATEDBOX_H
00035
00036 #include "CompositeBox.h"
00037 #include "MatrixXD.h"
00038 #include <boost/shared_ptr.hpp>
00039
00040 namespace Go
00041 {
00044
00045
00046
00052 class RotatedBox
00053 {
00054 public:
00059 template <typename RandomAccessIterator>
00060 RotatedBox(RandomAccessIterator start,
00061 int dim,
00062 int num_u,
00063 int num_v,
00064 const Point* axis)
00065 {
00066
00067 setCs(axis, dim);
00068
00069 setFromArray(start, dim, num_u, num_v);
00070 }
00071
00075 RotatedBox(const Point& low, const Point& high,
00076 const Point* axis)
00077 {
00078
00079 setCs(axis, low.size());
00080
00081 setFromPoints(low, high);
00082 }
00083
00085 ~RotatedBox()
00086 {
00087 }
00088
00095 template <typename RandomAccessIterator>
00096 void setFromArray(RandomAccessIterator start,
00097 int dim,
00098 int num_u,
00099 int num_v)
00100 {
00101
00102 std::vector<double> pts(dim*num_u*num_v);
00103 std::copy(start, start + dim*num_u*num_v, &pts[0]);
00104
00105 if (dim == 2) {
00106 for (int i = 0; i < num_u*num_v; ++i) {
00107 Point p(&pts[0] + i*2,
00108 &pts[0] + (i+1)*2, false);
00109 p = cs2_*p;
00110 pts[i*2] = p[0];
00111 pts[i*2+1] = p[1];
00112 }
00113 } else if (dim == 3) {
00114 for (int i = 0; i < num_u*num_v; ++i) {
00115 Point p(&pts[0] + i*3,
00116 &pts[0] + (i+1)*3, false);
00117 p = cs3_*p;
00118 pts[i*3] = p[0];
00119 pts[i*3+1] = p[1];
00120 pts[i*3+2] = p[2];
00121 }
00122 } else {
00123 THROW("Only supports 2 and 3 dimensions.");
00124 }
00125
00126 box_.reset(new CompositeBox(&pts[0], dim, num_u, num_v));
00127 }
00128
00131 void setFromPoints(const Point& low, const Point& high)
00132 {
00133 int dim = low.size();
00134
00135 if (dim == 2) {
00136 Point p1 = cs2_*low;
00137 Point p2 = cs2_*high;
00138
00139 box_.reset(new CompositeBox(p1, p2));
00140 } else if (dim == 3) {
00141 Point p1 = cs3_*low;
00142 Point p2 = cs3_*high;
00143
00144 box_.reset(new CompositeBox(p1, p2));
00145 } else {
00146 THROW("Only supports 2 and 3 dimensions.");
00147 }
00148 }
00149
00151 int dimension() const
00152 {
00153 return box_->dimension();
00154 }
00155
00158 const CompositeBox& box() const
00159 {
00160 return *box_;
00161 }
00162
00166 bool containsPoint(const Point& pt,
00167 double toli = 0.0,
00168 double tole = 0.0) const
00169 {
00170 int dim = dimension();
00171 Point rotp;
00172 if (dim == 2) {
00173 rotp = cs2_*pt;
00174 } else if (dim == 3) {
00175 rotp = cs2_*pt;
00176 } else {
00177 THROW("Only supports 2 and 3 dimensions.");
00178 }
00179 return box_->containsPoint(rotp, toli, tole);
00180 }
00181
00185 bool overlaps(const RotatedBox& box,
00186 double toli = 0.0,
00187 double tole = 0.0) const
00188 {
00189 MatrixXD<double, 2> m2 = cs2_;
00190 m2 += -box.cs2_;
00191 if (m2.frobeniusNorm() > 1e-12) {
00192 THROW("The two RotatedBox objects have different coordinate systems.");
00193 }
00194 MatrixXD<double, 3> m3 = cs3_;
00195 m3 += -box.cs3_;
00196 if (m3.frobeniusNorm() > 1e-12) {
00197 THROW("The two RotatedBox objects have different coordinate systems.");
00198 }
00199 return box_->overlaps(box.box(), toli, tole);
00200 }
00201
00205 bool containsBox(const RotatedBox& box,
00206 double toli = 0.0,
00207 double tole = 0.0) const
00208 {
00209 MatrixXD<double, 2> m2 = cs2_;
00210 m2 += -box.cs2_;
00211 if (m2.frobeniusNorm() > 1e-12) {
00212 THROW("The two RotatedBox objects have different coordinate systems.");
00213 }
00214 MatrixXD<double, 3> m3 = cs3_;
00215 m3 += -box.cs3_;
00216 if (m3.frobeniusNorm() > 1e-12) {
00217 THROW("The two RotatedBox objects have different coordinate systems.");
00218 }
00219 return box_->containsBox(box.box(), toli, tole);
00220 }
00221
00222
00223 private:
00224 void setCs(const Point* axis, int dim)
00225 {
00226
00227
00228
00229
00230 if (dim == 2) {
00231 cs2_(0,0) = axis[0][0];
00232 cs2_(0,1) = axis[0][1];
00233 cs2_(1,0) = -axis[0][1];
00234 cs2_(1,1) = axis[0][0];
00235
00236 cs3_(0,0) = cs3_(0,1) = cs3_(0,2) = 0.0;
00237 cs3_(1,0) = cs3_(1,1) = cs3_(1,2) = 0.0;
00238 cs3_(2,0) = cs3_(2,1) = cs3_(2,2) = 0.0;
00239 } else if (dim == 3) {
00240 Point zaxis = axis[0] % axis[1];
00241 zaxis.normalize();
00242 cs3_(0,0) = axis[0][0];
00243 cs3_(0,1) = axis[0][1];
00244 cs3_(0,2) = axis[0][2];
00245 cs3_(1,0) = axis[1][0];
00246 cs3_(1,1) = axis[1][1];
00247 cs3_(1,2) = axis[1][2];
00248 cs3_(2,0) = zaxis[0];
00249 cs3_(2,1) = zaxis[1];
00250 cs3_(2,2) = zaxis[2];
00251
00252 cs2_(0,0) = cs2_(0,1) = 0.0;
00253 cs2_(1,0) = cs2_(1,1) = 0.0;
00254 } else {
00255 THROW("Only supports 2 and 3 dimensions.");
00256 }
00257 }
00258
00259
00260 boost::shared_ptr<CompositeBox> box_;
00261 MatrixXD<double, 2> cs2_;
00262 MatrixXD<double, 3> cs3_;
00263 };
00264
00266 }
00267
00268
00269
00270 #endif // _ROTATEDBOX_H
00271
00272