ViennaGrid - The Vienna Grid Library  2.1.0
viennagrid/algorithm/distance.hpp
Go to the documentation of this file.
00001 #ifndef VIENNAGRID_ALGORITHM_DISTANCE_HPP
00002 #define VIENNAGRID_ALGORITHM_DISTANCE_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 <iostream>
00017 #include <sstream>
00018 #include <string>
00019 #include <stdexcept>
00020 #include <limits>
00021 
00022 #include "viennagrid/forwards.hpp"
00023 #include "viennagrid/topology/all.hpp"
00024 #include "viennagrid/algorithm/norm.hpp"
00025 #include "viennagrid/algorithm/inner_prod.hpp"
00026 #include "viennagrid/algorithm/closest_points.hpp"
00027 
00033 namespace viennagrid
00034 {
00035   namespace detail
00036   {
00037 
00038     //
00039     // Distance between points
00040     //
00041 
00042     // Distance between two points:
00043     template <typename PointT1, typename PointT2>
00044     typename viennagrid::result_of::coord<PointT1>::type
00045     distance_impl(PointT1 const & p1,
00046                   PointT2 const & p2)
00047     {
00048       return norm_2(p1 - p2);
00049     }
00050 
00051     template <typename PointT1, typename PointT2>
00052     typename viennagrid::result_of::coord<PointT1>::type
00053     distance_impl( std::pair<PointT1,PointT2> const & pts)
00054     {
00055       return distance_impl(pts.first, pts.second);
00056     }
00057 
00058     template <typename PointAccessorT, typename CoordT1, typename CoordinateSystemT1, typename CoordT2, typename CoordinateSystemT2>
00059     CoordT1
00060     distance_impl(PointAccessorT const,
00061                   spatial_point<CoordT1, CoordinateSystemT1> const & p1,
00062                   spatial_point<CoordT2, CoordinateSystemT2> const & p2)
00063     {
00064       return distance_impl(p1, p2);
00065     }
00066 
00067     template <typename PointAccessorT, typename PointT, typename WrappedConfigT>
00068     typename viennagrid::result_of::coord<PointT>::type
00069     distance_impl(PointAccessorT const accessor,
00070                   PointT const & p1,
00071                   viennagrid::element<viennagrid::vertex_tag, WrappedConfigT> const & v2)
00072     {
00073       return distance_impl(p1, accessor(v2));
00074     }
00075 
00076     template <typename PointAccessorT, typename PointT, typename WrappedConfigT>
00077     typename viennagrid::result_of::coord<typename PointAccessorT::value_type>::type
00078     distance_impl(PointAccessorT const accessor,
00079                   viennagrid::element<viennagrid::vertex_tag, WrappedConfigT> const & v1,
00080                   PointT const & p2)
00081     {
00082       return distance_impl(accessor(v1), p2);
00083     }
00084 
00085     // Distance between vertices: Use point distance
00086     template <typename PointAccessorT, typename PointT, typename WrappedConfigT1, typename WrappedConfigT2>
00087     typename viennagrid::result_of::coord<typename PointAccessorT::value_type>::type
00088     distance_impl(PointAccessorT const accessor,
00089                   viennagrid::element<viennagrid::vertex_tag, WrappedConfigT1> const & v1,
00090                   viennagrid::element<viennagrid::vertex_tag, WrappedConfigT2> const & v2)
00091     {
00092       return distance_impl(accessor(v1), accessor(v2));
00093     }
00094 
00095 
00096 
00097     //
00098     // Generic distance computation: Reuse closest_points()
00099     //
00100     template <typename PointAccessorT, typename SomethingT1, typename SomethingT2>
00101     typename viennagrid::result_of::coord<typename PointAccessorT::value_type>::type
00102     distance_impl(PointAccessorT const accessor,
00103                   SomethingT1 const & el1,
00104                   SomethingT2 const & el2)
00105     {
00106       //typedef typename result_of::point<ElementType1>::type   PointT;
00107       typedef typename PointAccessorT::value_type PointT;
00108 
00109       std::pair<PointT, PointT> points = closest_points(accessor, el1, el2);
00110 
00111       return distance_impl( points );
00112     }
00113 
00114 
00115 
00117 
00118 
00119     template <typename PointT1, typename PointT2>
00120     typename viennagrid::result_of::coord<PointT1>::type
00121     boundary_distance_impl(PointT1 const & p1,
00122                   PointT2 const & p2)
00123     {
00124       return norm_2(p1 - p2);
00125     }
00126 
00127     template <typename PointT1, typename PointT2>
00128     typename viennagrid::result_of::coord<PointT1>::type
00129     boundary_distance_impl( std::pair<PointT1,PointT2> const & pts)
00130     {
00131       return boundary_distance_impl(pts.first, pts.second);
00132     }
00133 
00134     template <typename PointAccessorT, typename CoordT1, typename CoordinateSystemT1, typename CoordT2, typename CoordinateSystemT2>
00135     CoordT1
00136     boundary_distance_impl(PointAccessorT const,
00137                   spatial_point<CoordT1, CoordinateSystemT1> const & p1,
00138                   spatial_point<CoordT2, CoordinateSystemT2> const & p2)
00139     {
00140       return boundary_distance_impl(p1, p2);
00141     }
00142 
00143     template <typename PointAccessorT, typename PointT, typename WrappedConfigT>
00144     typename viennagrid::result_of::coord<PointT>::type
00145     boundary_distance_impl(PointAccessorT const accessor,
00146                   PointT const & p1,
00147                   viennagrid::element<viennagrid::vertex_tag, WrappedConfigT> const & v2)
00148     {
00149       return boundary_distance_impl(p1, accessor(v2));
00150     }
00151 
00152     template <typename PointAccessorT, typename PointT, typename WrappedConfigT>
00153     typename viennagrid::result_of::coord<typename PointAccessorT::value_type>::type
00154     boundary_distance_impl(PointAccessorT const accessor,
00155                   viennagrid::element<viennagrid::vertex_tag, WrappedConfigT> const & v1,
00156                   PointT const & p2)
00157     {
00158       return boundary_distance_impl(accessor(v1), p2);
00159     }
00160 
00161     // Distance between vertices: Use point distance
00162     template <typename PointAccessorT, typename PointT, typename WrappedConfigT1, typename WrappedConfigT2>
00163     typename viennagrid::result_of::coord<typename PointAccessorT::value_type>::type
00164     boundary_distance_impl(PointAccessorT const accessor,
00165                   viennagrid::element<viennagrid::vertex_tag, WrappedConfigT1> const & v1,
00166                   viennagrid::element<viennagrid::vertex_tag, WrappedConfigT2> const & v2)
00167     {
00168       return boundary_distance_impl(accessor(v1), accessor(v2));
00169     }
00170 
00171 
00172 
00173     //
00174     // Generic distance computation: Reuse closest_points()
00175     //
00176     template <typename PointAccessorT, typename SomethingT1, typename SomethingT2>
00177     typename viennagrid::result_of::coord<typename PointAccessorT::value_type>::type
00178     boundary_distance_impl(PointAccessorT const accessor,
00179                            SomethingT1 const & el1,
00180                            SomethingT2 const & el2)
00181     {
00182       //typedef typename result_of::point<ElementType1>::type      PointT;
00183       typedef typename PointAccessorT::value_type PointT;
00184 
00185       std::pair<PointT, PointT> points = closest_points_on_boundary(accessor, el1, el2);
00186 
00187       return boundary_distance_impl(points);
00188     }
00189 
00190   } //namespace detail
00191 
00192   //
00193   // The public interface functions
00194   //
00196   template <typename PointAccessorT, typename SomethingT1, typename SomethingT2>
00197   typename viennagrid::result_of::coord<SomethingT1>::type
00198   distance(PointAccessorT const accessor,
00199            SomethingT1 const & el1,
00200            SomethingT2 const & el2)
00201   {
00202     return detail::distance_impl(accessor, el1, el2);
00203   }
00204 
00205 
00207   template <typename SomethingT1, typename SomethingT2>
00208   typename viennagrid::result_of::coord<SomethingT1>::type
00209   distance(SomethingT1 const & el1,
00210            SomethingT2 const & el2)
00211   {
00212     return detail::distance_impl( default_point_accessor(el1), el1, el2 );
00213   }
00214 
00216   template <typename SomethingT, typename CoordT, typename CoordinateSystemT>
00217   typename viennagrid::result_of::coord<SomethingT>::type
00218   distance(SomethingT const & el1,
00219            spatial_point<CoordT, CoordinateSystemT> const & el2)
00220   {
00221     return detail::distance_impl( default_point_accessor(el1), el1, el2 );
00222   }
00223 
00225   template <typename CoordT, typename CoordinateSystemT, typename SomethingT>
00226   typename viennagrid::result_of::coord<SomethingT>::type
00227   distance(spatial_point<CoordT, CoordinateSystemT> const & el1,
00228            SomethingT const & el2)
00229   {
00230     return detail::distance_impl( default_point_accessor(el2), el1, el2 );
00231   }
00232 
00234   template <typename CoordT1, typename CoordinateSystemT1, typename CoordT2, typename CoordinateSystemT2>
00235   typename viennagrid::result_of::coord< spatial_point<CoordT1, CoordinateSystemT1> >::type
00236   distance(spatial_point<CoordT1, CoordinateSystemT1> const & el1,
00237            spatial_point<CoordT2, CoordinateSystemT2> const & el2)
00238   {
00239     return detail::distance_impl( el1, el2 );
00240   }
00241 
00242 
00244   template<typename WrappedMeshConfigT, typename SegmentationT>
00245   typename result_of::coord< segment_handle<SegmentationT> >::type distance( element<line_tag, WrappedMeshConfigT> const & line, segment_handle<SegmentationT> const & segment_handle )
00246   {
00247     typedef viennagrid::segment_handle<SegmentationT> SegmentHandleType;
00248     typedef typename result_of::const_line_range<SegmentHandleType>::type ConstLineRangeType;
00249     typedef typename result_of::iterator<ConstLineRangeType>::type ConstLineIteratorType;
00250 
00251     typedef typename result_of::coord<SegmentHandleType>::type CoordType;
00252 
00253     ConstLineRangeType lines(segment_handle);
00254     if (lines.empty())
00255       return -1;
00256 
00257     ConstLineIteratorType lit = lines.begin();
00258     CoordType min_distance = distance(line, *(lit++));
00259 
00260     for (; lit != lines.end(); ++lit)
00261     {
00262       CoordType current_distance = distance(line, *lit);
00263       if (current_distance < min_distance)
00264         min_distance = current_distance;
00265     }
00266 
00267     return min_distance;
00268   }
00269 
00270   template<typename SegmentationT, typename WrappedMeshConfigT>
00271   typename result_of::coord< segment_handle<SegmentationT> >::type distance( segment_handle<SegmentationT> const & segment_handle, element<line_tag, WrappedMeshConfigT> const & line )
00272   {
00273     return distance( line, segment_handle );
00274   }
00275 
00276 
00277 
00278 
00279 
00286   template <typename PointAccessorT, typename SomethingT1, typename SomethingT2>
00287   typename viennagrid::result_of::coord<SomethingT1>::type
00288   boundary_distance(PointAccessorT const accessor,
00289                     SomethingT1 const & el1,
00290                     SomethingT2 const & el2)
00291   {
00292     return detail::boundary_distance_impl(accessor, el1, el2);
00293   }
00294 
00296   template <typename SomethingT1, typename SomethingT2>
00297   typename viennagrid::result_of::coord<SomethingT1>::type
00298   boundary_distance(SomethingT1 const & el1,
00299                     SomethingT2 const & el2)
00300   {
00301     return detail::boundary_distance_impl( default_point_accessor(el1), el1, el2 );
00302   }
00303 
00305   template <typename SomethingT, typename CoordT, typename CoordinateSystemT>
00306   typename viennagrid::result_of::coord<SomethingT>::type
00307   boundary_distance(SomethingT const & el1,
00308                     spatial_point<CoordT, CoordinateSystemT> const & el2)
00309   {
00310     return detail::boundary_distance_impl( default_point_accessor(el1), el1, el2 );
00311   }
00312 
00314   template <typename CoordT, typename CoordinateSystemT, typename SomethingT>
00315   typename viennagrid::result_of::coord<SomethingT>::type
00316   boundary_distance(spatial_point<CoordT, CoordinateSystemT> const & el1,
00317                     SomethingT const & el2)
00318   {
00319     return detail::boundary_distance_impl( default_point_accessor(el2), el1, el2 );
00320   }
00321 
00322 
00323 } //namespace viennagrid
00324 #endif