ViennaGrid - The Vienna Grid Library  2.1.0
viennagrid/algorithm/inclusion.hpp
Go to the documentation of this file.
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