ViennaGrid - The Vienna Grid Library  2.1.0
viennagrid/algorithm/centroid.hpp
Go to the documentation of this file.
00001 #ifndef VIENNAGRID_ALGORITHM_CENTROID_HPP
00002 #define VIENNAGRID_ALGORITHM_CENTROID_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 
00021 #include "viennagrid/forwards.hpp"
00022 #include "viennagrid/topology/all.hpp"
00023 #include "viennagrid/algorithm/volume.hpp"    //for mesh/segment centroid
00024 #include "viennagrid/accessor.hpp"
00025 
00030 namespace viennagrid
00031 {
00032   namespace detail
00033   {
00034     //
00035     // Calculation of centroid
00036     //
00038     template <typename PointAccessorT, typename ElementT>
00039     typename PointAccessorT::value_type
00040     centroid(PointAccessorT const accessor, ElementT const & cell, viennagrid::triangle_tag)
00041     {
00042       typedef typename PointAccessorT::value_type PointType;
00043       typedef typename viennagrid::result_of::coord<PointType>::type    CoordType;
00044 
00045       typedef typename viennagrid::result_of::const_element_range<ElementT, vertex_tag>::type         VertexOnCellRange;
00046       typedef typename viennagrid::result_of::iterator<VertexOnCellRange>::type            VertexOnCellIterator;
00047 
00048       PointType p0(0.0, 0.0);
00049 
00050       VertexOnCellRange vertices = viennagrid::elements<vertex_tag>(cell);
00051       for (VertexOnCellIterator vocit = vertices.begin();
00052            vocit != vertices.end();
00053            ++vocit)
00054         p0 += accessor(*vocit);
00055 
00056       p0 /= static_cast<CoordType>(vertices.size());
00057 
00058       return p0;
00059     }
00060 
00061     //tetrahedron can reuse the algorithm defined for a triangle
00063     template <typename PointAccessorT, typename ElementT>
00064     typename PointAccessorT::value_type
00065     centroid(PointAccessorT const accessor, ElementT const & cell, viennagrid::tetrahedron_tag)
00066     {
00067       return centroid(accessor, cell, viennagrid::triangle_tag());
00068     }
00069 
00070     //
00071     // Note: This works for rectangles only, but not for general quadrilateral
00072     //
00074     template <typename PointAccessorT, typename ElementT>
00075     typename PointAccessorT::value_type
00076     centroid(PointAccessorT const accessor, ElementT const & cell, viennagrid::quadrilateral_tag)
00077     {
00078       return centroid(accessor, cell, viennagrid::triangle_tag());
00079     }
00080 
00081     //
00082     // Note: This works for cuboids only, but not for general hexahedra
00083     //
00085     template <typename PointAccessorT, typename ElementT>
00086     typename PointAccessorT::value_type
00087     centroid(PointAccessorT const accessor, ElementT const & cell, viennagrid::hexahedron_tag)
00088     {
00089       return centroid(accessor, cell, viennagrid::triangle_tag());
00090     }
00091 
00092 
00093     //a line can reuse the algorithm defined for a triangle
00095     template <typename PointAccessorT, typename ElementT>
00096     typename PointAccessorT::value_type
00097     centroid(PointAccessorT const accessor, ElementT const & cell, viennagrid::simplex_tag<1>)
00098     {
00099       return centroid(accessor, cell, viennagrid::triangle_tag());
00100     }
00101 
00102 
00104     template <typename PointAccessorT, typename ElementT>
00105     typename PointAccessorT::value_type
00106     centroid(PointAccessorT const accessor, ElementT const & cell, viennagrid::hypercube_tag<1>)
00107     {
00108       return centroid(accessor, cell, viennagrid::triangle_tag());
00109     }
00110 
00111 
00112     //a point is degenerate and returns its location
00114     template <typename PointAccessorT, typename ElementT>
00115     typename PointAccessorT::value_type
00116     centroid(PointAccessorT const accessor, ElementT const & cell, viennagrid::vertex_tag)
00117     {
00118       return accessor(cell);
00119     }
00120 
00121 
00122 
00124     template <typename ElementTOrTag, typename MeshSegmentHandleType, typename PointAccessorT>
00125     typename viennagrid::result_of::point<MeshSegmentHandleType>::type
00126     centroid_mesh(MeshSegmentHandleType const & mesh_obj, PointAccessorT const point_accessor)
00127     {
00128       typedef typename viennagrid::result_of::element_tag<ElementTOrTag>::type            ElementTag;
00129       typedef typename viennagrid::result_of::point<MeshSegmentHandleType>::type          PointType;
00130       typedef typename viennagrid::result_of::const_element_range<MeshSegmentHandleType,
00131                                                                 ElementTag>::type         CellRange;
00132       typedef typename viennagrid::result_of::iterator<CellRange>::type                   CellIterator;
00133 
00134       PointType result = 0;
00135       double volume = 0;
00136 
00137       CellRange cells = viennagrid::elements<ElementTag>(mesh_obj);
00138       for (CellIterator cit = cells.begin(); cit != cells.end(); ++cit)
00139       {
00140         double vol_cell = viennagrid::volume( point_accessor, *cit );
00141         result += vol_cell * centroid( point_accessor, *cit);
00142         volume += vol_cell;
00143       }
00144 
00145       return result / volume;
00146     }
00147 
00148   } //namespace detail
00149 
00150 
00151 
00157   template <typename PointAccessorT, typename ElementT>
00158   typename PointAccessorT::value_type
00159   centroid(PointAccessorT const accessor, ElementT const & element)
00160   {
00161     return detail::centroid( accessor, element, typename ElementT::tag());
00162   }
00163 
00168   template <typename ElementTag, typename WrappedConfigT>
00169   typename viennagrid::result_of::point< viennagrid::element<ElementTag,WrappedConfigT> >::type
00170   centroid(viennagrid::element<ElementTag,WrappedConfigT> const & element)
00171   {
00172     return detail::centroid( default_point_accessor(element), element, ElementTag());
00173   }
00174 
00175 
00176 
00183   template<typename ElementTOrTagT, typename WrappedConfigT, typename PointAccessorT>
00184   typename viennagrid::result_of::point< mesh<WrappedConfigT> >::type
00185   centroid(mesh<WrappedConfigT> const & mesh_obj, PointAccessorT const point_accessor)
00186   {
00187     return detail::centroid_mesh<ElementTOrTagT>(mesh_obj, point_accessor);
00188   }
00189 
00195   template<typename WrappedConfigT, typename PointAccessorT>
00196   typename viennagrid::result_of::point< mesh<WrappedConfigT> >::type
00197   centroid(mesh<WrappedConfigT> const & mesh_obj, PointAccessorT const point_accessor)
00198   {
00199     typedef typename viennagrid::result_of::cell_tag< mesh<WrappedConfigT> >::type CellTag;
00200     return detail::centroid_mesh<CellTag>(mesh_obj, point_accessor);
00201   }
00202 
00203 
00209   template<typename ElementTOrTagT, typename WrappedConfigT>
00210   typename viennagrid::result_of::point< mesh<WrappedConfigT> >::type
00211   centroid(mesh<WrappedConfigT> const & mesh_obj)
00212   {
00213     return centroid<ElementTOrTagT>(mesh_obj, default_point_accessor(mesh_obj));
00214   }
00215 
00220   template<typename WrappedConfigT>
00221   typename viennagrid::result_of::point< mesh<WrappedConfigT> >::type
00222   centroid(mesh<WrappedConfigT> const & mesh_obj)
00223   {
00224     typedef typename viennagrid::result_of::cell_tag< mesh<WrappedConfigT> >::type CellTag;
00225     return centroid<CellTag>(mesh_obj, default_point_accessor(mesh_obj));
00226   }
00227 
00228 
00235   template<typename ElementTOrTagT, typename SegmentationT, typename PointAccessorT>
00236   typename viennagrid::result_of::point< segment_handle<SegmentationT> >::type
00237   centroid(segment_handle<SegmentationT> const & segment, PointAccessorT const point_accessor)
00238   {
00239     return detail::centroid_mesh<ElementTOrTagT>(segment, point_accessor);
00240   }
00241 
00247   template<typename SegmentationT, typename PointAccessorT>
00248   typename viennagrid::result_of::point< segment_handle<SegmentationT> >::type
00249   centroid(segment_handle<SegmentationT> const & segment, PointAccessorT const point_accessor)
00250   {
00251     typedef typename viennagrid::result_of::cell_tag< segment_handle<SegmentationT> >::type CellTag;
00252     return detail::centroid_mesh<CellTag>(segment, point_accessor);
00253   }
00254 
00255 
00261   template<typename ElementTOrTagT, typename SegmentationT>
00262   typename viennagrid::result_of::point< segment_handle<SegmentationT> >::type
00263   centroid(segment_handle<SegmentationT> const & segment)
00264   {
00265     return centroid<ElementTOrTagT>(segment, default_point_accessor(segment));
00266   }
00267 
00272   template<typename SegmentationT>
00273   typename viennagrid::result_of::point< segment_handle<SegmentationT> >::type
00274   centroid(segment_handle<SegmentationT> const & segment)
00275   {
00276     typedef typename viennagrid::result_of::cell_tag< segment_handle<SegmentationT> >::type CellTag;
00277     return centroid<CellTag>(segment, default_point_accessor(segment));
00278   }
00279 } //namespace viennagrid
00280 #endif