ViennaGrid - The Vienna Grid Library
2.1.0
|
00001 #ifndef VIENNAGRID_POINT_HPP 00002 #define VIENNAGRID_POINT_HPP 00003 00004 /* ======================================================================= 00005 Copyright (c) 2011-2014, Institute for Microelectronics, 00006 Institute for Analysis and Scientific Computing, 00007 TU Wien. 00008 00009 ----------------- 00010 ViennaGrid - The Vienna Grid Library 00011 ----------------- 00012 00013 License: MIT (X11), see file LICENSE in the base directory 00014 ======================================================================= */ 00015 00016 00017 #include <cmath> 00018 #include <assert.h> 00019 #include <stdexcept> 00020 #include <cstddef> 00021 #include <sstream> 00022 00023 #include "viennagrid/forwards.hpp" 00024 00025 #include "viennagrid/storage/static_array.hpp" 00026 00031 namespace viennagrid 00032 { 00033 namespace result_of 00034 { 00036 template <typename PointType> 00037 struct dimension; 00038 00040 template <typename CoordType, typename CoordinateSystem> 00041 struct dimension< spatial_point<CoordType, CoordinateSystem> > 00042 { 00043 static const int value = CoordinateSystem::dim; 00044 }; 00045 00046 00048 template <typename PointType> 00049 struct coordinate_system 00050 { 00051 //by default, we don't know anything about the point type, so let's complain at compile time 00052 typedef typename PointType::ERROR_UNKNOWN_COORDINATE_SYSTEM_FOR_POINT_TYPE type; 00053 }; 00054 00056 template <typename CoordType, typename CoordinateSystem> 00057 struct coordinate_system< spatial_point<CoordType, CoordinateSystem> > 00058 { 00059 typedef CoordinateSystem type; 00060 }; 00061 00062 00064 template <typename PointType> 00065 struct static_size; 00066 00068 template <typename CoordType, typename CoordinateSystem> 00069 struct static_size< spatial_point<CoordType, CoordinateSystem> > 00070 { 00071 static const int value = CoordinateSystem::dim; 00072 }; 00073 00074 } 00075 00077 template <typename PointType> 00078 std::size_t dynamic_size(PointType const & p) 00079 { 00080 return p.size(); 00081 } 00082 00083 template <int d> 00084 struct dim_dispatcher; 00085 00091 template <typename FromPointType, 00092 typename ToPointType, 00093 typename FromCoordinateSystem = typename result_of::coordinate_system<FromPointType>::type, 00094 typename ToCoordinateSystem = typename result_of::coordinate_system<ToPointType>::type 00095 > 00096 class coordinate_converter 00097 { 00098 public: 00100 ToPointType operator()(FromPointType const &) 00101 { 00102 typename FromPointType::ERROR_COORDINATE_SYSTEM_UNKNOWN error_object; 00103 (void)error_object; 00104 } 00105 }; 00106 00107 00109 template <typename FromPointType, 00110 typename ToPointType> 00111 class coordinate_converter<FromPointType, ToPointType, cartesian_cs<2>, polar_cs> 00112 { 00113 public: 00114 ToPointType operator()(FromPointType const & p_in) 00115 { 00116 ToPointType ret; 00117 ret[0] = sqrt(p_in[0] * p_in[0] + p_in[1] * p_in[1]); 00118 ret[1] = atan2(p_in[1], p_in[0]); 00119 return ret; 00120 } 00121 }; 00122 00124 template <typename FromPointType, 00125 typename ToPointType> 00126 class coordinate_converter<FromPointType, ToPointType, cartesian_cs<3>, spherical_cs> 00127 { 00128 public: 00129 ToPointType operator()(FromPointType const & p_in) 00130 { 00131 ToPointType ret; 00132 ret[0] = sqrt(p_in[0] * p_in[0] + p_in[1] * p_in[1] + p_in[2] * p_in[2]); 00133 ret[1] = (std::fabs(ret[0]) > 0) ? acos(p_in[2] / ret[0]) : 0; 00134 ret[2] = atan2(p_in[1], p_in[0]); 00135 return ret; 00136 } 00137 }; 00138 00140 template <typename FromPointType, 00141 typename ToPointType> 00142 class coordinate_converter<FromPointType, ToPointType, cartesian_cs<3>, cylindrical_cs> 00143 { 00144 public: 00145 ToPointType operator()(FromPointType const & p_in) 00146 { 00147 ToPointType ret; 00148 ret[0] = sqrt(p_in[0] * p_in[0] + p_in[1] * p_in[1]); 00149 ret[1] = atan2(p_in[1], p_in[0]); 00150 ret[2] = p_in[2]; 00151 return ret; 00152 } 00153 }; 00154 00155 namespace result_of 00156 { 00158 template <typename PointType> 00159 struct cartesian_point 00160 { 00161 typedef viennagrid::spatial_point<typename result_of::coord<PointType>::type, 00162 viennagrid::cartesian_cs<viennagrid::result_of::static_size<PointType>::value> 00163 > type; 00164 }; 00165 00166 } 00167 00169 template <typename PointType, typename CoordinateSystem> 00170 typename result_of::cartesian_point<PointType>::type 00171 to_cartesian_impl(PointType const & p, CoordinateSystem const &) 00172 { 00173 typedef typename result_of::cartesian_point<PointType>::type CartesianPointType; 00174 00175 return coordinate_converter<PointType, CartesianPointType>()(p); 00176 } 00177 00178 00180 template <typename FromPointType, 00181 typename ToPointType> 00182 class coordinate_converter<FromPointType, ToPointType, polar_cs, cartesian_cs<2> > 00183 { 00184 public: 00185 ToPointType operator()(FromPointType const & p_in) 00186 { 00187 ToPointType ret; 00188 ret[0] = p_in[0] * cos(p_in[1]); 00189 ret[1] = p_in[0] * sin(p_in[1]); 00190 return ret; 00191 } 00192 }; 00193 00194 00196 template <typename FromPointType, 00197 typename ToPointType> 00198 class coordinate_converter<FromPointType, ToPointType, spherical_cs, cartesian_cs<3> > 00199 { 00200 public: 00201 ToPointType operator()(FromPointType const & p_in) 00202 { 00203 ToPointType ret; 00204 ret[0] = p_in[0] * sin(p_in[1]) * cos(p_in[2]); 00205 ret[1] = p_in[0] * sin(p_in[1]) * sin(p_in[2]); 00206 ret[2] = p_in[0] * cos(p_in[1]); 00207 return ret; 00208 } 00209 }; 00210 00212 template <typename FromPointType, 00213 typename ToPointType> 00214 class coordinate_converter<FromPointType, ToPointType, spherical_cs, cylindrical_cs> 00215 { 00216 public: 00217 ToPointType operator()(FromPointType const & p_in) 00218 { 00219 ToPointType ret; 00220 ret[0] = p_in[0] * sin(p_in[1]); //rho 00221 ret[1] = p_in[2]; //phi 00222 ret[2] = p_in[0] * cos(p_in[1]); //z 00223 return ret; 00224 } 00225 }; 00226 00227 00229 template <typename FromPointType, 00230 typename ToPointType> 00231 class coordinate_converter<FromPointType, ToPointType, cylindrical_cs, cartesian_cs<3> > 00232 { 00233 public: 00234 ToPointType operator()(FromPointType const & p_in) 00235 { 00236 ToPointType ret; 00237 ret[0] = p_in[0] * cos(p_in[1]); 00238 ret[1] = p_in[0] * sin(p_in[1]); 00239 ret[2] = p_in[2]; 00240 return ret; 00241 } 00242 }; 00243 00245 template <typename FromPointType, 00246 typename ToPointType> 00247 class coordinate_converter<FromPointType, ToPointType, cylindrical_cs, spherical_cs> 00248 { 00249 public: 00250 ToPointType operator()(FromPointType const & p_in) 00251 { 00252 ToPointType ret; 00253 ret[0] = sqrt(p_in[0] * p_in[0] + p_in[2] * p_in[2]); 00254 ret[1] = (std::fabs(ret[0]) > 0) ? acos(p_in[2] / ret[0]) : 0; 00255 ret[2] = p_in[1]; 00256 return ret; 00257 } 00258 }; 00259 00260 /********************* CoordinateSystem *****************/ 00261 00263 template <int d> 00264 struct cartesian_cs 00265 { 00266 static const int dim = d; 00267 00269 template <typename PointType> 00270 static PointType add(PointType const & p1, PointType const & p2) 00271 { 00272 assert(p1.size() == p2.size()); 00273 00274 PointType ret; 00275 typedef typename PointType::size_type size_type; 00276 for (size_type i=0; i<ret.size(); ++i) 00277 ret[i] = p1[i] + p2[i]; 00278 return ret; 00279 } 00280 00282 template <typename PointType> 00283 static void inplace_add(PointType & p1, PointType const & p2) 00284 { 00285 assert(p1.size() == p2.size()); 00286 00287 typedef typename PointType::size_type size_type; 00288 for (size_type i=0; i<p1.size(); ++i) 00289 p1[i] += p2[i]; 00290 } 00291 00293 template <typename PointType> 00294 static PointType subtract(PointType const & p1, PointType const & p2) 00295 { 00296 typedef typename PointType::size_type size_type; 00297 assert(p1.size() == p2.size()); 00298 00299 PointType ret; 00300 for (size_type i=0; i<ret.size(); ++i) 00301 ret[i] = p1[i] - p2[i]; 00302 return ret; 00303 } 00304 00306 template <typename PointType> 00307 static void inplace_subtract(PointType & p1, PointType const & p2) 00308 { 00309 typedef typename PointType::size_type size_type; 00310 assert(p1.size() == p2.size()); 00311 00312 for (size_type i=0; i<p1.size(); ++i) 00313 p1[i] -= p2[i]; 00314 } 00315 00317 template <typename PointType> 00318 static PointType & inplace_stretch(PointType & p1, typename result_of::coord<PointType>::type factor) 00319 { 00320 typedef typename PointType::size_type size_type; 00321 for (size_type i=0; i<p1.size(); ++i) 00322 p1[i] *= factor; 00323 return p1; 00324 } 00325 00326 }; 00327 00329 template <typename PointType, int d> 00330 PointType const & 00331 to_cartesian_impl(PointType const & p, cartesian_cs<d>) 00332 { 00333 return p; 00334 } 00335 00337 template <typename PointType, int d> 00338 PointType & 00339 to_cartesian_impl(PointType & p, cartesian_cs<d>) 00340 { 00341 return p; 00342 } 00343 00344 00345 //public interface 00349 template <typename PointType> 00350 typename result_of::cartesian_point<PointType>::type 00351 to_cartesian(PointType const & p) 00352 { 00353 return to_cartesian_impl(p, typename result_of::coordinate_system<PointType>::type()); 00354 } 00355 00356 00357 00359 template <typename CSystem> 00360 struct cs_base 00361 { 00363 template <typename PointType> 00364 static PointType add(PointType const & p1, PointType const & p2) 00365 { 00366 static const int DIM = viennagrid::result_of::static_size<PointType>::value; 00367 00368 typedef spatial_point<typename PointType::value_type, 00369 cartesian_cs<DIM> 00370 > CartesianPointType; 00371 00372 assert(p1.size() == p2.size()); 00373 00374 coordinate_converter<PointType, CartesianPointType, 00375 CSystem, cartesian_cs<DIM> > cs_to_cartesian; 00376 coordinate_converter<CartesianPointType, PointType, 00377 cartesian_cs<DIM>, CSystem> cartesian_to_cs; 00378 00379 CartesianPointType cs1 = cs_to_cartesian(p1); 00380 CartesianPointType cs2 = cs_to_cartesian(p2); 00381 CartesianPointType cs_ret = cartesian_cs<DIM>::add(cs1, cs2); 00382 PointType ret = cartesian_to_cs(cs_ret); 00383 00384 return ret; 00385 } 00386 00388 template <typename PointType> 00389 static void inplace_add(PointType & p1, PointType const & p2) 00390 { 00391 static const int DIM = viennagrid::result_of::static_size<PointType>::value; 00392 00393 typedef spatial_point<typename PointType::value_type, 00394 cartesian_cs<DIM> 00395 > CartesianPointType; 00396 00397 assert(p1.size() == p2.size()); 00398 00399 coordinate_converter<PointType, CartesianPointType, CSystem, cartesian_cs<DIM> > cs_to_cartesian; 00400 coordinate_converter<CartesianPointType, PointType, cartesian_cs<DIM>, CSystem> cartesian_to_cs; 00401 00402 CartesianPointType cs1 = cs_to_cartesian(p1); 00403 CartesianPointType cs2 = cs_to_cartesian(p2); 00404 cartesian_cs<DIM>::inplace_add(cs1, cs2); 00405 p1 = cartesian_to_cs(cs1); 00406 } 00407 00409 template <typename PointType> 00410 static PointType subtract(PointType const & p1, PointType const & p2) 00411 { 00412 static const int DIM = viennagrid::result_of::static_size<PointType>::value; 00413 00414 typedef spatial_point<typename PointType::value_type, 00415 cartesian_cs<DIM> 00416 > CartesianPointType; 00417 00418 assert(p1.size() == p2.size()); 00419 00420 coordinate_converter<PointType, CartesianPointType, CSystem, cartesian_cs<DIM> > cs_to_cartesian; 00421 coordinate_converter<CartesianPointType, PointType, cartesian_cs<DIM>, CSystem> cartesian_to_cs; 00422 00423 CartesianPointType cs1 = cs_to_cartesian(p1); 00424 CartesianPointType cs2 = cs_to_cartesian(p2); 00425 CartesianPointType cs_ret = cartesian_cs<DIM>::subtract(cs1, cs2); 00426 PointType ret = cartesian_to_cs(cs_ret); 00427 00428 return ret; 00429 } 00430 00432 template <typename PointType> 00433 static void inplace_subtract(PointType & p1, PointType const & p2) 00434 { 00435 static const int DIM = viennagrid::result_of::static_size<PointType>::value; 00436 00437 typedef spatial_point<typename PointType::value_type, 00438 cartesian_cs<DIM> 00439 > CartesianPointType; 00440 00441 assert(p1.size() == p2.size()); 00442 00443 coordinate_converter<PointType, CartesianPointType, CSystem, cartesian_cs<DIM> > cs_to_cartesian; 00444 coordinate_converter<CartesianPointType, PointType, cartesian_cs<DIM>, CSystem> cartesian_to_cs; 00445 00446 CartesianPointType cs1 = cs_to_cartesian(p1); 00447 CartesianPointType cs2 = cs_to_cartesian(p2); 00448 cartesian_cs<DIM>::inplace_subtract(cs1, cs2); 00449 p1 = cartesian_to_cs(cs1); 00450 } 00451 }; 00452 00454 struct polar_cs : public cs_base<polar_cs> 00455 { 00456 static const int dim = 2; 00457 00458 template <typename PointType> 00459 static PointType & inplace_stretch(PointType & p1, typename result_of::coord<PointType>::type factor) 00460 { 00461 p1[0] *= factor; 00462 return p1; 00463 } 00464 }; 00465 00467 struct spherical_cs : public cs_base<spherical_cs> 00468 { 00469 static const int dim = 3; 00470 00471 template <typename PointType> 00472 static PointType & inplace_stretch(PointType & p1, typename result_of::coord<PointType>::type factor) 00473 { 00474 p1[0] *= factor; 00475 return p1; 00476 } 00477 }; 00478 00480 struct cylindrical_cs : public cs_base<cylindrical_cs> 00481 { 00482 static const int dim = 3; 00483 00485 template <typename PointType> 00486 static PointType & inplace_stretch(PointType & p1, typename result_of::coord<PointType>::type factor) 00487 { 00488 static const int DIM = viennagrid::result_of::static_size<PointType>::value; 00489 00490 typedef spatial_point<typename PointType::value_type, 00491 cartesian_cs<DIM> 00492 > CartesianPointType; 00493 00494 coordinate_converter<PointType, CartesianPointType, cylindrical_cs, cartesian_cs<DIM> > cs_to_cartesian; 00495 coordinate_converter<CartesianPointType, PointType, cartesian_cs<DIM>, cylindrical_cs> cartesian_to_cs; 00496 00497 CartesianPointType cs1 = cs_to_cartesian(p1); 00498 cartesian_cs<DIM>::inplace_stretch(cs1, factor); 00499 p1 = cartesian_to_cs(cs1); 00500 return p1; 00501 } 00502 }; 00503 00504 00505 00506 00507 /***************************** Point Type ************************/ 00508 00510 class point_index_out_of_bounds_exception : public std::exception 00511 { 00512 public: 00513 point_index_out_of_bounds_exception(std::size_t i) : i_(i) {} 00514 00515 virtual const char* what() const throw() 00516 { 00517 std::stringstream ss; 00518 ss << "Point index " << i_ << " out of bounds!"; 00519 return ss.str().c_str(); 00520 } 00521 00522 private: 00523 std::size_t i_; 00524 }; 00525 00526 00528 template <typename CoordType, int d> 00529 struct point_filler 00530 { 00531 static void apply(CoordType * coords, CoordType x, CoordType y, CoordType z) 00532 { 00533 coords[0] = x; 00534 coords[1] = y; 00535 coords[2] = z; 00536 for (int i=3; i<d; ++i) 00537 coords[i] = 0; 00538 } 00539 }; 00540 00542 template <typename CoordType> 00543 struct point_filler<CoordType, 1> 00544 { 00545 static void apply(CoordType * coords, CoordType x, CoordType, CoordType) 00546 { 00547 coords[0] = x; 00548 } 00549 }; 00550 00552 template <typename CoordType> 00553 struct point_filler<CoordType, 2> 00554 { 00555 static void apply(CoordType * coords, CoordType x, CoordType y, CoordType) 00556 { 00557 coords[0] = x; 00558 coords[1] = y; 00559 } 00560 }; 00561 00563 template <typename CoordType> 00564 struct point_filler<CoordType, 3> 00565 { 00566 static void apply(CoordType * coords, CoordType x, CoordType y, CoordType z) 00567 { 00568 coords[0] = x; 00569 coords[1] = y; 00570 coords[2] = z; 00571 } 00572 }; 00573 00574 00575 00581 template <typename CoordType, typename CoordinateSystem> 00582 class spatial_point : public static_array<CoordType, CoordinateSystem::dim> 00583 { 00584 public: 00586 typedef CoordType value_type; 00588 typedef dim_type size_type; 00589 00590 00592 static const int dim = CoordinateSystem::dim; 00593 00595 spatial_point() 00596 { 00597 point_filler<CoordType, dim>::apply( &(*this)[0], 0, 0, 0); //make sure that there is no bogus in the coords-array 00598 } 00599 00601 spatial_point(CoordType x, CoordType y = 0, CoordType z = 0) 00602 { 00603 point_filler<CoordType, dim>::apply( &(*this)[0], x, y, z); 00604 } 00605 00607 template <typename CoordType2, typename CoordinateSystem2> 00608 spatial_point(spatial_point<CoordType2, CoordinateSystem2> const & p2) 00609 { 00610 *this = coordinate_converter<spatial_point<CoordType2, CoordinateSystem2>, spatial_point>()(p2); 00611 } 00612 00613 00615 template <typename CoordType2, typename CoordinateSystem2> 00616 spatial_point & operator=(spatial_point<CoordType2, CoordinateSystem2> const & p2) 00617 { 00618 *this = coordinate_converter<spatial_point<CoordType2, CoordinateSystem2>, spatial_point>()(p2); 00619 return *this; 00620 } 00621 00622 // 00623 // operators: 00624 // 00625 00627 spatial_point operator-() const 00628 { 00629 return spatial_point() - *this; 00630 } 00631 00632 //with point: 00634 spatial_point operator+(spatial_point const & other) const 00635 { 00636 return CoordinateSystem::add(*this, other); 00637 } 00638 00640 spatial_point & operator+=(spatial_point const & other) 00641 { 00642 CoordinateSystem::inplace_add(*this, other); 00643 return *this; 00644 } 00645 00647 spatial_point operator-(spatial_point const & other) const 00648 { 00649 return CoordinateSystem::subtract(*this, other); 00650 } 00651 00653 spatial_point & operator-=(spatial_point const & other) 00654 { 00655 CoordinateSystem::inplace_subtract(*this, other); 00656 return *this; 00657 } 00658 00659 00660 //with CoordType 00662 spatial_point & operator*=(CoordType factor) 00663 { 00664 CoordinateSystem::inplace_stretch(*this, factor); 00665 return *this; 00666 } 00667 00669 spatial_point & operator/=(CoordType factor) 00670 { 00671 CoordinateSystem::inplace_stretch(*this, 1.0 / factor); 00672 return *this; 00673 } 00674 00676 spatial_point operator*(CoordType factor) const 00677 { 00678 spatial_point ret(*this); 00679 return CoordinateSystem::inplace_stretch(ret, factor); 00680 } 00681 00683 spatial_point operator/(CoordType factor) const 00684 { 00685 spatial_point ret(*this); 00686 return CoordinateSystem::inplace_stretch(ret, 1.0 / factor); 00687 } 00688 00689 }; 00690 00691 00693 template<typename CoordType, typename CoordinateSystem> 00694 spatial_point<CoordType, CoordinateSystem> min(const spatial_point<CoordType, CoordinateSystem> & p1, const spatial_point<CoordType, CoordinateSystem> & p2) 00695 { 00696 spatial_point<CoordType, CoordinateSystem> tmp; 00697 for (std::size_t i = 0; i < spatial_point<CoordType, CoordinateSystem>::dim; ++i) 00698 tmp[i] = std::min(p1[i], p2[i]); 00699 return tmp; 00700 } 00701 00703 template<typename CoordType, typename CoordinateSystem> 00704 spatial_point<CoordType, CoordinateSystem> max(const spatial_point<CoordType, CoordinateSystem> & p1, const spatial_point<CoordType, CoordinateSystem> & p2) 00705 { 00706 spatial_point<CoordType, CoordinateSystem> tmp; 00707 for (std::size_t i = 0; i < spatial_point<CoordType, CoordinateSystem>::dim; ++i) 00708 tmp[i] = std::max(p1[i], p2[i]); 00709 return tmp; 00710 } 00711 00712 00714 template <typename CoordType, typename CoordinateSystem> 00715 spatial_point<CoordType, CoordinateSystem> 00716 operator*(double val, spatial_point<CoordType, CoordinateSystem> const & p) 00717 { 00718 return p * val; 00719 } 00720 00722 template <typename CoordType, typename CoordinateSystem> 00723 std::ostream& operator << (std::ostream & os, spatial_point<CoordType, CoordinateSystem> const & p) 00724 { 00725 typedef typename spatial_point<CoordType, CoordinateSystem>::size_type size_type; 00726 os << "("; 00727 for (size_type i=0; i<static_cast<size_type>(CoordinateSystem::dim); ++i) 00728 os << p[i] << (i == static_cast<size_type>(CoordinateSystem::dim)-1 ? "" :" "); 00729 os << ")"; 00730 return os; 00731 } 00732 00733 00735 struct point_less 00736 { 00737 template <typename PointType> 00738 bool operator()(PointType const & p1, PointType const & p2) const 00739 { 00740 for (std::size_t i=0; i<p1.size(); ++i) 00741 { 00742 if (p1[i] < p2[i]) 00743 return true; 00744 else if (p1[i] > p2[i]) 00745 return false; 00746 } 00747 return false; 00748 } 00749 }; 00750 00751 namespace result_of 00752 { 00754 template<typename CoordType, typename CoordinateSystem> 00755 struct point< spatial_point<CoordType, CoordinateSystem> > 00756 { 00757 typedef spatial_point<CoordType, CoordinateSystem> type; 00758 }; 00759 00760 template<typename CoordType, typename CoordinateSystem> 00761 struct coord< spatial_point<CoordType, CoordinateSystem> > 00762 { 00763 typedef CoordType type; 00764 }; 00765 00766 template<typename CoordType, typename CoordinateSystem> 00767 struct geometric_dimension< spatial_point<CoordType, CoordinateSystem> > 00768 { 00769 static const int value = spatial_point<CoordType, CoordinateSystem>::dim; 00770 }; 00772 } 00773 00774 } 00775 #endif