LCOV - code coverage report
Current view: top level - ugbase/lib_disc/common - geometry_util.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 140 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 43 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2010-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Andreas Vogel
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #ifndef __H__UG__LIB_DISC__COMMON__GEOMETRY_UTIL__
      34              : #define __H__UG__LIB_DISC__COMMON__GEOMETRY_UTIL__
      35              : 
      36              : #include <vector>
      37              : #include <cmath>
      38              : 
      39              : #include "common/common.h"
      40              : #include "lib_disc/reference_element/reference_element.h"
      41              : #include "lib_disc/reference_element/element_list_traits.h"
      42              : #include "lib_disc/domain_traits.h"
      43              : #include "common/util/provider.h"
      44              : 
      45              : namespace ug{
      46              : 
      47              : ///////////////////////////////////////////////////////////////
      48              : /// Volume of an Element in a given Dimension
      49              : template <typename TRefElem, int TWorldDim>
      50              : inline number ElementSize(const MathVector<TWorldDim>* vCornerCoords);
      51              : 
      52              : ///////////////////////////////////////////////////////////////
      53              : ///////////////////////////////////////////////////////////////
      54              : // 1D Reference Elements
      55              : ///////////////////////////////////////////////////////////////
      56              : ///////////////////////////////////////////////////////////////
      57              : 
      58              : ///////////////////////////////////////////////////////////////
      59              : /// Volume of a Line in 1d
      60              : /**
      61              :  * This function returns the volume of a line in 1d.
      62              :  *
      63              :  * \param[in]   vCornerCoords   Vector of corner coordinates (2 corners)
      64              :  * \return              number                  Volume of Line
      65              :  */
      66              : template <>
      67              : inline number ElementSize<ReferenceEdge, 1>(const MathVector<1>* vCornerCoords)
      68              : {
      69              :         return VecDistance(vCornerCoords[0], vCornerCoords[1]);
      70              : }
      71              : 
      72              : ///////////////////////////////////////////////////////////////
      73              : /// Volume of a Line in 2d
      74              : /**
      75              :  * This function returns the volume of a line in 2d.
      76              :  *
      77              :  * \param[in]   vCornerCoords   Vector of corner coordinates (2 corners)
      78              :  * \return              number                  Volume of Line
      79              :  */
      80              : template <>
      81              : inline number ElementSize<ReferenceEdge, 2>(const MathVector<2>* vCornerCoords)
      82              : {
      83            0 :         return VecDistance(vCornerCoords[0], vCornerCoords[1]);
      84              : }
      85              : 
      86              : ///////////////////////////////////////////////////////////////
      87              : /// Volume of a Line in 3d
      88              : /**
      89              :  * This function returns the volume of a line in 3d.
      90              :  *
      91              :  * \param[in]   vCornerCoords   Vector of corner coordinates (2 corners)
      92              :  * \return              number                  Volume of Line
      93              :  */
      94              : template <>
      95            0 : inline number ElementSize<ReferenceEdge, 3>(const MathVector<3>* vCornerCoords)
      96              : {
      97            0 :         return VecDistance(vCornerCoords[0], vCornerCoords[1]);
      98              : }
      99              : 
     100              : ///////////////////////////////////////////////////////////////
     101              : ///////////////////////////////////////////////////////////////
     102              : // 2D Reference Elements
     103              : ///////////////////////////////////////////////////////////////
     104              : ///////////////////////////////////////////////////////////////
     105              : 
     106              : ///////////////////////////////////////////////////////////////
     107              : /// Volume of a Triangle in 2d
     108              : /**
     109              :  * This function returns the volume of a triangle in 2d.
     110              :  * The Volume is computed via:
     111              :  *      F = 1/2 * fabs( (x2-x1)*(y1-y0) - (x1-x0)*(y2-y0) )
     112              :  *
     113              :  *
     114              :  * \param[in]   vCornerCoords   Vector of corner coordinates (3 corners)
     115              :  * \return              number                  Volume of Triangle
     116              :  */
     117              : template <>
     118              : inline number ElementSize<ReferenceTriangle, 2>(const MathVector<2>* vCornerCoords)
     119              : {
     120            0 :         return(0.5*fabs((vCornerCoords[1][1]-vCornerCoords[0][1])*(vCornerCoords[2][0]-vCornerCoords[0][0])
     121            0 :                                    -(vCornerCoords[1][0]-vCornerCoords[0][0])*(vCornerCoords[2][1]-vCornerCoords[0][1])));
     122              : }
     123              : 
     124              : ///////////////////////////////////////////////////////////////
     125              : /// Volume of a Triangle in 3d
     126              : /**
     127              :  * This function returns the volume of a triangle in 3d.
     128              :  * The Volume is computed via:
     129              :  *      F = 1/2 * | (c - a) x (b - a) | (Here, a,b,c are the vectors of the corners)
     130              :  *
     131              :  * \param[in]   vCornerCoords   Vector of corner coordinates (3 corners)
     132              :  * \return              number                  Volume of Triangle
     133              :  */
     134              : template <>
     135            0 : inline number ElementSize<ReferenceTriangle, 3>(const MathVector<3>* vCornerCoords)
     136              : {
     137              :         MathVector<3> x10, x20, n;
     138              : 
     139              :         VecSubtract(x10, vCornerCoords[1], vCornerCoords[0]);
     140              :         VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
     141            0 :         VecCross(n, x10, x20);
     142              : 
     143            0 :         return(0.5 * VecTwoNorm(n) );
     144              : }
     145              : 
     146              : ///////////////////////////////////////////////////////////////
     147              : /// Volume of a Quadrilateral in 2d
     148              : /**
     149              :  * This function returns the volume of a quadrilateral in 2d.
     150              :  * The Volume is computed via:
     151              :  *      F = 1/2 * | (y3-y1)*(x2-x0) - (x3-x1)*(y2-y0) |
     152              :  *
     153              :  * \param[in]   vCornerCoords   Vector of corner coordinates (4 corners)
     154              :  * \return              number                  Volume of Quadrilateral
     155              :  */
     156              : template <>
     157              : inline number ElementSize<ReferenceQuadrilateral, 2>(const MathVector<2>* vCornerCoords)
     158              : {
     159            0 :         return( 0.5*fabs( (vCornerCoords[3][1]-vCornerCoords[1][1])*(vCornerCoords[2][0]-vCornerCoords[0][0])
     160            0 :                                          -(vCornerCoords[3][0]-vCornerCoords[1][0])*(vCornerCoords[2][1]-vCornerCoords[0][1]) ) );
     161              : }
     162              : 
     163              : ///////////////////////////////////////////////////////////////
     164              : /// Volume of a Quadrilateral in 3d
     165              : /**
     166              :  * This function returns the volume of a quadrilateral in 3d.
     167              :  * The Volume is computed via:
     168              :  *      F = 1/2 * | (c - a) x (d - b) |  (Here, a,b,c,d are the vectors of the corners)
     169              :  *
     170              :  * The corner coordinates must be given in counter - clockwise order
     171              :  *
     172              :  * \param[in]   vCornerCoords   Vector of corner coordinates (4 corners)
     173              :  * \return              number                  Volume of Quadrilateral
     174              :  */
     175              : template <>
     176            0 : inline number ElementSize<ReferenceQuadrilateral, 3>(const MathVector<3>* vCornerCoords)
     177              : {
     178              :         MathVector<3> x20, x31, n;
     179              : 
     180              :         VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
     181              :         VecSubtract(x31, vCornerCoords[3], vCornerCoords[1]);
     182            0 :         VecCross(n, x20, x31);
     183              : 
     184            0 :         return(0.5 * VecTwoNorm(n) );
     185              : }
     186              : 
     187              : 
     188              : ///////////////////////////////////////////////////////////////
     189              : ///////////////////////////////////////////////////////////////
     190              : // 3D Reference Elements
     191              : ///////////////////////////////////////////////////////////////
     192              : ///////////////////////////////////////////////////////////////
     193              : 
     194              : ///////////////////////////////////////////////////////////////
     195              : /// Volume of a Tetrahedron in 3d
     196              : /**
     197              :  * This function returns the volume of a tetrahedron in 3d.
     198              :  * The Volume is computed via:
     199              :  *      V = 1/6 * | ( (b - a) x (c - a) ) * (d - a) |  (Here, a,b,c,d are the vectors of the corners)
     200              :  *
     201              :  * This is motivated by the formula: V = 1/3 * (S * h) with
     202              :  * - S is the area of the base
     203              :  * - h is the height
     204              :  *
     205              :  * \param[in]   vCornerCoords   Vector of corner coordinates (4 corners)
     206              :  * \return              number                  Volume of Tetrahedron
     207              :  */
     208              : template <>
     209            0 : inline number ElementSize<ReferenceTetrahedron, 3>(const MathVector<3>* vCornerCoords)
     210              : {
     211              :         MathVector<3> x10, x20, x30, n;
     212              : 
     213              :         VecSubtract(x10, vCornerCoords[1], vCornerCoords[0]);
     214              :         VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
     215              :         VecSubtract(x30, vCornerCoords[3], vCornerCoords[0]);
     216            0 :         VecCross(n, x10, x20);
     217              : 
     218            0 :         return (1./6.) * fabs ( VecDot(n, x30) );
     219              : }
     220              : 
     221              : ///////////////////////////////////////////////////////////////
     222              : /// Volume of a Pyramid in 3d
     223              : /**
     224              :  * This function returns the volume of a pyramid in 3d.
     225              :  * The volume is computed via: V = 1/3 * (S * h) with
     226              :  * - S is the area of the base
     227              :  * - h is the height
     228              :  *
     229              :  * The corner coordinates must be given as prescribed by the reference element
     230              :  *
     231              :  * \param[in]   vCornerCoords   Vector of corner coordinates (5 corners)
     232              :  * \return              number                  Volume of Pyramid
     233              :  */
     234              : template <>
     235            0 : inline number ElementSize<ReferencePyramid, 3>(const MathVector<3>* vCornerCoords)
     236              : {
     237              :         MathVector<3> x20, x31, x40, n;
     238              : 
     239              :         VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
     240              :         VecSubtract(x31, vCornerCoords[3], vCornerCoords[1]);
     241              :         VecSubtract(x40, vCornerCoords[4], vCornerCoords[0]);
     242            0 :         VecCross(n, x20, x31);
     243              : 
     244            0 :         return (1./6.) * VecDot(n, x40);
     245              : }
     246              : 
     247              : ///////////////////////////////////////////////////////////////
     248              : /// Volume of a Prism in 3d
     249              : /**
     250              :  * This function returns the volume of a prism in 3d. Therefore, the
     251              :  * element is divided into pyramid {x0, x_1, x_4, x_3; x_5} and  a
     252              :  * tetrahedron {x_0, x_1, x_2; x_5}, whose volumes are computed and added.
     253              :  *
     254              :  * The corner coordinates must be given as prescribed by the reference element
     255              :  *
     256              :  * \param[in]   vCornerCoords   Vector of corner coordinates (6 corners)
     257              :  * \return              number                  Volume of Prism
     258              :  */
     259              : template <>
     260            0 : inline number ElementSize<ReferencePrism, 3>(const MathVector<3>* vCornerCoords)
     261              : {
     262              :         MathVector<3> x40, x13, x10, x20, x50, m, n;
     263              : 
     264              :         VecSubtract(x40, vCornerCoords[4], vCornerCoords[0]);
     265              :         VecSubtract(x13, vCornerCoords[1], vCornerCoords[3]);
     266              :         VecSubtract(x10, vCornerCoords[1], vCornerCoords[0]);
     267              :         VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
     268              : 
     269              :         // height for both subelements
     270              :         VecSubtract(x50, vCornerCoords[5], vCornerCoords[0]);
     271              : 
     272            0 :         VecCross(m, x40, x13); // base of pyramid
     273            0 :         VecCross(n, x10, x20); // base of tetrahedron
     274              : 
     275              :         // n = n + m
     276              :         VecAppend(n, m);
     277              : 
     278            0 :         return (1./6.) * VecDot(n, x50);
     279              : }
     280              : 
     281              : ///////////////////////////////////////////////////////////////
     282              : /// Volume of a Hexahedron in 3d
     283              : /**
     284              :  * This function returns the volume of a hexahedron in 3d. Therefore, the
     285              :  * element is divided into two prisms:
     286              :  *  1) {x0, x_1, x_2, x_4; x_5, x_6} and
     287              :  *  2) {x0, x_2, x_3, x_4; x_6, x_7}
     288              :  *
     289              :  * The corner coordinates must be given as prescribed by the reference element
     290              :  *
     291              :  * \param[in]   vCornerCoords   Vector of corner coordinates (8 corners)
     292              :  * \return              number                  Volume of Hexahedron
     293              :  */
     294              : template <>
     295            0 : inline number ElementSize<ReferenceHexahedron, 3>(const MathVector<3>* vCornerCoords)
     296              : {
     297              :         MathVector<3> x50, x14, x10, x20, x60, m1, n1;
     298              :         MathVector<3>      x24,      x30, x70, m2, n2;
     299              : 
     300              :         // 1. prism
     301              :         VecSubtract(x50, vCornerCoords[5], vCornerCoords[0]);
     302              :         VecSubtract(x14, vCornerCoords[1], vCornerCoords[4]);
     303              :         VecSubtract(x10, vCornerCoords[1], vCornerCoords[0]);
     304              :         VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
     305              :         VecSubtract(x60, vCornerCoords[6], vCornerCoords[0]);
     306              : 
     307            0 :         VecCross(m1, x50, x14); // base of pyramid
     308            0 :         VecCross(n1, x10, x20); // base of tetrahedron
     309              : 
     310              :         // n1 = n1 + m1
     311              :         VecAppend(n1, m1);
     312              : 
     313              :         // 2. prism
     314              :         //VecSubtract(x60, vCornerCoords[6], vCornerCoords[0]);
     315              :         VecSubtract(x24, vCornerCoords[2], vCornerCoords[4]);
     316              :         //VecSubtract(x20, vCornerCoords[2], vCornerCoords[0]);
     317              :         VecSubtract(x30, vCornerCoords[3], vCornerCoords[0]);
     318              :         VecSubtract(x70, vCornerCoords[7], vCornerCoords[0]);
     319              : 
     320            0 :         VecCross(m2, x60, x24); // base of pyramid
     321            0 :         VecCross(n2, x20, x30); // base of tetrahedron
     322              : 
     323              :         // n2 = n2 + m2
     324              :         VecAppend(n2, m2);
     325              : 
     326            0 :         return (1./6.) * (VecDot(n1, x60) + VecDot(n2, x70));
     327              : }
     328              : 
     329              : ///////////////////////////////////////////////////////////////
     330              : /// Volume of an Octahedron in 3d
     331              : /**
     332              :  * This function returns the volume of an octhedron in 3d
     333              :  * by calculating the volumes of the upper and lower pyramid
     334              :  * the octahedron consists of.
     335              :  * The pyramidal volumes are computed via: V = 1/3 * (S * h) with
     336              :  * - S is the area of the base
     337              :  * - h is the height
     338              :  *
     339              :  * The corner coordinates must be given as prescribed by the reference element
     340              :  *
     341              :  * \param[in]   vCornerCoords   Vector of corner coordinates (6 corners)
     342              :  * \return              number                  Volume of Octahedron
     343              :  */
     344              : template <>
     345            0 : inline number ElementSize<ReferenceOctahedron, 3>(const MathVector<3>* vCornerCoords)
     346              : {
     347              :         MathVector<3> x31, x42, x51, n;
     348              :         MathVector<3>                     x01;
     349              : 
     350              :         VecSubtract(x31, vCornerCoords[3], vCornerCoords[1]);
     351              :         VecSubtract(x42, vCornerCoords[4], vCornerCoords[2]);
     352              :         VecSubtract(x51, vCornerCoords[5], vCornerCoords[1]);
     353            0 :         VecCross(n, x31, x42);
     354              : 
     355              :         //VecSubtract(x31, vCornerCoords[3], vCornerCoords[1]);
     356              :         //VecSubtract(x42, vCornerCoords[4], vCornerCoords[2]);
     357              :         VecSubtract(x01, vCornerCoords[0], vCornerCoords[1]);
     358              :         //VecCross(n, x31, x42);
     359              : 
     360            0 :         number volTopPyr        = (1./6.) * fabs(VecDot(n, x51));
     361            0 :         number volBottomPyr = (1./6.) * fabs(VecDot(n, x01));
     362              : 
     363            0 :         return volTopPyr + volBottomPyr;
     364              : }
     365              : 
     366              : ///////////////////////////////////////////////////////////////
     367              : //      run-time size of element
     368              : ///////////////////////////////////////////////////////////////
     369              : 
     370              : template <int dim>
     371              : inline number ElementSize(ReferenceObjectID roid, const MathVector<dim>* vCornerCoords);
     372              : 
     373              : template <>
     374            0 : inline number ElementSize<1>(ReferenceObjectID roid, const MathVector<1>* vCornerCoords)
     375              : {
     376            0 :         switch(roid)
     377              :         {
     378              :                 case ROID_VERTEX: return 1.0;
     379            0 :                 case ROID_EDGE: return ElementSize<ReferenceEdge, 1>(vCornerCoords);
     380            0 :                 default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 1.");
     381              :         }
     382              : }
     383              : 
     384              : template <>
     385            0 : inline number ElementSize<2>(ReferenceObjectID roid, const MathVector<2>* vCornerCoords)
     386              : {
     387            0 :         switch(roid)
     388              :         {
     389              :                 case ROID_VERTEX: return 1.0;
     390            0 :                 case ROID_EDGE: return ElementSize<ReferenceEdge, 2>(vCornerCoords);
     391            0 :                 case ROID_TRIANGLE: return ElementSize<ReferenceTriangle, 2>(vCornerCoords);
     392            0 :                 case ROID_QUADRILATERAL: return ElementSize<ReferenceQuadrilateral, 2>(vCornerCoords);
     393            0 :                 default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 2.");
     394              :         }
     395              : }
     396              : 
     397              : template <>
     398            0 : inline number ElementSize<3>(ReferenceObjectID roid, const MathVector<3>* vCornerCoords)
     399              : {
     400            0 :         switch(roid)
     401              :         {
     402              :                 case ROID_VERTEX: return 1.0;
     403            0 :                 case ROID_EDGE: return ElementSize<ReferenceEdge, 3>(vCornerCoords);
     404            0 :                 case ROID_TRIANGLE: return ElementSize<ReferenceTriangle, 3>(vCornerCoords);
     405            0 :                 case ROID_QUADRILATERAL: return ElementSize<ReferenceQuadrilateral, 3>(vCornerCoords);
     406            0 :                 case ROID_TETRAHEDRON: return ElementSize<ReferenceTetrahedron, 3>(vCornerCoords);
     407            0 :                 case ROID_PYRAMID: return ElementSize<ReferencePyramid, 3>(vCornerCoords);
     408            0 :                 case ROID_PRISM: return ElementSize<ReferencePrism, 3>(vCornerCoords);
     409            0 :                 case ROID_HEXAHEDRON: return ElementSize<ReferenceHexahedron, 3>(vCornerCoords);
     410            0 :                 case ROID_OCTAHEDRON: return ElementSize<ReferenceOctahedron, 3>(vCornerCoords);
     411            0 :                 default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 3.");
     412              :         }
     413              : }
     414              : 
     415              : ///////////////////////////////////////////////////////////////
     416              : ///////////////////////////////////////////////////////////////
     417              : // Normals on Elements
     418              : ///////////////////////////////////////////////////////////////
     419              : ///////////////////////////////////////////////////////////////
     420              : 
     421              : ///////////////////////////////////////////////////////////////
     422              : /// Normal to an Element in a given Dimension
     423              : template <typename TRefElem, int TWorldDim>
     424              : inline void ElementNormal(MathVector<TWorldDim>& normalOut, const MathVector<TWorldDim>* vCornerCoords);
     425              : 
     426              : ///////////////////////////////////////////////////////////////
     427              : /// Normal to a Point in 1d
     428              : /**
     429              :  * This function returns the normal of a point in 1d.
     430              :  * This always 1.0.
     431              :  *
     432              :  * \param[in]   vCornerCoords   Vector of corner coordinates
     433              :  * \param[out]  normalOut               Normal
     434              :  */
     435              : template <>
     436              : inline void ElementNormal<ReferenceVertex, 1>(MathVector<1>& normalOut, const MathVector<1>* vCornerCoords)
     437              : {
     438            0 :         normalOut[0] = 1.0;
     439              : }
     440              : 
     441              : ///////////////////////////////////////////////////////////////
     442              : /// Normal to a Point in 2d
     443              : /**
     444              :  * This function returns the normal of a point in 2d.
     445              :  * This can only be understood as the normal on a corner of an edge in 2d.
     446              :  * Therefore, it will be assumed that vCornerCoords has exactly 2 entries
     447              :  * defining the edge. Then the normal is the one-dim. normal on the first vertex
     448              :  * embedded in the 1D subspace defined by the edge.
     449              :  *
     450              :  * \param[in]   vCornerCoords   Vector of corner coordinates
     451              :  * \param[out]  normalOut               Normal
     452              :  */
     453              : template <>
     454            0 : inline void ElementNormal<ReferenceVertex, 2>(MathVector<2>& normalOut, const MathVector<2>* vCornerCoords)
     455              : {
     456              :         try
     457              :         {
     458              :                 normalOut = vCornerCoords[0];
     459              :                 normalOut -= vCornerCoords[1];
     460            0 :                 VecNormalize(normalOut, normalOut);
     461              :         }
     462              :         UG_CATCH_THROW("Element normal can not be computed. Maybe there are not enough vertices to work on.")
     463            0 : }
     464              : 
     465              : ///////////////////////////////////////////////////////////////
     466              : /// Normal to a Point in 3d
     467              : /**
     468              :  * This function returns the normal of a point in 3d.
     469              :  * This can only be understood as the normal on a corner of an edge in 3d.
     470              :  * Therefore, it will be assumed that vCornerCoords has exactly 2 entries
     471              :  * defining the edge. Then the normal is the one-dim. normal on the first vertex
     472              :  * embedded in the 1D subspace defined by the edge.
     473              :  *
     474              :  * \param[in]   vCornerCoords   Vector of corner coordinates
     475              :  * \param[out]  normalOut               Normal
     476              :  */
     477              : template <>
     478            0 : inline void ElementNormal<ReferenceVertex, 3>(MathVector<3>& normalOut, const MathVector<3>* vCornerCoords)
     479              : {
     480              :         try
     481              :         {
     482              :                 normalOut = vCornerCoords[0];
     483              :                 normalOut -= vCornerCoords[1];
     484            0 :                 VecNormalize(normalOut, normalOut);
     485              :         }
     486              :         UG_CATCH_THROW("Element normal can not be computed. Maybe there are not enough vertices to work on.")
     487            0 : }
     488              : 
     489              : ///////////////////////////////////////////////////////////////
     490              : /// Normal to a Line in 2d
     491              : /**
     492              :  * This function returns the normal of a line in 2d.
     493              :  * The normal is in clockwise direction to the vector (x1-x0).
     494              :  * The norm of the normal is the size of the line.
     495              :  *
     496              :  * \param[in]   vCornerCoords   Vector of corner coordinates
     497              :  * \param[out]  normalOut               Normal
     498              :  */
     499              : template <>
     500              : inline void ElementNormal<ReferenceEdge, 2>(MathVector<2>& normalOut, const MathVector<2>* vCornerCoords)
     501              : {
     502              :         MathVector<2> diff(vCornerCoords[1]);
     503              :         diff -= vCornerCoords[0];
     504              : 
     505            0 :         normalOut[0] = diff[1];
     506            0 :         normalOut[1] = -diff[0];
     507            0 : }
     508              : 
     509              : ///////////////////////////////////////////////////////////////
     510              : /// Normal to a Line in 3d
     511              : /**
     512              :  * This function returns the normal of a line in 3d.
     513              :  * This can only be understood as the normal on an edge in a 2d manifold
     514              :  * defined by at least a triangle. Therefore, it is assumed that vCornerCoords
     515              :  * contains at least three vertices.
     516              :  * The normal is computed as the outer normal on the first edge (v2-v1) of the triangle
     517              :  * and embedded in the 2d subspace defined by the triangle.
     518              :  * The norm of the normal is the size of the line.
     519              :  *
     520              :  * \param[in]   vCornerCoords   Vector of corner coordinates
     521              :  * \param[out]  normalOut               Normal
     522              :  */
     523              : template <>
     524            0 : inline void ElementNormal<ReferenceEdge, 3>(MathVector<3>& normalOut, const MathVector<3>* vCornerCoords)
     525              : {
     526              :         try
     527              :         {
     528              :                 // normal on triangle
     529              :                 MathVector<3> edge0, edge1;
     530              :                 VecSubtract(edge0, vCornerCoords[1], vCornerCoords[0]);
     531              :                 VecSubtract(edge1, vCornerCoords[2], vCornerCoords[1]);
     532            0 :                 VecCross(normalOut, edge0, edge1);
     533              :                 // normal an edge is edge x normal on triangle
     534            0 :                 VecCross(normalOut, edge0, normalOut);
     535              :                 // scale
     536            0 :                 VecNormalize(normalOut, normalOut);
     537              :                 VecScale(normalOut, normalOut, VecTwoNorm(edge0));
     538              :         }
     539              :         UG_CATCH_THROW("Element normal can not be computed. Maybe there are not enough vertices to work on.")
     540            0 : }
     541              : 
     542              : ///////////////////////////////////////////////////////////////
     543              : /// Normal to a Triangle in 3d
     544              : /**
     545              :  * This function returns the normal of a triangle in 3d.
     546              :  * The orientation is right-handed (i.e. forming with the four fingers of the
     547              :  * right hand a circle in direction of the corner nodes, the thumb points in
     548              :  * the direction of the normal)
     549              :  *
     550              :  * The norm of the normal is the size of the triangle.
     551              :  *
     552              :  * \param[in]   vCornerCoords   Vector of corner coordinates
     553              :  * \param[out]  normalOut               Normal
     554              :  */
     555              : template <>
     556            0 : inline void ElementNormal<ReferenceTriangle, 3>(MathVector<3>& normalOut, const MathVector<3>* vCornerCoords)
     557              : {
     558              :         MathVector<3> a, b;
     559              :         VecSubtract(a, vCornerCoords[1], vCornerCoords[0]);
     560              :         VecSubtract(b, vCornerCoords[2], vCornerCoords[0]);
     561            0 :         VecCross(normalOut, a,b);
     562              :         VecScale(normalOut, normalOut, 0.5);
     563            0 : }
     564              : 
     565              : ///////////////////////////////////////////////////////////////
     566              : /// Normal to a Quadrilateral in 3d
     567              : /**
     568              :  * This function returns the normal of a quadrilateral in 3d.
     569              :  * The orientation is right-handed (i.e. forming with the four fingers of the
     570              :  * right hand a circle in direction of the corner nodes, the thumb points in
     571              :  * the direction of the normal)
     572              :  *
     573              :  * The norm of the normal is the size of the quadrilateral.
     574              :  *
     575              :  * \param[in]   vCornerCoords   Vector of corner coordinates
     576              :  * \param[out]  normalOut               Normal
     577              :  */
     578              : template <>
     579            0 : inline void ElementNormal<ReferenceQuadrilateral, 3>(MathVector<3>& normalOut, const MathVector<3>* vCornerCoords)
     580              : {
     581              :         MathVector<3> a, b;
     582              :         VecSubtract(a, vCornerCoords[2], vCornerCoords[0]);
     583              :         VecSubtract(b, vCornerCoords[3], vCornerCoords[1]);
     584            0 :         VecCross(normalOut, a,b);
     585              :         VecScale(normalOut, normalOut, 0.5);
     586            0 : }
     587              : 
     588              : ///////////////////////////////////////////////////////////////
     589              : //      run-time normal of element
     590              : ///////////////////////////////////////////////////////////////
     591              : 
     592              : template <int dim>
     593              : inline void ElementNormal(ReferenceObjectID roid, MathVector<dim>& normalOut, const MathVector<dim>* vCornerCoords);
     594              : 
     595              : template <>
     596            0 : inline void ElementNormal<1>(ReferenceObjectID roid, MathVector<1>& normalOut, const MathVector<1>* vCornerCoords)
     597              : {
     598            0 :         switch(roid)
     599              :         {
     600            0 :                 case ROID_VERTEX: ElementNormal<ReferenceVertex, 1>(normalOut, vCornerCoords); return;
     601            0 :                 default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 1.");
     602              :         }
     603              : }
     604              : 
     605              : template <>
     606            0 : inline void ElementNormal<2>(ReferenceObjectID roid, MathVector<2>& normalOut, const MathVector<2>* vCornerCoords)
     607              : {
     608            0 :         switch(roid)
     609              :         {
     610            0 :                 case ROID_VERTEX: ElementNormal<ReferenceVertex, 2>(normalOut, vCornerCoords); return;
     611              :                 case ROID_EDGE: ElementNormal<ReferenceEdge, 2>(normalOut, vCornerCoords); return;
     612            0 :                 default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 2.");
     613              :         }
     614              : }
     615              : 
     616              : template <>
     617            0 : inline void ElementNormal<3>(ReferenceObjectID roid, MathVector<3>& normalOut, const MathVector<3>* vCornerCoords)
     618              : {
     619            0 :         switch(roid)
     620              :         {
     621            0 :                 case ROID_VERTEX: ElementNormal<ReferenceVertex, 3>(normalOut, vCornerCoords); return;
     622            0 :                 case ROID_EDGE: ElementNormal<ReferenceEdge, 3>(normalOut, vCornerCoords); return;
     623            0 :                 case ROID_TRIANGLE: ElementNormal<ReferenceTriangle, 3>(normalOut, vCornerCoords); return;
     624            0 :                 case ROID_QUADRILATERAL: ElementNormal<ReferenceQuadrilateral, 3>(normalOut, vCornerCoords); return;
     625            0 :                 default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 3.");
     626              :         }
     627              : }
     628              : 
     629              : ///////////////////////////////////////////////////////////////
     630              : /// Normal to a side of an Element in a given Dimension
     631              : /**
     632              :  * This function computes the outer normal to a given side
     633              :  * of an element. The Euclidean norm of the normal is the
     634              :  * area of the side. Note that the normal is computed in
     635              :  * the same dimensionality as the reference element itself.
     636              :  *
     637              :  * \param[in] side                      index of the side of the element
     638              :  * \param[in] vCornerCoords     array of the global coordinates of the corners
     639              :  * \param[out] normalOut        the computed normal
     640              :  */
     641              : template <typename TRefElem, int TWorldDim>
     642            0 : inline void SideNormal(MathVector<TWorldDim>& normalOut, int side, const MathVector<TWorldDim>* vCornerCoords)
     643              : {
     644              :         static const int dim = (int) TRefElem::dim;
     645              :         static const int maxSideCorners = element_list_traits<typename domain_traits<dim-1>::DimElemList>::maxCorners;
     646              :         
     647              : //      Get own reference element and the side roid:
     648              :         TRefElem & rRefElem = (TRefElem&) ReferenceElementProvider::get(TRefElem::REFERENCE_OBJECT_ID);
     649            0 :         ReferenceObjectID sideRoid = rRefElem.roid(dim-1,side);
     650              :         
     651              : //      Get the coordinates of the vertices:
     652            0 :         MathVector<TWorldDim> vSideCorner [(dim == TWorldDim)? maxSideCorners : maxSideCorners + 1];
     653              :         size_t numSideCorners = rRefElem.num(dim-1, side, 0);
     654            0 :         for (size_t co = 0; co < numSideCorners; ++co)
     655            0 :                 vSideCorner[co] = vCornerCoords[rRefElem.id(dim-1, side, 0, co)];
     656              :         // we need another point if dim != TWorldDim:
     657              :         // take the highest-numbered corner of the next side, since
     658              :         // it is always different from the other points (is it not?)
     659              :         if (dim != TWorldDim)
     660              :         {
     661              :                 vSideCorner[numSideCorners] =
     662            0 :                         vCornerCoords[rRefElem.id(dim-1, (side+1)%rRefElem.num(dim-1), 0,
     663            0 :                                                   rRefElem.num(dim-1, (side+1)%rRefElem.num(dim-1), 0)-1)];
     664              :         }
     665              : 
     666              : //      Get the normal:
     667            0 :         ElementNormal<TWorldDim>(sideRoid, normalOut, vSideCorner);
     668              : //      Note: We assume that the for the standard ordering, the last line computes
     669              : //      the outer normal.
     670            0 : }
     671              : 
     672              : ///     Computation of the side normal for a generic reference element:
     673              : template <int dim>
     674              : inline void SideNormal(ReferenceObjectID roid, MathVector<dim>& normalOut, int side, const MathVector<dim>* vCornerCoords);
     675              : 
     676              : template <>
     677              : inline void SideNormal<1>(ReferenceObjectID roid, MathVector<1>& normalOut, int side, const MathVector<1>* vCornerCoords)
     678              : {
     679              :         switch(roid)
     680              :         {
     681              :                 case ROID_EDGE: SideNormal<ReferenceEdge,1>(normalOut, side, vCornerCoords); return;
     682              :                 default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 1.");
     683              :         }
     684              : }
     685              : 
     686              : template <>
     687              : inline void SideNormal<2>(ReferenceObjectID roid, MathVector<2>& normalOut, int side, const MathVector<2>* vCornerCoords)
     688              : {
     689              :         switch(roid)
     690              :         {
     691              :                 case ROID_EDGE: SideNormal<ReferenceEdge,2>(normalOut, side, vCornerCoords); return;
     692              :                 case ROID_TRIANGLE: SideNormal<ReferenceTriangle,2>(normalOut, side, vCornerCoords); return;
     693              :                 case ROID_QUADRILATERAL: SideNormal<ReferenceQuadrilateral,2>(normalOut, side, vCornerCoords); return;
     694              :                 default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 2.");
     695              :         }
     696              : }
     697              : 
     698              : template <>
     699              : inline void SideNormal<3>(ReferenceObjectID roid, MathVector<3>& normalOut, int side, const MathVector<3>* vCornerCoords)
     700              : {
     701              :         switch(roid)
     702              :         {
     703              :                 case ROID_EDGE: SideNormal<ReferenceEdge,3>(normalOut, side, vCornerCoords); return;
     704              :                 case ROID_TRIANGLE: SideNormal<ReferenceTriangle,3>(normalOut, side, vCornerCoords); return;
     705              :                 case ROID_QUADRILATERAL: SideNormal<ReferenceQuadrilateral,3>(normalOut, side, vCornerCoords); return;
     706              :                 case ROID_TETRAHEDRON: SideNormal<ReferenceTetrahedron,3>(normalOut, side, vCornerCoords); return;
     707              :                 case ROID_PYRAMID: SideNormal<ReferencePyramid,3>(normalOut, side, vCornerCoords); return;
     708              :                 case ROID_PRISM: SideNormal<ReferencePrism,3>(normalOut, side, vCornerCoords); return;
     709              :                 case ROID_HEXAHEDRON: SideNormal<ReferenceHexahedron,3>(normalOut, side, vCornerCoords); return;
     710              :                 case ROID_OCTAHEDRON: SideNormal<ReferenceOctahedron,3>(normalOut, side, vCornerCoords); return;
     711              :                 default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 3.");
     712              :         }
     713              : }
     714              : 
     715              : ///////////////////////////////////////////////////////////////
     716              : ///////////////////////////////////////////////////////////////
     717              : // ElementSideRayIntersection
     718              : ///////////////////////////////////////////////////////////////
     719              : ///////////////////////////////////////////////////////////////
     720              : 
     721              : // wrapper class to distinguish reference dimesion
     722              : template <typename TRefElem, int TWorldDim, int TRefDim = TRefElem::dim>
     723              : struct ElementSideRayIntersectionWrapper
     724              : {
     725            0 :         static bool apply(      size_t& sideOut,
     726              :                                                 MathVector<TWorldDim>& GlobalIntersectionPointOut,
     727              :                                                 MathVector<TRefElem::dim>& LocalIntersectionPoint,
     728              :                                                 const MathVector<TWorldDim>& From, const MathVector<TWorldDim>& Direction,
     729              :                                                 bool bPositiv, const MathVector<TWorldDim>* vCornerCoords)
     730              :         {
     731            0 :                 UG_THROW("Not implemented.");
     732              :                 return false;
     733              :         }
     734              : };
     735              : 
     736              : // specialization for 2d
     737              : template <typename TRefElem>
     738              : struct ElementSideRayIntersectionWrapper<TRefElem, 2, 2>
     739              : {
     740            0 :         static bool apply(      size_t& sideOut,
     741              :                                                 MathVector<2>& GlobalIntersectionPointOut,
     742              :                                                 MathVector<TRefElem::dim>& LocalIntersectionPoint,
     743              :                                                 const MathVector<2>& From, const MathVector<2>& Direction,
     744              :                                                 bool bPositiv, const MathVector<2>* vCornerCoords)
     745              :         {
     746            0 :                 static const TRefElem& rRefElem = Provider<TRefElem>::get();
     747              : 
     748              :                 // reference dimension
     749              :                 const int dim = TRefElem::dim;
     750              : 
     751              :                 // parameters
     752            0 :                 number bc = 0., t = 0.;
     753              :                 size_t p0 = 0, p1 = 0;
     754              : 
     755              :                 // find side
     756            0 :                 for(sideOut = 0; sideOut < rRefElem.num(dim-1); ++sideOut)
     757              :                 {
     758              :                         // get corners
     759            0 :                         p0 = rRefElem.id(dim-1, sideOut, 0, 0);
     760            0 :                         p1 = rRefElem.id(dim-1, sideOut, 0, 1);
     761              : 
     762              :                         // if match: break
     763            0 :                         if(RayLineIntersection2d(       GlobalIntersectionPointOut, bc, t,
     764            0 :                                                                                 vCornerCoords[p0], vCornerCoords[p1],
     765              :                                                                                 From, Direction))
     766              :                         {
     767            0 :                                 if(bPositiv && t >= 0.0) break;
     768            0 :                                 else if(!bPositiv && t <= 0.0) break;
     769              :                         }
     770              :                 }
     771              :                 // if not found
     772            0 :                 if(sideOut >= rRefElem.num(dim-1))
     773            0 :                         UG_THROW("ElementSideRayIntersection: no cut side found.");
     774              : 
     775              :                 // Compute local intersection
     776            0 :                 VecScaleAdd(LocalIntersectionPoint, bc, rRefElem.corner(p1), 1.-bc, rRefElem.corner(p0));
     777              : 
     778              :                 // true if found
     779            0 :                 return true;
     780              :         }
     781              : };
     782              : 
     783              : // specialization for 3d
     784              : template <typename TRefElem>
     785              : struct ElementSideRayIntersectionWrapper<TRefElem, 3, 3>
     786              : {
     787            0 :         static bool apply(      size_t& sideOut,
     788              :                                                 MathVector<3>& GlobalIntersectionPointOut,
     789              :                                                 MathVector<TRefElem::dim>& LocalIntersectionPoint,
     790              :                                                 const MathVector<3>& From, const MathVector<3>& Direction,
     791              :                                                 bool bPositiv, const MathVector<3>* vCornerCoords)
     792              :         {
     793            0 :                 static const TRefElem& rRefElem = Provider<TRefElem>::get();
     794              : 
     795              :                 // reference dimension
     796              :                 const int dim = TRefElem::dim;
     797              : 
     798              :                 // parameters
     799            0 :                 number bc0 = 0., bc1 = 0., t = 0.;
     800              :                 size_t p0 = 0, p1 = 0, p2 = 0;
     801              : 
     802              :                 // find side
     803            0 :                 for(sideOut = 0; sideOut < rRefElem.num(dim-1); ++sideOut)
     804              :                 {
     805              :                         // get corners
     806            0 :                         p0 = rRefElem.id(dim-1, sideOut, 0, 0);
     807            0 :                         p1 = rRefElem.id(dim-1, sideOut, 0, 1);
     808            0 :                         p2 = rRefElem.id(dim-1, sideOut, 0, 2);
     809              : 
     810              :                         // if match: break
     811            0 :                         if(RayTriangleIntersection(     GlobalIntersectionPointOut, bc0, bc1, t,
     812            0 :                                                                                 vCornerCoords[p0], vCornerCoords[p1], vCornerCoords[p2],
     813              :                                                                                 From, Direction))
     814              :                         {
     815            0 :                                 if(bPositiv && t >= 0.0) break;
     816            0 :                                 else if(!bPositiv && t <= 0.0) break;
     817              :                         }
     818              : 
     819              :                         // second triangle (only if 4 corners)
     820            0 :                         if(rRefElem.num(dim-1, sideOut, 0) == 3) continue;
     821              : 
     822              :                         // get corner number 4
     823            0 :                         p1 = rRefElem.id(dim-1, sideOut, 0, 3);
     824              : 
     825              :                         // if match: break
     826            0 :                         if(RayTriangleIntersection(     GlobalIntersectionPointOut, bc0, bc1, t,
     827            0 :                                                                                 vCornerCoords[p0], vCornerCoords[p1], vCornerCoords[p2],
     828              :                                                                                 From, Direction))
     829              :                         {
     830            0 :                                 if(bPositiv && t >= 0.0) break;
     831            0 :                                 else if(!bPositiv && t <= 0.0) break;
     832              :                         }
     833              :                 }
     834              : 
     835              :                 // if not found
     836            0 :                 if(sideOut >= rRefElem.num(dim-1))
     837            0 :                         UG_THROW("ElementSideRayIntersection: no cut side found.");
     838              : 
     839              :                 // Compute local intersection
     840            0 :                 VecScaleAdd(LocalIntersectionPoint,
     841            0 :                             (1.-bc0-bc1), rRefElem.corner(p0),
     842              :                                         bc0, rRefElem.corner(p1),
     843              :                                         bc1, rRefElem.corner(p2));
     844              : 
     845              :                 // true if found
     846            0 :                 return true;
     847              :         }
     848              : };
     849              : 
     850              : 
     851              : ///////////////////////////////////////////////////////////////
     852              : /// ElementSideRayIntersection
     853              : /**
     854              :  * This function computes the side of element, that is intersected
     855              :  * by a Ray given in Parameter form by 'From + c * Direction'. The
     856              :  * intersection is choose to be at positive parameter if bPositiv == true,
     857              :  * else the intersection at negative parameter is choosen.
     858              :  * Global and local coordinates of the intersection points are returned
     859              :  * as well as the reference element number of the side.
     860              :  *
     861              :  * \param[in]   From                                                    Point of Ray
     862              :  * \param[in]   Direction                                               Direction of Ray
     863              :  * \param[in]   bPositiv                                                Flag, whether to search in positiv of negative direction
     864              :  * \param[in]   vCornerCoords                                   Vector of corner coordinates
     865              :  * \param[out]  sideOut                                                 side of intersection
     866              :  * \param[out]  GlobalIntersectionPointOut              Intersection Point (global)
     867              :  * \param[out]  LocalIntersectionPoint                  Intersection Point (local)
     868              :  */
     869              : template <typename TRefElem, int TWorldDim>
     870              : bool ElementSideRayIntersection(        size_t& sideOut,
     871              :                                                                         MathVector<TWorldDim>& GlobalIntersectionPointOut,
     872              :                                                                         MathVector<TRefElem::dim>& LocalIntersectionPoint,
     873              :                                                                         const MathVector<TWorldDim>& From, const MathVector<TWorldDim>& Direction,
     874              :                                                                         bool bPositiv, const MathVector<TWorldDim>* vCornerCoords)
     875              : {
     876              :         UG_ASSERT(VecTwoNorm(Direction) > 0, "Direction must be non-zero vector.");
     877              :         return ElementSideRayIntersectionWrapper<TRefElem, TWorldDim>::
     878            0 :                         apply(sideOut, GlobalIntersectionPointOut, LocalIntersectionPoint,
     879            0 :                                         From, Direction, bPositiv, vCornerCoords);
     880              : }
     881              : 
     882              : 
     883              : ///////////////////////////////////////////////////////////////
     884              : ///////////////////////////////////////////////////////////////
     885              : // ElementSideRayIntersection
     886              : ///////////////////////////////////////////////////////////////
     887              : ///////////////////////////////////////////////////////////////
     888              : 
     889              : // wrapper class to distinguish reference dimesion
     890              : template <int TDim, int TWorldDim>
     891              : struct SCVFofSCVRayIntersectionWrapper
     892              : {
     893              :         static bool apply(      size_t& sideOut, number& bc,
     894              :                                                 MathVector<TWorldDim>& GlobalIntersectionPointOut,
     895              :                                                 MathVector<TDim>& LocalIntersectionPoint,
     896              :                                                 const MathVector<TWorldDim>& From, const MathVector<TWorldDim>& Direction,
     897              :                                                 bool bPositiv, const MathVector<TWorldDim>* vCornerCoords)
     898              :         {
     899              :                 UG_THROW("Not implemented.");
     900              :                 return false;
     901              :         }
     902              : };
     903              : 
     904              : // specialization for 2d
     905              : template <>
     906              : struct SCVFofSCVRayIntersectionWrapper<2, 2>
     907              : {
     908              :         static bool apply(      size_t& sideOut, number& bc,
     909              :                                                 MathVector<2>& GlobalIntersectionPointOut,
     910              :                                                 MathVector<2>& LocalIntersectionPoint,
     911              :                                                 const MathVector<2>& From, const MathVector<2>& Direction,
     912              :                                                 bool bPositiv, const MathVector<2>* vCornerCoords)
     913              :         {
     914              :                 static const ReferenceQuadrilateral& rRefElem = Provider<ReferenceQuadrilateral>::get();
     915              : 
     916              :                 // reference dimension
     917              :                 static const int dim = 2;
     918              : 
     919              :                 // parameters
     920              :                 bc = 0.;
     921              :                 number t = 0.;
     922              :                 size_t p0 = 0, p1 = 0;
     923              : 
     924              :                 // find side
     925              :                 for(sideOut = 0; sideOut < rRefElem.num(0); ++sideOut)
     926              :                 {
     927              :                         // get corners
     928              :                         p0 = rRefElem.id(dim-1, sideOut, 0, 0);
     929              :                         p1 = rRefElem.id(dim-1, sideOut, 0, 1);
     930              : 
     931              :                         // if match: break
     932              :                         if(RayLineIntersection2d(       GlobalIntersectionPointOut, bc, t,
     933              :                                                                                 vCornerCoords[p0], vCornerCoords[p1],
     934              :                                                                                 From, Direction))
     935              :                         {
     936              :                         //      skip if one root-point scvf
     937              :                                 if(fabs(t) <= std::numeric_limits<number>::epsilon() * 10)
     938              :                                         continue;
     939              : 
     940              :                         //      upwind / downwind switch
     941              :                                 if(bPositiv && t >= 0.0) break;
     942              :                                 else if(!bPositiv && t <= 0.0) break;
     943              :                         }
     944              :                 }
     945              : 
     946              :                 // if not found
     947              :                 if(sideOut >= rRefElem.num(0))
     948              :                         UG_THROW("Side not found.");
     949              : 
     950              :                 // Compute local intersection
     951              :                 VecScaleAdd(LocalIntersectionPoint, bc, rRefElem.corner(p1), 1.-bc, rRefElem.corner(p0));
     952              : 
     953              :                 //      parameter of intersection should loop always from center to edgeMidpoint
     954              :                 //      thus, for side 2 this is correct, but for side 1 we have to invert direction
     955              :                 if(sideOut == 1) bc = 1. - bc;
     956              : 
     957              :                 // true if found on scvf
     958              :                 if(sideOut == 1 || sideOut == 2) return true;
     959              :                 // false if found on element corner
     960              :                 else return false;
     961              :         }
     962              : };
     963              : 
     964              : ///////////////////////////////////////////////////////////////
     965              : // SCVFofSCVRayIntersection
     966              : /**
     967              :  * This function computes if another scvf of a scv is intersected
     968              :  * by a Ray given in Parameter form by 'Root + c * Direction'. The
     969              :  * intersection is choose to be at positive parameter if bPositiv == true,
     970              :  * else the intersection at negative parameter is choosen.
     971              :  * Global and local coordinates of the intersection points are returned
     972              :  * as well as the local number of the side of the scv that matches the intersection.
     973              :  *
     974              :  * \param[in]   Root                                                    Point of Ray
     975              :  * \param[in]   Direction                                               Direction of Ray
     976              :  * \param[in]   bPositiv                                                Flag, whether to search in positiv of negative direction
     977              :  * \param[in]   vCornerCoords                                   Vector of corner coordinates
     978              :  * \param[out]  sideOut                                                 side of intersection
     979              :  * \param[out]  bc                                                              line parameter in [0,1] indicating position
     980              :  *                                                                                              of intersection point on scvf in direction
     981              :  *                                                                                              center to edge
     982              :  * \param[out]  GlobalIntersectionPointOut              Intersection Point (global)
     983              :  * \param[out]  LocalIntersectionPoint                  Intersection Point (local)
     984              :  * \returns true if intersected with another scvf of the scv, false else
     985              :  */
     986              : template <int TDim, int TWorldDim>
     987              : bool SCVFofSCVRayIntersection(  size_t& sideOut, number& bc,
     988              :                                 MathVector<TWorldDim>& GlobalIntersectionPointOut,
     989              :                                 MathVector<TDim>& LocalIntersectionPoint,
     990              :                                 const MathVector<TWorldDim>& Root, const MathVector<TWorldDim>& Direction,
     991              :                                 bool bPositiv, const MathVector<TWorldDim>* vCornerCoords)
     992              : {
     993              :         UG_ASSERT(VecTwoNorm(Direction) > 0, "Direction must be non-zero vector.");
     994              :         return SCVFofSCVRayIntersectionWrapper<TDim, TWorldDim>::
     995              :                         apply(sideOut, bc, GlobalIntersectionPointOut, LocalIntersectionPoint,
     996              :                                         Root, Direction, bPositiv, vCornerCoords);
     997              : }
     998              : 
     999              : 
    1000              : 
    1001              : ///////////////////////////////////////////////////////////////
    1002              : /// Extension of an element (in a given dimension)
    1003              : ///////////////////////////////////////////////////////////////
    1004              : 
    1005              : 
    1006              : template <typename TVector>
    1007              : inline void ComputeElementExtensionsSqForEdges(const TVector* vCornerCoords, TVector &ext)
    1008              : {
    1009              :         VecElemProd(ext, vCornerCoords[0], vCornerCoords[1]);
    1010              : }
    1011              : 
    1012              : 
    1013              : template <int TWorldDim, int ncorners>
    1014              : inline void ComputeElementExtensionsSq(const MathVector<TWorldDim>* vCornerCoords, MathVector<TWorldDim> &ext)
    1015              : {
    1016              :         // compute center
    1017              :         MathVector<TWorldDim> mid = 0.0;
    1018              :         for (int i=ncorners-1; i>=0; --i){
    1019              :                 VecAppend(mid, vCornerCoords[i]);
    1020              :         }
    1021              :         VecScale(mid, mid, 1.0/ncorners);
    1022              : 
    1023              :         // compute
    1024              :         ext = 0.0;
    1025              :         MathVector<TWorldDim> aux;
    1026              :         for (int i=ncorners-1; i>=0; --i){
    1027              :                 VecSubtract(aux, mid, vCornerCoords[i]);
    1028              :                 VecElemProd(aux, aux, aux);
    1029              :                 VecAppend(ext, aux);
    1030              :         }
    1031              :         VecScale(ext, ext, 1.0/ncorners);
    1032              : }
    1033              : 
    1034              : ///////////////////////////////////////////////////////////////
    1035              : //      extensions of an element
    1036              : ///////////////////////////////////////////////////////////////
    1037              : 
    1038              : 
    1039              : template <int dim>
    1040              : inline void ElementExtensionsSq(ReferenceObjectID roid, MathVector<dim>& ext, const MathVector<dim>* vCornerCoords);
    1041              : 
    1042              : template <>
    1043              : inline void ElementExtensionsSq<1>(ReferenceObjectID roid, MathVector<1>& ext, const MathVector<1>* vCornerCoords)
    1044              : {
    1045              :         switch(roid)
    1046              :         {
    1047              :                 case ROID_VERTEX:                       ext = 0; return;
    1048              :                 case ROID_EDGE:                         ComputeElementExtensionsSqForEdges(vCornerCoords,ext); return;
    1049              :                 default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 1.");
    1050              :         }
    1051              : }
    1052              : 
    1053              : template <>
    1054              : inline void ElementExtensionsSq<2>(ReferenceObjectID roid, MathVector<2>& ext, const MathVector<2>* vCornerCoords)
    1055              : {
    1056              :         switch(roid)
    1057              :         {
    1058              :                 case ROID_VERTEX:                       ext = 0; return;
    1059              :                 case ROID_EDGE:                         ComputeElementExtensionsSqForEdges(vCornerCoords,ext); return;
    1060              :                 case ROID_TRIANGLE:             ComputeElementExtensionsSq<2,3>(vCornerCoords,ext); return;
    1061              :                 case ROID_QUADRILATERAL:        ComputeElementExtensionsSq<2,4>(vCornerCoords,ext); return;
    1062              :                 default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 2.");
    1063              :         }
    1064              : }
    1065              : 
    1066              : template <>
    1067              : inline void ElementExtensionsSq<3>(ReferenceObjectID roid, MathVector<3>& ext, const MathVector<3>* vCornerCoords)
    1068              : {
    1069              :         switch(roid)
    1070              :         {
    1071              :                 case ROID_VERTEX:                       ext = 0; return;
    1072              :                 case ROID_EDGE:                         ComputeElementExtensionsSqForEdges(vCornerCoords,ext); return; 
    1073              :                 case ROID_TRIANGLE:             ComputeElementExtensionsSq<3,3>(vCornerCoords,ext); return;
    1074              :                 case ROID_QUADRILATERAL:        ComputeElementExtensionsSq<3,4>(vCornerCoords,ext); return;
    1075              :                 case ROID_TETRAHEDRON:          ComputeElementExtensionsSq<3,4>(vCornerCoords,ext); return;
    1076              :                 case ROID_PYRAMID:                      ComputeElementExtensionsSq<3,5>(vCornerCoords,ext); return;
    1077              :                 case ROID_PRISM:                        ComputeElementExtensionsSq<3,6>(vCornerCoords,ext); return;
    1078              :                 case ROID_HEXAHEDRON:           ComputeElementExtensionsSq<3,8>(vCornerCoords,ext); return;
    1079              :                 case ROID_OCTAHEDRON:           ComputeElementExtensionsSq<3,6>(vCornerCoords,ext); return;
    1080              :                 default: UG_THROW("ReferenceObject "<<roid<<" not found in dim 3.");
    1081              :         }
    1082              : }
    1083              : 
    1084              : 
    1085              : } // end namespace ug
    1086              : 
    1087              : #endif /* __H__UG__LIB_DISC__COMMON__GEOMETRY_UTIL__ */
        

Generated by: LCOV version 2.0-1