ViennaGrid - The Vienna Grid Library
2.1.0
|
00001 #ifndef VIENNAGRID_ALGORITHM_INCLUSION_HPP 00002 #define VIENNAGRID_ALGORITHM_INCLUSION_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 #include <limits> 00017 #include "viennagrid/point.hpp" 00018 #include "viennagrid/mesh/mesh.hpp" 00019 #include "viennagrid/topology/simplex.hpp" 00020 #include "viennagrid/algorithm/spanned_volume.hpp" 00021 #include "viennagrid/algorithm/detail/numeric.hpp" 00022 00027 namespace viennagrid 00028 { 00029 namespace detail 00030 { 00031 // http://www.blackpawn.com/texts/pointinpoly/ 00033 template<typename PointAccessorT, typename ElementT, typename CoordType, typename CoordinateSystem, typename NumericConfigT> 00034 bool is_inside_impl( PointAccessorT const accessor, 00035 ElementT const & element, viennagrid::triangle_tag, 00036 spatial_point<CoordType, CoordinateSystem> const & p, 00037 NumericConfigT numeric_config ) 00038 { 00039 typedef spatial_point<CoordType, CoordinateSystem> PointType; 00040 typedef typename viennagrid::result_of::coord<PointType>::type NumericType; 00041 00042 PointType const & a = accessor( viennagrid::vertices(element)[0] ); 00043 PointType const & b = accessor( viennagrid::vertices(element)[1] ); 00044 PointType const & c = accessor( viennagrid::vertices(element)[2] ); 00045 00046 PointType v0 = c-a; 00047 PointType v1 = b-a; 00048 PointType v2 = p-a; 00049 00050 NumericType dot00 = viennagrid::inner_prod(v0, v0); 00051 NumericType dot01 = viennagrid::inner_prod(v0, v1); 00052 NumericType dot02 = viennagrid::inner_prod(v0, v2); 00053 NumericType dot11 = viennagrid::inner_prod(v1, v1); 00054 NumericType dot12 = viennagrid::inner_prod(v1, v2); 00055 00056 NumericType denom = static_cast<NumericType>(1) / (dot00 * dot11 - dot01 * dot01); 00057 NumericType u = (dot11*dot02 - dot01*dot12) * denom; 00058 NumericType v = (dot00*dot12 - dot01*dot02) * denom; 00059 00060 NumericType abs_eps = absolute_tolerance<NumericType>(numeric_config); 00061 return (u >= -abs_eps) && (v >= -abs_eps) && (u+v <= static_cast<NumericType>(1) + NumericType(2.0)*abs_eps ); 00062 } 00063 00064 00066 template<typename PointAccessorT, typename ElementT, typename CoordType, typename CoordinateSystem, typename NumericConfigT> 00067 bool is_inside_impl( PointAccessorT const accessor, 00068 ElementT const & element, viennagrid::tetrahedron_tag, 00069 spatial_point<CoordType, CoordinateSystem> const & p, 00070 NumericConfigT numeric_config ) 00071 { 00072 typedef spatial_point<CoordType, CoordinateSystem> PointType; 00073 typedef typename viennagrid::result_of::coord<PointType>::type NumericType; 00074 00075 PointType const & a = accessor( viennagrid::vertices(element)[0] ); 00076 PointType const & b = accessor( viennagrid::vertices(element)[1] ); 00077 PointType const & c = accessor( viennagrid::vertices(element)[2] ); 00078 PointType const & d = accessor( viennagrid::vertices(element)[3] ); 00079 00080 00081 NumericType denom = static_cast<NumericType>(1) / spanned_volume(a,b,c,d); 00082 00083 NumericType A = spanned_volume(p,b,c,d) * denom; 00084 NumericType B = spanned_volume(a,p,c,d) * denom; 00085 NumericType C = spanned_volume(a,b,p,d) * denom; 00086 NumericType D = spanned_volume(a,b,c,p) * denom; 00087 00088 NumericType abs_eps = absolute_tolerance<NumericType>(numeric_config); 00089 return (A >= -abs_eps) && (B >= -abs_eps) && (C >= -abs_eps) && (D >= -abs_eps) && (A+B+C+D <= static_cast<NumericType>(1) + NumericType(2.0)*abs_eps); 00090 } 00091 } 00092 00093 00101 template<typename PointAccessorT, typename ElementT, typename CoordType, typename CoordinateSystem, typename NumericConfigT> 00102 bool is_inside( PointAccessorT const accessor, ElementT const & element, 00103 spatial_point<CoordType, CoordinateSystem> const & point, 00104 NumericConfigT numeric_config ) 00105 { 00106 return detail::is_inside_impl( accessor, element, typename ElementT::tag(), point, numeric_config ); 00107 } 00108 00115 template<typename ElementT, typename CoordType, typename CoordinateSystem, typename NumericConfigT> 00116 bool is_inside( ElementT const & element, spatial_point<CoordType, CoordinateSystem> const & point, NumericConfigT numeric_config ) 00117 { 00118 return is_inside( viennagrid::default_point_accessor(element), element, point, numeric_config ); 00119 } 00120 00121 00127 template<typename ElementT, typename CoordType, typename CoordinateSystem> 00128 bool is_inside( ElementT const & element, spatial_point<CoordType, CoordinateSystem> const & point ) 00129 { 00130 return is_inside( element, point, CoordType(10.0)*std::numeric_limits<CoordType>::epsilon() ); 00131 } 00132 00133 } 00134 00135 00136 #endif