LCOV - code coverage report
Current view: top level - ugbase/lib_grid/grid_objects - tetrahedron_rules.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 300 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 6 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2011-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Sebastian Reiter
       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              : #include <cassert>
      34              : #include "tetrahedron_rules.h"
      35              : #include "rule_util.h"
      36              : #include "grid_object_ids.h"
      37              : 
      38              : namespace ug{
      39              : namespace tet_rules
      40              : {
      41              : 
      42              : /// global refinement rule information switching between regular and subdivision volume refinement
      43              : static GlobalRefinementRule g_refinementRule = STANDARD;
      44              : 
      45            0 : void SetRefinementRule(GlobalRefinementRule refRule)
      46              : {
      47            0 :         g_refinementRule = refRule;
      48            0 : }
      49              : 
      50            0 : GlobalRefinementRule GetRefinementRule()
      51              : {
      52            0 :         return g_refinementRule;
      53              : }
      54              : 
      55              : 
      56              : ///     Rotates the given tetrahedron while keeping the specified point fixed
      57              : /**     The face opposed to the fixed point is rotated in counter-clockwise order when
      58              :  * viewed from the fixed point.
      59              :  * e.g.
      60              :  * \code
      61              :  *              int vrts[] = {0, 1, 2, 3};
      62              :  *              TetRotation(vrts, 3, 1);
      63              :  *      //      -> vrts == {2, 0, 1, 3}
      64              :  * \endcode
      65              :  */
      66            0 : void TetRotation (
      67              :                 int vrtsInOut[NUM_VERTICES],
      68              :                 const int fixedPoint,
      69              :                 const size_t steps)
      70              : {
      71              : //      get the opposing face of the fixed point
      72            0 :         const int opFace = OPPOSED_OBJECT[fixedPoint][1];
      73            0 :         const int* finds = FACE_VRT_INDS[opFace];
      74              : 
      75            0 :         for(size_t i = 0; i < steps; ++i){
      76            0 :                 const int tmp = vrtsInOut[finds[0]];
      77            0 :                 vrtsInOut[finds[0]] = vrtsInOut[finds[2]];
      78            0 :                 vrtsInOut[finds[2]] = vrtsInOut[finds[1]];
      79            0 :                 vrtsInOut[finds[1]] = tmp;
      80              :         }
      81            0 : }
      82              : 
      83            0 : void InverseTetTransform(int* indsOut, const int* transformedInds){
      84              :         UG_ASSERT(indsOut != transformedInds, "The arrays have to differ!");
      85            0 :         for(int i = 0; i < NUM_VERTICES; ++i)
      86            0 :                 indsOut[transformedInds[i]] = i;
      87            0 : }
      88              : 
      89              : 
      90            0 : int Refine(int* newIndsOut, int* newEdgeVrts, bool& newCenterOut,
      91              :                    vector3* corners, bool*)
      92              : {
      93            0 :         newCenterOut = false;
      94              : //      If a refinement rule is not implemented, fillCount will stay at 0.
      95              : //      Before returning, we'll check, whether fillCount is at 0 and will
      96              : //      perform refinement with an additional vertex in this case.
      97              : 
      98              : //      corner status is used to mark vertices, which are connected to refined edges
      99              : //      the value tells, how many associated edges are refined.
     100            0 :         int cornerStatus[4] = {0, 0, 0, 0};
     101              : 
     102              : //      here we'll store the index of each edge, which will be refined.
     103              : //      Size of the valid sub-array is numNewVrts, which is calculated below.
     104              :         int refEdgeInds[NUM_EDGES];
     105              : 
     106              : //      count the number of new vertices and fill newVrtEdgeInds
     107              :         int numNewVrts = 0;
     108            0 :         for(int i = 0; i < NUM_EDGES; ++i){
     109            0 :                 if(newEdgeVrts[i]){
     110            0 :                         refEdgeInds[numNewVrts] = i;
     111            0 :                         ++numNewVrts;
     112              : 
     113              :                 //      adjust corner status of associated vertices
     114            0 :                         const int* evi = EDGE_VRT_INDS[i];
     115            0 :                         ++cornerStatus[evi[0]];
     116            0 :                         ++cornerStatus[evi[1]];
     117              :                 }
     118              :         }
     119              : 
     120              : //      the fillCount tells how much data has already been written to newIndsOut.
     121              :         int fillCount = 0;
     122              : 
     123              : //      depending on the number of new vertices, we will now apply different
     124              : //      refinement rules. Further distinction may have to be done.
     125            0 :         switch(numNewVrts){
     126            0 :                 case 0:
     127              :                 {
     128              :                 //      simply put the default tetrahedron back to newIndsOut
     129            0 :                         newIndsOut[fillCount++] = GOID_TETRAHEDRON;
     130            0 :                         newIndsOut[fillCount++] = 0;
     131            0 :                         newIndsOut[fillCount++] = 1;
     132            0 :                         newIndsOut[fillCount++] = 2;
     133            0 :                         newIndsOut[fillCount++] = 3;
     134              :                 }break;
     135              : 
     136            0 :                 case 1:
     137              :                 {
     138            0 :                         int refEdgeInd = refEdgeInds[0];
     139              :                 //      the two faces which are not connected to the refined edge
     140              :                 //      serve as bottom for the new tetrahedrons.
     141            0 :                         for(int i_face = 0; i_face < NUM_FACES; ++i_face){
     142            0 :                                 if(!FACE_CONTAINS_EDGE[i_face][refEdgeInd]){
     143            0 :                                         const int* fvi = FACE_VRT_INDS[i_face];
     144              : 
     145            0 :                                         newIndsOut[fillCount++] = GOID_TETRAHEDRON;
     146            0 :                                         newIndsOut[fillCount++] = fvi[0];
     147            0 :                                         newIndsOut[fillCount++] = fvi[1];
     148            0 :                                         newIndsOut[fillCount++] = fvi[2];
     149            0 :                                         newIndsOut[fillCount++] = NUM_VERTICES + refEdgeInd;
     150              :                                 }
     151              :                         }
     152              :                 }break;
     153              : 
     154            0 :                 case 2:
     155              :                 {
     156              :                 //      two types exist: The two refined edges share a vertex or not.
     157            0 :                         if(OPPOSED_EDGE[refEdgeInds[0]] == refEdgeInds[1]){
     158              :                         //      they do not share an edge
     159              :                         //      we create a local order from refEdgeInds[0], which
     160              :                         //      always has to be an edge in the base-triangle and
     161              :                         //      refEdgeInds[1], which always connects a base-corner with
     162              :                         //      the top.
     163            0 :                                 const int v0 = EDGE_VRT_INDS[refEdgeInds[0]][0];
     164            0 :                                 const int v1 = EDGE_VRT_INDS[refEdgeInds[0]][1];
     165            0 :                                 const int v2 = EDGE_VRT_INDS[refEdgeInds[1]][0];
     166            0 :                                 const int v3 = EDGE_VRT_INDS[refEdgeInds[1]][1];
     167            0 :                                 const int n0 = refEdgeInds[0] + NUM_VERTICES;
     168            0 :                                 const int n1 = refEdgeInds[1] + NUM_VERTICES;
     169              : 
     170              :                         //      from this local order we can now construct the 4 new tetrahedrons.
     171              :                                 int& fi = fillCount;
     172              :                                 int* inds = newIndsOut;
     173            0 :                                 inds[fi++] = GOID_TETRAHEDRON;
     174            0 :                                 inds[fi++] = v0;        inds[fi++] = n0;
     175            0 :                                 inds[fi++] = v2;        inds[fi++] = n1;
     176              : 
     177            0 :                                 inds[fi++] = GOID_TETRAHEDRON;
     178            0 :                                 inds[fi++] = v0;        inds[fi++] = n0;
     179            0 :                                 inds[fi++] = n1;        inds[fi++] = v3;
     180              : 
     181            0 :                                 inds[fi++] = GOID_TETRAHEDRON;
     182            0 :                                 inds[fi++] = n0;        inds[fi++] = v1;
     183            0 :                                 inds[fi++] = v2;        inds[fi++] = n1;
     184              : 
     185            0 :                                 inds[fi++] = GOID_TETRAHEDRON;
     186            0 :                                 inds[fi++] = n0;        inds[fi++] = v1;
     187            0 :                                 inds[fi++] = n1;        inds[fi++] = v3;
     188              :                         }
     189              :                         else{
     190              :                         //      they share an edge
     191              :                         //      We have to create a pyramid and a tetrahedron.
     192              :                         //      get the triangle, which contains both refEdges
     193            0 :                                 int refTriInd = FACE_FROM_EDGES[refEdgeInds[0]][refEdgeInds[1]];
     194            0 :                                 const int* f = FACE_VRT_INDS[refTriInd];
     195              : 
     196              :                         //      find the edge (v0, v1) in refTri, which won't be refined
     197              :                                 int v0 = -1; int v1 = -1; int v2 = -1;
     198            0 :                                 for(int i = 0; i < 3; ++i){
     199            0 :                                         v0 = f[i];
     200            0 :                                         v1 = f[(i+1)%3];
     201            0 :                                         v2 = f[(i+2)%3];
     202            0 :                                         if(cornerStatus[v0] == 1 && cornerStatus[v1] == 1)
     203              :                                                 break;
     204              :                                 }
     205              : 
     206              :                         //      make sure that v2 is connected to two refined edges
     207              :                                 assert(cornerStatus[v2] == 2);
     208              : 
     209              :                         //      get the new vertex on edge v1v2 and on v2v0
     210            0 :                                 int v1v2 = EDGE_FROM_VRTS[v1][v2] + NUM_VERTICES;
     211            0 :                                 int v2v0 = EDGE_FROM_VRTS[v2][v0] + NUM_VERTICES;
     212              : 
     213              :                         //      get the top (vertex with cornerState 0)
     214              :                                 int vtop = -1;
     215            0 :                                 for(int i = 0; i < NUM_VERTICES; ++i){
     216            0 :                                         if(cornerStatus[i] == 0){
     217              :                                                 vtop = i;
     218              :                                                 break;
     219              :                                         }
     220              :                                 }
     221              : 
     222              :                         //      now lets build the pyramid
     223              :                                 int& fi = fillCount;
     224              :                                 int* inds = newIndsOut;
     225            0 :                                 inds[fi++] = GOID_PYRAMID;
     226            0 :                                 inds[fi++] = v0;        inds[fi++] = v1;
     227            0 :                                 inds[fi++] = v1v2;      inds[fi++] = v2v0;
     228            0 :                                 inds[fi++] = vtop;
     229              : 
     230              :                         //      and now the terahedron
     231            0 :                                 inds[fi++] = GOID_TETRAHEDRON;
     232            0 :                                 inds[fi++] = v2;        inds[fi++] = vtop;
     233            0 :                                 inds[fi++] = v2v0;      inds[fi++] = v1v2;
     234              :                         }
     235              :                 }break;
     236              : 
     237            0 :                 case 3:
     238              :                 {
     239              :                 //      different possibilities exist. First we'll treat the one,
     240              :                 //      where all new vertices lie on the edges of one triangle.
     241              :                 //      Note that refTriInd could be -1 after the call.
     242            0 :                         int refTriInd = FACE_FROM_EDGES[refEdgeInds[0]][refEdgeInds[1]];
     243            0 :                         if(refTriInd == FACE_FROM_EDGES[refEdgeInds[1]][refEdgeInds[2]])
     244              :                         {
     245              :                         //      all three lie in one plane (refTriInd has to be != -1 to get here)
     246              :                         //      get the top (vertex with cornerState 0)
     247              :                                 int vtop = -1;
     248            0 :                                 for(int i = 0; i < NUM_VERTICES; ++i){
     249            0 :                                         if(cornerStatus[i] == 0){
     250              :                                                 vtop = i;
     251              :                                                 break;
     252              :                                         }
     253              :                                 }
     254              : 
     255            0 :                                 const int* f = FACE_VRT_INDS[refTriInd];
     256              : 
     257              :                         //      create four new tetrahedrons
     258            0 :                                 const int v0 = f[0]; const int v1 = f[1]; const int v2 = f[2];
     259            0 :                                 const int v0v1 = EDGE_FROM_VRTS[v0][v1] + NUM_VERTICES;
     260            0 :                                 const int v1v2 = EDGE_FROM_VRTS[v1][v2] + NUM_VERTICES;
     261            0 :                                 const int v2v0 = EDGE_FROM_VRTS[v2][v0] + NUM_VERTICES;
     262              : 
     263              :                                 int& fi = fillCount;
     264              :                                 int* inds = newIndsOut;
     265            0 :                                 inds[fi++] = GOID_TETRAHEDRON;
     266            0 :                                 inds[fi++] = v0;        inds[fi++] = vtop;
     267            0 :                                 inds[fi++] = v0v1;      inds[fi++] = v2v0;
     268            0 :                                 inds[fi++] = GOID_TETRAHEDRON;
     269            0 :                                 inds[fi++] = v1;        inds[fi++] = vtop;
     270            0 :                                 inds[fi++] = v1v2;      inds[fi++] = v0v1;
     271            0 :                                 inds[fi++] = GOID_TETRAHEDRON;
     272            0 :                                 inds[fi++] = v2;        inds[fi++] = vtop;
     273            0 :                                 inds[fi++] = v2v0;      inds[fi++] = v1v2;
     274            0 :                                 inds[fi++] = GOID_TETRAHEDRON;
     275            0 :                                 inds[fi++] = v0v1;      inds[fi++] = vtop;
     276            0 :                                 inds[fi++] = v1v2;      inds[fi++] = v2v0;
     277              :                         }
     278              :                         else{
     279              :                         //      we have to further distinguish.
     280              :                         //      gather the corners with corner-state 3 and corner state 1
     281              :                                 int corner3 = -1;
     282              :                                 int freeCorner[NUM_VERTICES];
     283              :                                 int freeCount = 0;
     284            0 :                                 for(int i = 0; i < NUM_VERTICES; ++i){
     285            0 :                                         if(cornerStatus[i] == 3)
     286              :                                                 corner3 = i;
     287              :                                         else
     288            0 :                                                 freeCorner[freeCount++] = i;
     289              :                                 }
     290              : 
     291            0 :                                 if(corner3 != -1){
     292              :                                 //      a corner with corner state 3 exists.
     293              :                                         assert(freeCount == 3);
     294              : 
     295              :                                 // get the face which won't be refined (required for correct orientation)
     296            0 :                                         int freeTriInd = FACE_FROM_VRTS[freeCorner[0]][freeCorner[1]]
     297            0 :                                                                                                    [freeCorner[2]];
     298              : 
     299              :                                 //      the free tri is the new base, corner3 the top
     300            0 :                                         const int* f = FACE_VRT_INDS[freeTriInd];
     301            0 :                                         int v2v3 = EDGE_FROM_VRTS[f[2]][corner3] + NUM_VERTICES;
     302            0 :                                         int v1v3 = EDGE_FROM_VRTS[f[1]][corner3] + NUM_VERTICES;
     303            0 :                                         int v0v3 = EDGE_FROM_VRTS[f[0]][corner3] + NUM_VERTICES;
     304              : 
     305              :                                 //      add a prism and a tetrahedron
     306              :                                         int& fi = fillCount;
     307              :                                         int* inds = newIndsOut;
     308            0 :                                         inds[fi++] = GOID_PRISM;
     309            0 :                                         inds[fi++] = f[0]; inds[fi++] = f[1]; inds[fi++] = f[2];
     310            0 :                                         inds[fi++] = v0v3; inds[fi++] = v1v3; inds[fi++] = v2v3;
     311              : 
     312            0 :                                         inds[fi++] = GOID_TETRAHEDRON;
     313            0 :                                         inds[fi++] = v2v3; inds[fi++] = corner3; inds[fi++] = v0v3;
     314            0 :                                         inds[fi++] = v1v3;
     315              :                                 }
     316              :                         }
     317              :                 }break;
     318              : 
     319              :                 case 4:
     320              :                 {
     321              :                 //      multiple settings with 4 refined edges exist.
     322              :                 //      Either two opposing edges are not marked (case all2 == true)
     323              :                 //      or the two unmarked edges are contained in 1 triangle
     324              : 
     325              :                 //      check whether all vertices have corner state 2
     326              :                         bool all2 = true;
     327            0 :                         for(int i = 0; i < NUM_VERTICES; ++i){
     328            0 :                                 if(cornerStatus[i] !=2){
     329              :                                         all2 = false;
     330              :                                         break;
     331              :                                 }
     332              :                         }
     333              : 
     334            0 :                         if(all2){
     335              :                         //      we've got a straight cut.
     336              :                         //      we'll rotate the tetrahedron around the tip so, that edge 2 won't be refined.
     337              :                                 int steps = 0;
     338            0 :                                 if(!newEdgeVrts[EDGE_FROM_VRTS[0][1]])
     339              :                                         steps = 2;
     340            0 :                                 else if(!newEdgeVrts[EDGE_FROM_VRTS[1][2]])
     341              :                                         steps = 1;
     342              : 
     343            0 :                                 int t[NUM_VERTICES] = {0, 1, 2, 3};
     344            0 :                                 TetRotation(t, 3, steps);
     345              : 
     346            0 :                                 const int v0v1 = EDGE_FROM_VRTS[t[0]][t[1]] + NUM_VERTICES;
     347            0 :                                 const int v1v2 = EDGE_FROM_VRTS[t[1]][t[2]] + NUM_VERTICES;
     348            0 :                                 const int v0v3 = EDGE_FROM_VRTS[t[0]][t[3]] + NUM_VERTICES;
     349            0 :                                 const int v2v3 = EDGE_FROM_VRTS[t[2]][t[3]] + NUM_VERTICES;
     350              : 
     351              :                                 assert(newEdgeVrts[v0v1 - NUM_VERTICES]);
     352              :                                 assert(newEdgeVrts[v1v2 - NUM_VERTICES]);
     353              :                                 assert(newEdgeVrts[v0v3 - NUM_VERTICES]);
     354              :                                 assert(newEdgeVrts[v2v3 - NUM_VERTICES]);
     355              : 
     356              :                         //      now build two prisms
     357              :                                 int& fi = fillCount;
     358              :                                 int* inds = newIndsOut;
     359              : 
     360            0 :                                 inds[fi++] = GOID_PRISM;
     361            0 :                                 inds[fi++] = t[0];      inds[fi++] = v0v3;      inds[fi++] = v0v1;
     362            0 :                                 inds[fi++] = t[2];      inds[fi++] = v2v3;      inds[fi++] = v1v2;
     363              : 
     364            0 :                                 inds[fi++] = GOID_PRISM;
     365            0 :                                 inds[fi++] = t[1];      inds[fi++] = v1v2;      inds[fi++] = v0v1;
     366            0 :                                 inds[fi++] = t[3];      inds[fi++] = v2v3;      inds[fi++] = v0v3;
     367              :                         }
     368              :                         else{
     369              :                         //      one corner has state 1, one has state 3 and two have state 2.
     370              :                         //      Rotate the tet so that 1 is at the top and 4 is at the origin
     371            0 :                                 int I[NUM_VERTICES] = {0, 1, 2, 3};
     372              : 
     373              :                                 int s1 = -1;
     374            0 :                                 for(int i = 0; i < 4; ++i){
     375            0 :                                         if(cornerStatus[i] == 1){
     376              :                                                 s1 = i;
     377              :                                                 break;
     378              :                                         }
     379              :                                 }
     380              : 
     381            0 :                                 if(s1 != 3){
     382            0 :                                         const int fixedPoint = (s1 + 2) % 3;
     383            0 :                                         TetRotation(I, fixedPoint, 1);
     384              :                                 }
     385              : 
     386            0 :                                 if(cornerStatus[I[1]] == 3)
     387            0 :                                         TetRotation(I, 3, 2);
     388            0 :                                 else if(cornerStatus[I[2]] == 3)
     389            0 :                                         TetRotation(I, 3, 1);
     390              : 
     391              :                         //      indices of edge-center vertices
     392            0 :                                 const int v01 = EDGE_FROM_VRTS[I[0]][I[1]] + NUM_VERTICES;
     393            0 :                                 const int v02 = EDGE_FROM_VRTS[I[0]][I[2]] + NUM_VERTICES;
     394            0 :                                 const int v03 = EDGE_FROM_VRTS[I[0]][I[3]] + NUM_VERTICES;
     395            0 :                                 const int v12 = EDGE_FROM_VRTS[I[1]][I[2]] + NUM_VERTICES;
     396              : 
     397              :                                 int& fi = fillCount;
     398              :                                 int* inds = newIndsOut;
     399              : 
     400            0 :                                 inds[fi++] = GOID_TETRAHEDRON;
     401            0 :                                 inds[fi++] = I[0];      inds[fi++] = v01;
     402            0 :                                 inds[fi++] = v02;       inds[fi++] = v03;
     403              : 
     404            0 :                                 inds[fi++] = GOID_TETRAHEDRON;
     405            0 :                                 inds[fi++] = v01;       inds[fi++] = v12;
     406            0 :                                 inds[fi++] = v02;       inds[fi++] = v03;
     407              : 
     408            0 :                                 inds[fi++] = GOID_PYRAMID;
     409            0 :                                 inds[fi++] = I[3];      inds[fi++] = I[1];
     410            0 :                                 inds[fi++] = v01;       inds[fi++] = v03;
     411            0 :                                 inds[fi++] = v12;
     412              : 
     413            0 :                                 inds[fi++] = GOID_PYRAMID;
     414            0 :                                 inds[fi++] = I[2];      inds[fi++] = I[3];
     415            0 :                                 inds[fi++] = v03;       inds[fi++] = v02;
     416            0 :                                 inds[fi++] = v12;
     417              :                         }
     418              :                 }break;
     419              : 
     420              :                 case 5:{
     421              :                 //      only one edge is not marked for refinement
     422              :                         int unmarkedEdge = 0;
     423            0 :                         for(int i = 0; i < NUM_EDGES; ++i){
     424            0 :                                 if(!newEdgeVrts[i]){
     425              :                                         unmarkedEdge = i;
     426              :                                         break;
     427              :                                 }
     428              :                         }
     429              : 
     430            0 :                         int uei0 = EDGE_VRT_INDS[unmarkedEdge][0];
     431            0 :                         int uei1 = EDGE_VRT_INDS[unmarkedEdge][1];
     432              : 
     433              :                 //      orientate the tetrahedron so that the unmarked edge connects
     434              :                 //      vertices 2 and 3
     435            0 :                         int I[NUM_VERTICES] = {0, 1, 2, 3};
     436              :                 //      if the unmarked edge lies in the base triangle, we'll first have to
     437              :                 //      rotate so that it connects a base-vertex with the top
     438            0 :                         if(unmarkedEdge < 3){
     439            0 :                                 const int fixedPoint = (uei1 + 1) % 3;
     440            0 :                                 TetRotation(I, fixedPoint, 1);
     441              :                                 int IInv[4];
     442            0 :                                 InverseTetTransform(IInv, I);
     443              : 
     444            0 :                                 uei0 = IInv[uei0];
     445            0 :                                 uei1 = IInv[uei1];
     446            0 :                                 unmarkedEdge = EDGE_FROM_VRTS[uei0][uei1];
     447              :                         }
     448              : 
     449              :                 //      now rotate the tet to its final place
     450            0 :                         if(unmarkedEdge == 3)
     451            0 :                                 TetRotation(I, 3, 2);
     452            0 :                         else if(unmarkedEdge == 4)
     453            0 :                                 TetRotation(I, 3, 1);
     454              : 
     455              :                 //      We obtained the final permutation I. Now create new elements
     456              :                 //      indices of edge-center vertices
     457            0 :                         const int v01 = EDGE_FROM_VRTS[I[0]][I[1]] + NUM_VERTICES;
     458            0 :                         const int v02 = EDGE_FROM_VRTS[I[0]][I[2]] + NUM_VERTICES;
     459            0 :                         const int v03 = EDGE_FROM_VRTS[I[0]][I[3]] + NUM_VERTICES;
     460            0 :                         const int v12 = EDGE_FROM_VRTS[I[1]][I[2]] + NUM_VERTICES;
     461            0 :                         const int v13 = EDGE_FROM_VRTS[I[1]][I[3]] + NUM_VERTICES;
     462              : 
     463              :                         int& fi = fillCount;
     464              :                         int* inds = newIndsOut;
     465              : 
     466            0 :                         inds[fi++] = GOID_TETRAHEDRON;
     467            0 :                         inds[fi++] = I[0];      inds[fi++] = v01;
     468            0 :                         inds[fi++] = v02;       inds[fi++] = v03;
     469              : 
     470            0 :                         inds[fi++] = GOID_TETRAHEDRON;
     471            0 :                         inds[fi++] = I[1];      inds[fi++] = v12;
     472            0 :                         inds[fi++] = v01;       inds[fi++] = v13;
     473              : 
     474            0 :                         inds[fi++] = GOID_PYRAMID;
     475            0 :                         inds[fi++] = v02;       inds[fi++] = v12;
     476            0 :                         inds[fi++] = v13;       inds[fi++] = v03;
     477            0 :                         inds[fi++] = v01;
     478              : 
     479            0 :                         inds[fi++] = GOID_PRISM;
     480            0 :                         inds[fi++] = v02;       inds[fi++] = v12;       inds[fi++] = I[2];
     481            0 :                         inds[fi++] = v03;       inds[fi++] = v13;       inds[fi++] = I[3];
     482              : 
     483              : 
     484              :                 }break;
     485              : 
     486              :         //      REGULAR REFINEMENT
     487            0 :                 case 6:
     488              :                 {
     489              :                 //      depending on the user specified global refinement rule, we will now apply different
     490              :                 //      refinement rules.
     491            0 :                         switch(g_refinementRule){
     492            0 :                                 case STANDARD:
     493              :                                 {
     494              :                                         int& fi = fillCount;
     495              :                                         int* inds = newIndsOut;
     496              : 
     497            0 :                                         inds[fi++] = GOID_TETRAHEDRON;
     498            0 :                                         inds[fi++] = 0;                                 inds[fi++] = NUM_VERTICES + 0;
     499            0 :                                         inds[fi++] = NUM_VERTICES + 2;  inds[fi++] = NUM_VERTICES + 3;
     500              : 
     501            0 :                                         inds[fi++] = GOID_TETRAHEDRON;
     502            0 :                                         inds[fi++] = 1;                                 inds[fi++] = NUM_VERTICES + 1;
     503            0 :                                         inds[fi++] = NUM_VERTICES + 0;  inds[fi++] = NUM_VERTICES + 4;
     504              : 
     505            0 :                                         inds[fi++] = GOID_TETRAHEDRON;
     506            0 :                                         inds[fi++] = 2;                                 inds[fi++] = NUM_VERTICES + 2;
     507            0 :                                         inds[fi++] = NUM_VERTICES + 1;  inds[fi++] = NUM_VERTICES + 5;
     508              : 
     509            0 :                                         inds[fi++] = GOID_TETRAHEDRON;
     510            0 :                                         inds[fi++] = NUM_VERTICES + 3;  inds[fi++] = NUM_VERTICES + 4;
     511            0 :                                         inds[fi++] = NUM_VERTICES + 5;  inds[fi++] = 3;
     512              : 
     513              :                                 //      for the remaining four tetrahedrons, we'll choose the shortest diagonal
     514              :                                         int bestDiag = 2;
     515            0 :                                         if(corners){
     516              :                                         //      there are three diagonals between the following edge-centers:
     517              :                                         //      0-5, 1-3, 2-4
     518              :                                                 vector3 c1, c2;
     519              : 
     520              :                                         //      0-5
     521              :                                                 VecAdd(c1, corners[0], corners[1]);
     522              :                                                 VecScale(c1, c1, 0.5);
     523              :                                                 VecAdd(c2, corners[2], corners[3]);
     524              :                                                 VecScale(c2, c2, 0.5);
     525            0 :                                                 number d05 = VecDistanceSq(c1, c2);
     526              : 
     527              :                                         //      1-3
     528              :                                                 VecAdd(c1, corners[1], corners[2]);
     529              :                                                 VecScale(c1, c1, 0.5);
     530              :                                                 VecAdd(c2, corners[0], corners[3]);
     531              :                                                 VecScale(c2, c2, 0.5);
     532            0 :                                                 number d13 = VecDistanceSq(c1, c2);
     533              : 
     534              :                                         //      2-4
     535              :                                                 VecAdd(c1, corners[0], corners[2]);
     536              :                                                 VecScale(c1, c1, 0.5);
     537              :                                                 VecAdd(c2, corners[1], corners[3]);
     538              :                                                 VecScale(c2, c2, 0.5);
     539            0 :                                                 number d = VecDistanceSq(c1, c2);
     540              : 
     541            0 :                                                 if(d13 < d){
     542              :                                                         bestDiag = 1;
     543              :                                                         d = d13;
     544              :                                                 }
     545            0 :                                                 if(d05 < d){
     546              :                                                         bestDiag = 0;
     547              :                                                 }
     548              :                                         }
     549              : 
     550            0 :                                         switch(bestDiag){
     551              :                                         case 0:// diag: 0-5
     552            0 :                                                 inds[fi++] = GOID_TETRAHEDRON;
     553            0 :                                                 inds[fi++] = NUM_VERTICES + 0;  inds[fi++] = NUM_VERTICES + 1;
     554            0 :                                                 inds[fi++] = NUM_VERTICES + 2;  inds[fi++] = NUM_VERTICES + 5;
     555              : 
     556            0 :                                                 inds[fi++] = GOID_TETRAHEDRON;
     557            0 :                                                 inds[fi++] = NUM_VERTICES + 1;  inds[fi++] = NUM_VERTICES + 4;
     558            0 :                                                 inds[fi++] = NUM_VERTICES + 5;  inds[fi++] = NUM_VERTICES + 0;
     559              : 
     560            0 :                                                 inds[fi++] = GOID_TETRAHEDRON;
     561            0 :                                                 inds[fi++] = NUM_VERTICES + 2;  inds[fi++] = NUM_VERTICES + 5;
     562            0 :                                                 inds[fi++] = NUM_VERTICES + 3;  inds[fi++] = NUM_VERTICES + 0;
     563              : 
     564            0 :                                                 inds[fi++] = GOID_TETRAHEDRON;
     565            0 :                                                 inds[fi++] = NUM_VERTICES + 0;  inds[fi++] = NUM_VERTICES + 3;
     566            0 :                                                 inds[fi++] = NUM_VERTICES + 4;  inds[fi++] = NUM_VERTICES + 5;
     567              : 
     568              :                                                 break;
     569              : 
     570            0 :                                         case 1:// diag: 1-3
     571            0 :                                                 inds[fi++] = GOID_TETRAHEDRON;
     572            0 :                                                 inds[fi++] = NUM_VERTICES + 0;  inds[fi++] = NUM_VERTICES + 1;
     573            0 :                                                 inds[fi++] = NUM_VERTICES + 2;  inds[fi++] = NUM_VERTICES + 3;
     574              : 
     575            0 :                                                 inds[fi++] = GOID_TETRAHEDRON;
     576            0 :                                                 inds[fi++] = NUM_VERTICES + 1;  inds[fi++] = NUM_VERTICES + 4;
     577            0 :                                                 inds[fi++] = NUM_VERTICES + 5;  inds[fi++] = NUM_VERTICES + 3;
     578              : 
     579            0 :                                                 inds[fi++] = GOID_TETRAHEDRON;
     580            0 :                                                 inds[fi++] = NUM_VERTICES + 2;  inds[fi++] = NUM_VERTICES + 5;
     581            0 :                                                 inds[fi++] = NUM_VERTICES + 3;  inds[fi++] = NUM_VERTICES + 1;
     582              : 
     583            0 :                                                 inds[fi++] = GOID_TETRAHEDRON;
     584            0 :                                                 inds[fi++] = NUM_VERTICES + 0;  inds[fi++] = NUM_VERTICES + 3;
     585            0 :                                                 inds[fi++] = NUM_VERTICES + 4;  inds[fi++] = NUM_VERTICES + 1;
     586              : 
     587              :                                                 break;
     588              : 
     589            0 :                                         case 2:// diag 2-4
     590            0 :                                                 inds[fi++] = GOID_TETRAHEDRON;
     591            0 :                                                 inds[fi++] = NUM_VERTICES + 0;  inds[fi++] = NUM_VERTICES + 2;
     592            0 :                                                 inds[fi++] = NUM_VERTICES + 3;  inds[fi++] = NUM_VERTICES + 4;
     593              : 
     594            0 :                                                 inds[fi++] = GOID_TETRAHEDRON;
     595            0 :                                                 inds[fi++] = NUM_VERTICES + 1;  inds[fi++] = NUM_VERTICES + 2;
     596            0 :                                                 inds[fi++] = NUM_VERTICES + 0;  inds[fi++] = NUM_VERTICES + 4;
     597              : 
     598            0 :                                                 inds[fi++] = GOID_TETRAHEDRON;
     599            0 :                                                 inds[fi++] = NUM_VERTICES + 2;  inds[fi++] = NUM_VERTICES + 3;
     600            0 :                                                 inds[fi++] = NUM_VERTICES + 4;  inds[fi++] = NUM_VERTICES + 5;
     601              : 
     602            0 :                                                 inds[fi++] = GOID_TETRAHEDRON;
     603            0 :                                                 inds[fi++] = NUM_VERTICES + 4;  inds[fi++] = NUM_VERTICES + 1;
     604            0 :                                                 inds[fi++] = NUM_VERTICES + 2;  inds[fi++] = NUM_VERTICES + 5;
     605              : 
     606              :                                                 break;
     607              :                                         }
     608              :                                 }break;
     609              :                                 
     610            0 :                                 case HYBRID_TET_OCT:
     611              :                                 {
     612              :                                 //      REGULAR REFINEMENT
     613              :                                         int& fi = fillCount;
     614              :                                         int* inds = newIndsOut;
     615              : 
     616              :                                 //      outer tetrahedrons analogously defined to STANDARD case
     617            0 :                                         inds[fi++] = GOID_TETRAHEDRON;
     618            0 :                                         inds[fi++] = 0;                                 inds[fi++] = NUM_VERTICES + 0;
     619            0 :                                         inds[fi++] = NUM_VERTICES + 2;  inds[fi++] = NUM_VERTICES + 3;
     620              : 
     621            0 :                                         inds[fi++] = GOID_TETRAHEDRON;
     622            0 :                                         inds[fi++] = 1;                                 inds[fi++] = NUM_VERTICES + 1;
     623            0 :                                         inds[fi++] = NUM_VERTICES + 0;  inds[fi++] = NUM_VERTICES + 4;
     624              : 
     625            0 :                                         inds[fi++] = GOID_TETRAHEDRON;
     626            0 :                                         inds[fi++] = 2;                                 inds[fi++] = NUM_VERTICES + 2;
     627            0 :                                         inds[fi++] = NUM_VERTICES + 1;  inds[fi++] = NUM_VERTICES + 5;
     628              : 
     629            0 :                                         inds[fi++] = GOID_TETRAHEDRON;
     630            0 :                                         inds[fi++] = NUM_VERTICES + 3;  inds[fi++] = NUM_VERTICES + 4;
     631            0 :                                         inds[fi++] = NUM_VERTICES + 5;  inds[fi++] = 3;
     632              : 
     633              :                                 //      inner octahedron:
     634              :                                 //      For the remaining inner cavity we'll choose the shortest diagonal
     635              :                                 //      and order the octahedral nodes, so that, the implicit
     636              :                                 //      subdivision of the octahedron into tetrahedrons during
     637              :                                 //      discretization happens alongside exactly this shortest diagonal.
     638              :                                         int bestDiag = 2;
     639            0 :                                         if(corners){
     640              :                                         //      there are three diagonals between the following edge-centers:
     641              :                                         //      0-5, 1-3, 2-4
     642              :                                                 vector3 c1, c2;
     643              : 
     644              :                                         //      0-5
     645              :                                                 VecAdd(c1, corners[0], corners[1]);
     646              :                                                 VecScale(c1, c1, 0.5);
     647              :                                                 VecAdd(c2, corners[2], corners[3]);
     648              :                                                 VecScale(c2, c2, 0.5);
     649            0 :                                                 number d05 = VecDistanceSq(c1, c2);
     650              : 
     651              :                                         //      1-3
     652              :                                                 VecAdd(c1, corners[1], corners[2]);
     653              :                                                 VecScale(c1, c1, 0.5);
     654              :                                                 VecAdd(c2, corners[0], corners[3]);
     655              :                                                 VecScale(c2, c2, 0.5);
     656            0 :                                                 number d13 = VecDistanceSq(c1, c2);
     657              : 
     658              :                                         //      2-4
     659              :                                                 VecAdd(c1, corners[0], corners[2]);
     660              :                                                 VecScale(c1, c1, 0.5);
     661              :                                                 VecAdd(c2, corners[1], corners[3]);
     662              :                                                 VecScale(c2, c2, 0.5);
     663            0 :                                                 number d = VecDistanceSq(c1, c2);
     664              : 
     665            0 :                                                 if(d13 < d){
     666              :                                                         bestDiag = 1;
     667              :                                                         d = d13;
     668              :                                                 }
     669            0 :                                                 if(d05 < d){
     670              :                                                         bestDiag = 0;
     671              :                                                 }
     672              :                                         }
     673              : 
     674            0 :                                         switch(bestDiag){
     675              :                                                 case 0:// diag: 0-5
     676            0 :                                                         inds[fi++] = GOID_OCTAHEDRON;
     677            0 :                                                         inds[fi++] = NUM_VERTICES + 1;          inds[fi++] = NUM_VERTICES + 0;
     678            0 :                                                         inds[fi++] = NUM_VERTICES + 4;          inds[fi++] = NUM_VERTICES + 5;
     679            0 :                                                         inds[fi++] = NUM_VERTICES + 2;          inds[fi++] = NUM_VERTICES + 3;
     680              :                                                 break;
     681              : 
     682            0 :                                                 case 1:// diag: 1-3
     683            0 :                                                         inds[fi++] = GOID_OCTAHEDRON;
     684            0 :                                                         inds[fi++] = NUM_VERTICES + 0;          inds[fi++] = NUM_VERTICES + 3;
     685            0 :                                                         inds[fi++] = NUM_VERTICES + 4;          inds[fi++] = NUM_VERTICES + 1;
     686            0 :                                                         inds[fi++] = NUM_VERTICES + 2;          inds[fi++] = NUM_VERTICES + 5;
     687              :                                                 break;
     688              : 
     689            0 :                                                 case 2:// diag 2-4
     690            0 :                                                         inds[fi++] = GOID_OCTAHEDRON;
     691            0 :                                                         inds[fi++] = NUM_VERTICES + 1;          inds[fi++] = NUM_VERTICES + 2;
     692            0 :                                                         inds[fi++] = NUM_VERTICES + 0;          inds[fi++] = NUM_VERTICES + 4;
     693            0 :                                                         inds[fi++] = NUM_VERTICES + 5;          inds[fi++] = NUM_VERTICES + 3;
     694              :                                                 break;
     695              :                                         }break;
     696              : 
     697              :                                 }break;
     698              :                         }
     699              :                 }break;
     700              :         }
     701              : 
     702            0 :         if(fillCount == 0){
     703              :         //      call recursive refine
     704            0 :                 fillCount = shared_rules::RecursiveRefine(newIndsOut, newEdgeVrts,
     705              :                                                                         FACE_VRT_INDS, FACE_EDGE_INDS, NUM_VERTICES,
     706              :                                                                         NUM_EDGES, NUM_FACES);
     707              : 
     708              :         //      the rule requires a new center vertex
     709            0 :                 newCenterOut = true;
     710              :         }
     711              : 
     712            0 :         return fillCount;
     713              : }
     714              : 
     715              : 
     716            0 : bool IsRegularRefRule(const int edgeMarks)
     717              : {
     718            0 :         return false;
     719              : }
     720              : 
     721              : }//     end of namespace tet_rules
     722              : }//     end of namespace ug
        

Generated by: LCOV version 2.0-1