//=========================================================================== // GoTools Core - SINTEF Geometry Tools Core library, version 2.0.1 // // Copyright (C) 2000-2007, 2010 SINTEF ICT, Applied Mathematics, Norway. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., // 59 Temple Place - Suite 330, // Boston, MA 02111-1307, USA. // // Contact information: E-mail: tor.dokken@sintef.no // SINTEF ICT, Department of Applied Mathematics, // P.O. Box 124 Blindern, // 0314 Oslo, Norway. // // Other licenses are also available for this software, notably licenses // for: // - Building commercial software. // - Building software whose source code you wish to keep private. //=========================================================================== 00013 #ifndef _ROTATEDBOX_H 00014 #define _ROTATEDBOX_H 00015 00016 #include "GoTools/utils/CompositeBox.h" 00017 #include "GoTools/utils/MatrixXD.h" 00018 #include <boost/shared_ptr.hpp> 00019 00020 namespace Go 00021 { 00022 00023 00029 class RotatedBox 00030 { 00031 public: 00036 template <typename RandomAccessIterator> 00037 RotatedBox(RandomAccessIterator start, 00038 int dim, 00039 int num_u, 00040 int num_v, 00041 const Point* axis) 00042 { 00043 // Make coordinate system. 00044 setCs(axis, dim); 00045 // Make box. 00046 setFromArray(start, dim, num_u, num_v); 00047 } 00048 00052 RotatedBox(const Point& low, const Point& high, 00053 const Point* axis) 00054 { 00055 // Make coordinate system. 00056 setCs(axis, low.size()); 00057 // Make box. 00058 setFromPoints(low, high); 00059 } 00060 00062 ~RotatedBox() 00063 { 00064 } 00065 00072 template <typename RandomAccessIterator> 00073 void setFromArray(RandomAccessIterator start, 00074 int dim, 00075 int num_u, 00076 int num_v) 00077 { 00078 // Make a temporary array of points 00079 std::vector<double> pts(dim*num_u*num_v); 00080 std::copy(start, start + dim*num_u*num_v, &pts[0]); 00081 // Transform the points. 00082 if (dim == 2) { 00083 for (int i = 0; i < num_u*num_v; ++i) { 00084 Point p(&pts[0] + i*2, 00085 &pts[0] + (i+1)*2, false); 00086 p = cs2_*p; 00087 pts[i*2] = p[0]; 00088 pts[i*2+1] = p[1]; 00089 } 00090 } else if (dim == 3) { 00091 for (int i = 0; i < num_u*num_v; ++i) { 00092 Point p(&pts[0] + i*3, 00093 &pts[0] + (i+1)*3, false); 00094 p = cs3_*p; 00095 pts[i*3] = p[0]; 00096 pts[i*3+1] = p[1]; 00097 pts[i*3+2] = p[2]; 00098 } 00099 } else { 00100 THROW("Only supports 2 and 3 dimensions."); 00101 } 00102 // Make the composite box. 00103 box_.reset(new CompositeBox(&pts[0], dim, num_u, num_v)); 00104 } 00105 00108 void setFromPoints(const Point& low, const Point& high) 00109 { 00110 int dim = low.size(); 00111 // Transform the points. 00112 if (dim == 2) { 00113 Point p1 = cs2_*low; 00114 Point p2 = cs2_*high; 00115 // Make the composite box. 00116 box_.reset(new CompositeBox(p1, p2)); 00117 } else if (dim == 3) { 00118 Point p1 = cs3_*low; 00119 Point p2 = cs3_*high; 00120 // Make the composite box. 00121 box_.reset(new CompositeBox(p1, p2)); 00122 } else { 00123 THROW("Only supports 2 and 3 dimensions."); 00124 } 00125 } 00126 00128 int dimension() const 00129 { 00130 return box_->dimension(); 00131 } 00132 00135 const Point& low() const 00136 { 00137 return box_->edge().low(); 00138 } 00139 00142 const Point& high() const 00143 { 00144 return box_->edge().high(); 00145 } 00146 00149 const Point low_rot() const 00150 { 00151 Point low = box_->edge().low(); 00152 Point rot_low; 00153 if (dimension() == 2) { 00154 rot_low = cs2_i_*low; 00155 } else if (dimension() == 3) { 00156 rot_low = cs3_i_*low; 00157 } else { 00158 THROW("Only supports 2 and 3 dimensions."); 00159 } 00160 00161 return rot_low; 00162 } 00163 00166 const Point high_rot() const 00167 { 00168 Point high = box_->edge().high(); 00169 Point rot_high; 00170 if (dimension() == 2) { 00171 rot_high = cs2_i_*high; // We need the inverste rotation ... 00172 } else if (dimension() == 3) { 00173 rot_high = cs3_i_*high; 00174 } else { 00175 THROW("Only supports 2 and 3 dimensions."); 00176 } 00177 00178 return rot_high; 00179 } 00180 00183 const CompositeBox& box() const 00184 { 00185 return *box_; 00186 } 00187 00191 bool containsPoint(const Point& pt, 00192 double toli = 0.0, 00193 double tole = 0.0) const 00194 { 00195 int dim = dimension(); 00196 Point rotp; 00197 if (dim == 2) { 00198 rotp = cs2_*pt; 00199 } else if (dim == 3) { 00200 rotp = cs2_*pt; 00201 } else { 00202 THROW("Only supports 2 and 3 dimensions."); 00203 } 00204 return box_->containsPoint(rotp, toli, tole); 00205 } 00206 00210 bool overlaps(const RotatedBox& box, 00211 double toli = 0.0, 00212 double tole = 0.0) const 00213 { 00214 MatrixXD<double, 2> m2 = cs2_; 00215 m2 += -box.cs2_; 00216 if (m2.frobeniusNorm() > 1e-12) { 00217 THROW("The two RotatedBox objects have different coordinate systems."); 00218 } 00219 MatrixXD<double, 3> m3 = cs3_; 00220 m3 += -box.cs3_; 00221 if (m3.frobeniusNorm() > 1e-12) { 00222 THROW("The two RotatedBox objects have different coordinate systems."); 00223 } 00224 return box_->overlaps(box.box(), toli, tole); 00225 } 00226 00230 bool containsBox(const RotatedBox& box, 00231 double toli = 0.0, 00232 double tole = 0.0) const 00233 { 00234 MatrixXD<double, 2> m2 = cs2_; 00235 m2 += -box.cs2_; 00236 if (m2.frobeniusNorm() > 1e-12) { 00237 THROW("The two RotatedBox objects have different coordinate systems."); 00238 } 00239 MatrixXD<double, 3> m3 = cs3_; 00240 m3 += -box.cs3_; 00241 if (m3.frobeniusNorm() > 1e-12) { 00242 THROW("The two RotatedBox objects have different coordinate systems."); 00243 } 00244 return box_->containsBox(box.box(), toli, tole); 00245 } 00246 00247 00248 private: 00249 void setCs(const Point* axis, int dim) 00250 { 00251 // What we actually compute is the inverse coordinate system. 00252 // This way when we multiply a vector with cs we get its 00253 // coordinates in the system given by (axis[0], Rot(Pi/2)*axis[0]). 00254 // Initiate the other array to zero to avoid an exception 00255 if (dim == 2) { 00256 cs2_(0,0) = axis[0][0]; 00257 cs2_(0,1) = axis[0][1]; 00258 cs2_(1,0) = -axis[0][1]; 00259 cs2_(1,1) = axis[0][0]; 00260 00261 // Setting the inverse matrix. 00262 double det = cs2_(0,0)*cs2_(1,1) - cs2_(0,1)*cs2_(1,0); 00263 double det_inv = 1.0/det; 00264 cs2_i_(0,0) = det_inv*cs2_(1,1); 00265 cs2_i_(0,1) = -det_inv*cs2_(0,1); 00266 cs2_i_(1,0) = -det_inv*cs2_(1,0); 00267 cs2_i_(1,1) = det_inv*cs2_(0,0); 00268 00269 cs3_(0,0) = cs3_(0,1) = cs3_(0,2) = 0.0; 00270 cs3_(1,0) = cs3_(1,1) = cs3_(1,2) = 0.0; 00271 cs3_(2,0) = cs3_(2,1) = cs3_(2,2) = 0.0; 00272 cs3_i_(0,0) = cs3_i_(0,1) = cs3_i_(0,2) = 0.0; 00273 cs3_i_(1,0) = cs3_i_(1,1) = cs3_i_(1,2) = 0.0; 00274 cs3_i_(2,0) = cs3_i_(2,1) = cs3_i_(2,2) = 0.0; 00275 } else if (dim == 3) { 00276 Point zaxis = axis[0] % axis[1]; 00277 zaxis.normalize(); 00278 cs3_(0,0) = axis[0][0]; 00279 cs3_(0,1) = axis[0][1]; 00280 cs3_(0,2) = axis[0][2]; 00281 cs3_(1,0) = axis[1][0]; 00282 cs3_(1,1) = axis[1][1]; 00283 cs3_(1,2) = axis[1][2]; 00284 cs3_(2,0) = zaxis[0]; 00285 cs3_(2,1) = zaxis[1]; 00286 cs3_(2,2) = zaxis[2]; 00287 00288 // Setting the inverse matrix. 00289 double det = cs3_(0,0)*(cs3_(2,2)*cs3_(1,1) - cs3_(2,1)*cs3_(1,2)) - 00290 cs3_(1,0)*(cs3_(2,2)*cs3_(0,1) - cs3_(2,1)*cs3_(0,2)) + 00291 cs3_(2,0)*(cs3_(1,2)*cs3_(0,1) - cs3_(1,1)*cs3_(0,2)); 00292 double det_inv = 1.0/det; 00293 cs3_i_(0,0) = det_inv*(cs3_(2,2)*cs3_(1,1) - cs3_(2,1)*cs3_(1,2)); 00294 cs3_i_(0,1) = -det_inv*(cs3_(2,2)*cs3_(0,1) - cs3_(2,1)*cs3_(0,2)); 00295 cs3_i_(0,2) = det_inv*(cs3_(1,2)*cs3_(0,1) - cs3_(1,1)*cs3_(0,2)); 00296 cs3_i_(1,0) = -det_inv*(cs3_(2,2)*cs3_(1,0) - cs3_(2,0)*cs3_(1,2)); 00297 cs3_i_(1,1) = det_inv*(cs3_(2,2)*cs3_(0,0) - cs3_(2,0)*cs3_(0,2)); 00298 cs3_i_(1,2) = -det_inv*(cs3_(1,2)*cs3_(0,0) - cs3_(1,0)*cs3_(0,2)); 00299 cs3_i_(2,0) = det_inv*(cs3_(2,1)*cs3_(1,0) - cs3_(2,0)*cs3_(1,1)); 00300 cs3_i_(2,1) = -det_inv*(cs3_(2,1)*cs3_(0,0) - cs3_(2,0)*cs3_(0,1)); 00301 cs3_i_(2,2) = det_inv*(cs3_(1,1)*cs3_(0,0) - cs3_(1,0)*cs3_(0,1)); 00302 00303 cs2_(0,0) = cs2_(0,1) = 0.0; 00304 cs2_(1,0) = cs2_(1,1) = 0.0; 00305 cs2_i_(0,0) = cs2_i_(0,1) = 0.0; 00306 cs2_i_(1,0) = cs2_i_(1,1) = 0.0; 00307 } else { 00308 THROW("Only supports 2 and 3 dimensions."); 00309 } 00310 } 00311 00312 // Data members 00313 boost::shared_ptr<CompositeBox> box_; 00314 MatrixXD<double, 2> cs2_; 00315 MatrixXD<double, 3> cs3_; 00316 MatrixXD<double, 2> cs2_i_; // We also store the inverse matrices. 00317 MatrixXD<double, 3> cs3_i_; 00318 }; 00319 00320 } // namespace Go 00321 00322 00323 00324 #endif // _ROTATEDBOX_H 00325