LCOV - code coverage report
Current view: top level - ugbase/lib_grid/grid_objects - grid_objects_2d.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 4.4 % 248 11
Test Date: 2025-09-21 23:31:46 Functions: 3.3 % 61 2

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2010-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 <vector>
      34              : #include <algorithm>
      35              : #include "grid_objects_2d.h"
      36              : //#include "../algorithms/geom_obj_util/geom_obj_util.h"
      37              : 
      38              : using namespace std;
      39              : 
      40              : namespace ug
      41              : {
      42              : ////////////////////////////////////////////////////////////////////////
      43              : ////////////////////////////////////////////////////////////////////////
      44              : //      TOOLS
      45              : ///     helpful if a local vertex-order is required
      46              : /**
      47              :  * cornersOut and cornersIn both have to be of size numCorners.
      48              :  * After termination cornersOut will contain the vertices of
      49              :  * cornersIn, starting from firstCorner, taking vertices modulo numCorners.
      50              :  * If cornersOut == cornersIn, the method will fail! This is ok since
      51              :  * the method is used locally and has been created for a special case.
      52              :  */
      53              : static inline
      54              : bool ReorderCornersCCW(Vertex** cornersOut, Vertex** const cornersIn,
      55              :                                            int numCorners, int firstCorner)
      56              : {
      57            0 :         cornersOut[0] = cornersIn[firstCorner];
      58            0 :         for(int i = 1; i < numCorners; ++i)
      59            0 :                 cornersOut[i] = cornersIn[(firstCorner + i) % numCorners];
      60              :         return true;
      61              : }
      62              : 
      63              : 
      64              : ////////////////////////////////////////////////////////////////////////
      65              : ////////////////////////////////////////////////////////////////////////
      66              : //      FACES
      67              : 
      68              : ////////////////////////////////////////////////////////////////////////
      69              : //      TriangleDescriptor
      70            0 : TriangleDescriptor::TriangleDescriptor(const TriangleDescriptor& td)
      71              : {
      72            0 :         m_vertex[0] = td.vertex(0);
      73            0 :         m_vertex[1] = td.vertex(1);
      74            0 :         m_vertex[2] = td.vertex(2);
      75            0 : }
      76              : 
      77            1 : TriangleDescriptor::TriangleDescriptor(Vertex* v1, Vertex* v2, Vertex* v3)
      78              : {
      79            1 :         m_vertex[0] = v1;
      80            1 :         m_vertex[1] = v2;
      81            1 :         m_vertex[2] = v3;
      82            1 : }
      83              : 
      84              : ////////////////////////////////////////////////////////////////////////
      85              : //      CustomTriangle
      86              : template <class ConcreteTriangleType, class BaseClass, class RefTriType, class RefQuadType>
      87            1 : CustomTriangle<ConcreteTriangleType, BaseClass, RefTriType, RefQuadType>::
      88            1 : CustomTriangle(const TriangleDescriptor& td)
      89              : {
      90            1 :         m_vertices[0] = td.vertex(0);
      91            1 :         m_vertices[1] = td.vertex(1);
      92            1 :         m_vertices[2] = td.vertex(2);
      93            1 : }
      94              : 
      95              : template <class ConcreteTriangleType, class BaseClass, class RefTriType, class RefQuadType>
      96            0 : CustomTriangle<ConcreteTriangleType, BaseClass, RefTriType, RefQuadType>::
      97            0 : CustomTriangle(Vertex* v1, Vertex* v2, Vertex* v3)
      98              : {
      99            0 :         m_vertices[0] = v1;
     100            0 :         m_vertices[1] = v2;
     101            0 :         m_vertices[2] = v3;
     102            0 : }
     103              : 
     104              : template <class ConcreteTriangleType, class BaseClass, class RefTriType, class RefQuadType>
     105              : std::pair<GridBaseObjectId, int>
     106            0 : CustomTriangle<ConcreteTriangleType, BaseClass, RefTriType, RefQuadType>::
     107              : get_opposing_object(Vertex* vrt) const
     108              : {
     109            0 :         for(int i = 0; i < 3; ++i){
     110            0 :                 if(vrt == m_vertices[i]){
     111            0 :                         return make_pair(EDGE, (i + 1) % 3);
     112              :                 }
     113              :         }
     114              : 
     115            0 :         UG_THROW("The given vertex is not contained in the given face.");
     116              : }
     117              : 
     118              : template <class ConcreteTriangleType, class BaseClass, class RefTriType, class RefQuadType>
     119              : bool
     120            0 : CustomTriangle<ConcreteTriangleType, BaseClass, RefTriType, RefQuadType>::
     121              : refine(std::vector<Face*>& vNewFacesOut,
     122              :                 Vertex** newFaceVertexOut,
     123              :                 Vertex** newEdgeVertices,
     124              :                 Vertex* newFaceVertex,
     125              :                 Vertex** pSubstituteVertices,
     126              :                 int snapPointIndex)
     127              : {
     128              : //TODO: complete triangle refine
     129              : 
     130            0 :         *newFaceVertexOut = newFaceVertex;
     131              :         vNewFacesOut.clear();
     132              : 
     133              : //      handle substitute vertices.
     134              :         Vertex** vrts;
     135            0 :         if(pSubstituteVertices)
     136              :                 vrts = pSubstituteVertices;
     137              :         else
     138            0 :                 vrts = m_vertices;
     139              : 
     140              : //      get the number of new vertices.
     141              :         uint numNewVrts = 0;
     142            0 :         for(uint i = 0; i < 3; ++i)
     143              :         {
     144            0 :                 if(newEdgeVertices[i] != NULL)
     145            0 :                         ++numNewVrts;
     146              :         }
     147              : 
     148              : //      if newFaceVertex is specified, then create three sub-triangles and
     149              : //      refine each. If not then refine the triangle depending
     150            0 :         if(newFaceVertex)
     151              :         {
     152            0 :                 if(numNewVrts > 0){
     153              :                         assert(!"Problem in CustomTriangle::refine: refine with newFaceVertex and newEdgeVertices is not yet supported.");
     154              :                         return false;
     155              :                 }
     156              : 
     157              :         //      create three new triangles
     158            0 :                 vNewFacesOut.push_back(new RefTriType(vrts[0], vrts[1], newFaceVertex));
     159            0 :                 vNewFacesOut.push_back(new RefTriType(vrts[1], vrts[2], newFaceVertex));
     160            0 :                 vNewFacesOut.push_back(new RefTriType(vrts[2], vrts[0], newFaceVertex));
     161            0 :                 return true;
     162              :         }
     163              :         else
     164              :         {
     165            0 :                 switch(numNewVrts)
     166              :                 {
     167            0 :                         case 0: // this may happen when the triangle belongs to a prism being anisotropically refined
     168              :                                         // and the volume on the other side is not being refined
     169            0 :                                 vNewFacesOut.push_back(new RefTriType(vrts[0], vrts[1], vrts[2]));
     170            0 :                                 return true;
     171              : 
     172              :                         case 1:
     173              :                         {
     174              :                         //      get the index of the edge that will be refined
     175              :                                 int iNew = -1;;
     176            0 :                                 for(int i = 0; i < 3; ++i){
     177            0 :                                         if(newEdgeVertices[i]){
     178              :                                                 iNew = i;
     179              :                                                 break;
     180              :                                         }
     181              :                                 }
     182              :                                 
     183              :                         //      the corners. The first corner is the corner on the opposite side of iNew.
     184              :                         //      Other follow in ccw order
     185              :                                 int iCorner[3];
     186            0 :                                 iCorner[0] = (iNew + 2) % 3;
     187            0 :                                 iCorner[1] = (iCorner[0] + 1) % 3;
     188            0 :                                 iCorner[2] = (iCorner[1] + 1) % 3;
     189              :                                         
     190              :                         //      create the new triangles.
     191            0 :                                 vNewFacesOut.push_back(new RefTriType(vrts[iCorner[0]], vrts[iCorner[1]],
     192            0 :                                                                                                                                 newEdgeVertices[iNew]));
     193            0 :                                 vNewFacesOut.push_back(new RefTriType(vrts[iCorner[0]], newEdgeVertices[iNew],
     194            0 :                                                                                                                                 vrts[iCorner[2]]));
     195              :                                                                                                                                 
     196              :                                 return true;
     197              :                         }
     198              : 
     199              :                         case 2:
     200              :                         {
     201              :                         //      get the index of the edge that won't be refined
     202              :                                 int iFree = -1;
     203            0 :                                 for(int i = 0; i < 3; ++i){
     204            0 :                                         if(!newEdgeVertices[i]){
     205              :                                                 iFree = i;
     206              :                                                 break;
     207              :                                         }
     208              :                                 }
     209              :                                 
     210              :                         //      the refined edges
     211              :                                 int iNew[2];
     212            0 :                                 iNew[0] = (iFree + 1) % 3;
     213            0 :                                 iNew[1] = (iFree + 2) % 3;
     214              :                                 
     215              :                         //      the corners
     216              :                                 int iCorner[3];
     217              :                                 iCorner[0] = iFree;
     218              :                                 iCorner[1] = (iFree + 1) % 3;
     219              :                                 iCorner[2] = (iFree + 2) % 3;
     220              :                                 
     221              :                         //      create the faces
     222            0 :                                 vNewFacesOut.push_back(new RefTriType(newEdgeVertices[iNew[0]],
     223            0 :                                                                                                                                 vrts[iCorner[2]],
     224            0 :                                                                                                                                 newEdgeVertices[iNew[1]]));
     225            0 :                                 vNewFacesOut.push_back(new RefQuadType(vrts[iCorner[0]], vrts[iCorner[1]],
     226              :                                                                                                                 newEdgeVertices[iNew[0]], newEdgeVertices[iNew[1]]));
     227              :                                 return true;
     228              :                         }
     229              : 
     230            0 :                         case 3:
     231              :                         {
     232              :                         //      perform regular refine.
     233            0 :                                 vNewFacesOut.push_back(new RefTriType(vrts[0], newEdgeVertices[0], newEdgeVertices[2]));
     234            0 :                                 vNewFacesOut.push_back(new RefTriType(vrts[1], newEdgeVertices[1], newEdgeVertices[0]));
     235            0 :                                 vNewFacesOut.push_back(new RefTriType(vrts[2], newEdgeVertices[2], newEdgeVertices[1]));
     236            0 :                                 vNewFacesOut.push_back(new RefTriType(newEdgeVertices[0], newEdgeVertices[1], newEdgeVertices[2]));
     237            0 :                                 return true;
     238              :                         }
     239              : 
     240              :                 }
     241              :         }
     242              : 
     243              :         return false;
     244              : }
     245              : 
     246              : template <class ConcreteTriangleType, class BaseClass, class RefTriType, class RefQuadType>
     247              : bool
     248            0 : CustomTriangle<ConcreteTriangleType, BaseClass, RefTriType, RefQuadType>::
     249              : is_regular_ref_rule(int edgeMarks) const
     250              : {
     251            0 :         return edgeMarks == 7;
     252              : }
     253              : 
     254              : template <class ConcreteTriangleType, class BaseClass, class RefTriType, class RefQuadType>
     255              : bool
     256            0 : CustomTriangle<ConcreteTriangleType, BaseClass, RefTriType, RefQuadType>::
     257              : collapse_edge(std::vector<Face*>& vNewFacesOut,
     258              :                                 int edgeIndex, Vertex* newVertex,
     259              :                                 Vertex** pSubstituteVertices)
     260              : {
     261              : //      if an edge of the triangle is collapsed, nothing remains
     262              :         vNewFacesOut.clear();
     263            0 :         return true;
     264              : }
     265              : 
     266              : template <class ConcreteTriangleType, class BaseClass, class RefTriType, class RefQuadType>
     267              : bool
     268            0 : CustomTriangle<ConcreteTriangleType, BaseClass, RefTriType, RefQuadType>::
     269              : collapse_edges(std::vector<Face*>& vNewFacesOut,
     270              :                                 std::vector<Vertex*>& vNewEdgeVertices,
     271              :                                 Vertex** pSubstituteVertices)
     272              : {
     273            0 :         if(vNewEdgeVertices.size() > BaseClass::num_edges())
     274              :         {
     275              :                 assert(!"WARNING in Triangle::collapse_edges(...): bad number of newEdgeVertices.");
     276              :                 LOG("WARNING in Triangle::collapse_edges(...): bad number of newEdgeVertices.");
     277            0 :                 return false;
     278              :         }
     279              : 
     280              : //      check if there is a valid entry in vNewEdgeVertices
     281              :         bool bGotOne = false;
     282            0 :         for(uint i = 0; i < vNewEdgeVertices.size(); ++i)
     283              :         {
     284            0 :                 if(vNewEdgeVertices[i] != NULL)
     285              :                 {
     286              :                         bGotOne = true;
     287              :                         break;
     288              :                 }
     289              :         }
     290              : 
     291            0 :         if(!bGotOne)
     292              :         {
     293              :                 assert(!"WARNING in Triangle::collapse:edges(...): no new vertex was specified.");
     294              :                 LOG("WARNING in Triangle::collapse:edges(...): no new vertex was specified.");
     295            0 :                 return false;
     296              :         }
     297              : 
     298              : //      if an edge of the triangle is collapsed, nothing remains
     299              :         vNewFacesOut.clear();
     300              :         return true;
     301              : }
     302              : 
     303              : //      BEGIN Depreciated
     304              : template <class ConcreteTriangleType, class BaseClass, class RefTriType, class RefQuadType>
     305              : void
     306            0 : CustomTriangle<ConcreteTriangleType, BaseClass, RefTriType, RefQuadType>::
     307              : create_faces_by_edge_split(int splitEdgeIndex,
     308              :                                                                 Vertex* newVertex,
     309              :                                                                 std::vector<Face*>& vNewFacesOut,
     310              :                                                                 Vertex** pSubstituteVertices)
     311              : {
     312              :         assert(((splitEdgeIndex >= 0) && (splitEdgeIndex < 3)) && "ERROR in Triangle::create_faces_by_edge_split(...): bad edge index!");
     313              : 
     314              : //      if pvSubstituteVertices is supplied, we will use the vertices in
     315              : //      pvSubstituteVertices instead the ones of 'this'.
     316              : //      If not, we will redirect the pointer to a local local vector,
     317              : //      that holds the vertices of 'this'
     318              :         Vertex** vrts;
     319            0 :         if(pSubstituteVertices)
     320              :                 vrts = pSubstituteVertices;
     321              :         else
     322            0 :                 vrts = m_vertices;
     323              : 
     324              : //      we have to find the indices ind0, ind1, ind2, where
     325              : //      ind0 is the index of the vertex on e before newVertex,
     326              : //      ind1 is the index of the vertex on e after newVertex
     327              : //      and ind2 is the index of the vertex not located on e.
     328              : 
     329              :         int ind0 = splitEdgeIndex;
     330            0 :         int ind1 = (ind0 + 1) % 3;
     331            0 :         int ind2 = (ind1 + 1) % 3;
     332              : 
     333            0 :         vNewFacesOut.push_back(new Triangle(vrts[ind0], newVertex, vrts[ind2]));
     334            0 :         vNewFacesOut.push_back(new Triangle(newVertex, vrts[ind1], vrts[ind2]));
     335            0 : }
     336              : 
     337              : 
     338              : ////////////////////////////////////////////////////////////////////////
     339              : ////////////////////////////////////////////////////////////////////////
     340              : //      QUADRILATERALS
     341              : 
     342              : ////////////////////////////////////////////////////////////////////////
     343              : //      QuadrilateralDescriptor
     344            0 : QuadrilateralDescriptor::QuadrilateralDescriptor(const QuadrilateralDescriptor& qd)
     345              : {
     346            0 :         m_vertex[0] = qd.vertex(0);
     347            0 :         m_vertex[1] = qd.vertex(1);
     348            0 :         m_vertex[2] = qd.vertex(2);
     349            0 :         m_vertex[3] = qd.vertex(3);
     350            0 : }
     351              : 
     352            0 : QuadrilateralDescriptor::QuadrilateralDescriptor(Vertex* v1, Vertex* v2, Vertex* v3, Vertex* v4)
     353              : {
     354            0 :         m_vertex[0] = v1;
     355            0 :         m_vertex[1] = v2;
     356            0 :         m_vertex[2] = v3;
     357            0 :         m_vertex[3] = v4;
     358            0 : }
     359              : 
     360              : ////////////////////////////////////////////////////////////////////////
     361              : //      Quad
     362              : 
     363              : template <class ConcreteQuadrilateralType, class BaseClass, class RefTriType, class RefQuadType>
     364            0 : CustomQuadrilateral<ConcreteQuadrilateralType, BaseClass, RefTriType, RefQuadType>::
     365            0 : CustomQuadrilateral(const QuadrilateralDescriptor& qd)
     366              : {
     367            0 :         m_vertices[0] = qd.vertex(0);
     368            0 :         m_vertices[1] = qd.vertex(1);
     369            0 :         m_vertices[2] = qd.vertex(2);
     370            0 :         m_vertices[3] = qd.vertex(3);
     371            0 : }
     372              : 
     373              : template <class ConcreteQuadrilateralType, class BaseClass, class RefTriType, class RefQuadType>
     374            0 : CustomQuadrilateral<ConcreteQuadrilateralType, BaseClass, RefTriType, RefQuadType>::
     375            0 : CustomQuadrilateral(Vertex* v1, Vertex* v2, Vertex* v3, Vertex* v4)
     376              : {
     377            0 :         m_vertices[0] = v1;
     378            0 :         m_vertices[1] = v2;
     379            0 :         m_vertices[2] = v3;
     380            0 :         m_vertices[3] = v4;
     381            0 : }
     382              : 
     383              : template <class ConcreteQuadrilateralType, class BaseClass, class RefTriType, class RefQuadType>
     384              : bool
     385            0 : CustomQuadrilateral<ConcreteQuadrilateralType, BaseClass, RefTriType, RefQuadType>::
     386              : get_opposing_side(EdgeVertices* e, EdgeDescriptor& edOut) const
     387              : {
     388            0 :         int localInd = Face::get_local_side_index(e);
     389            0 :         if(localInd == -1){
     390              :                 return false;
     391              :         }
     392              : 
     393            0 :         edge_desc((localInd + 2) % 4, edOut);
     394            0 :         return true;
     395              : }
     396              : 
     397              : template <class ConcreteQuadrilateralType, class BaseClass, class RefTriType, class RefQuadType>
     398              : std::pair<GridBaseObjectId, int>
     399            0 : CustomQuadrilateral<ConcreteQuadrilateralType, BaseClass, RefTriType, RefQuadType>::
     400              : get_opposing_object(Vertex* vrt) const
     401              : {
     402            0 :         for(int i = 0; i < 4; ++i){
     403            0 :                 if(vrt == m_vertices[i]){
     404            0 :                         return make_pair(VERTEX, (i + 2) % 4);
     405              :                 }
     406              :         }
     407              : 
     408            0 :         UG_THROW("The given vertex is not contained in the given face.");
     409              : }
     410              : 
     411              : template <class ConcreteQuadrilateralType, class BaseClass, class RefTriType, class RefQuadType>
     412              : void
     413            0 : CustomQuadrilateral<ConcreteQuadrilateralType, BaseClass, RefTriType, RefQuadType>::
     414              : create_faces_by_edge_split(int splitEdgeIndex,
     415              :                                                         Vertex* newVertex,
     416              :                                                         std::vector<Face*>& vNewFacesOut,
     417              :                                                         Vertex** pSubstituteVertices)
     418              : {
     419              :         assert(((splitEdgeIndex >= 0) && (splitEdgeIndex < 4)) && "ERROR in Quadrilateral::create_faces_by_edge_split(...): bad edge index!");
     420              : 
     421              : //      if pvSubstituteVertices is supplied, we will use the vertices in
     422              : //      pvSubstituteVertices instead the ones of 'this'.
     423              : //      If not, we will redirect the pointer to a local local vector,
     424              : //      that holds the vertices of 'this'
     425              :         Vertex** vrts;
     426            0 :         if(pSubstituteVertices)
     427              :                 vrts = pSubstituteVertices;
     428              :         else
     429            0 :                 vrts = m_vertices;
     430              : 
     431              : //      we have to find the indices ind0, ind1, ind2, where
     432              : //      ind0 is the index of the vertex on e before newVertex,
     433              : //      ind1 is the index of the vertex on e after newVertex
     434              : //      and ind2 and ind3 are the indices of the vertices not located on e.
     435              :         int ind0 = splitEdgeIndex; //edge-index equals the index of its first vertex.
     436            0 :         int ind1 = (ind0 + 1) % 4;
     437            0 :         int ind2 = (ind0 + 2) % 4;
     438            0 :         int ind3 = (ind0 + 3) % 4;
     439              : 
     440              :         TriangleDescriptor td;
     441              : 
     442              : //      edge-split generates 3 triangles
     443            0 :         vNewFacesOut.push_back(new RefTriType(vrts[ind0], newVertex, vrts[ind3]));
     444            0 :         vNewFacesOut.push_back(new RefTriType(newVertex, vrts[ind1], vrts[ind2]));
     445            0 :         vNewFacesOut.push_back(new RefTriType(vrts[ind3], newVertex, vrts[ind2]));
     446              : 
     447              : //      we're done.
     448            0 : }
     449              : 
     450              : ////////////////////////////////////////////////////////////////////////
     451              : //      Quadrilateral::refine
     452              : template <class ConcreteQuadrilateralType, class BaseClass, class RefTriType, class RefQuadType>
     453              : bool
     454            0 : CustomQuadrilateral<ConcreteQuadrilateralType, BaseClass, RefTriType, RefQuadType>::
     455              : refine(std::vector<Face*>& vNewFacesOut,
     456              :                 Vertex** newFaceVertexOut,
     457              :                 Vertex** edgeVrts,
     458              :                 Vertex* newFaceVertex,
     459              :                 Vertex** pSubstituteVertices,
     460              :                 int snapPointIndex)
     461              : {
     462              : //TODO: complete quad refine
     463            0 :         *newFaceVertexOut = newFaceVertex;
     464              :         vNewFacesOut.clear();
     465              :         
     466              : //      handle substitute vertices.
     467              :         Vertex** vrts;
     468            0 :         if(pSubstituteVertices)
     469              :                 vrts = pSubstituteVertices;
     470              :         else
     471            0 :                 vrts = m_vertices;
     472              : 
     473              : //      check which edges have to be refined and perform the required operations.
     474              : //      get the number of new vertices.
     475              :         uint numNewVrts = 0;
     476            0 :         for(uint i = 0; i < 4; ++i)
     477              :         {
     478            0 :                 if(edgeVrts[i] != NULL)
     479            0 :                         ++numNewVrts;
     480              :         }
     481              : 
     482            0 :         switch(numNewVrts)
     483              :         {
     484            0 :                 case 0:
     485              :                         // refine with mid point if it exists
     486            0 :                         if (newFaceVertex)
     487              :                         {
     488              :                         //      create four new triangles
     489            0 :                                 vNewFacesOut.push_back(new RefTriType(vrts[0], vrts[1], newFaceVertex));
     490            0 :                                 vNewFacesOut.push_back(new RefTriType(vrts[1], vrts[2], newFaceVertex));
     491            0 :                                 vNewFacesOut.push_back(new RefTriType(vrts[2], vrts[3], newFaceVertex));
     492            0 :                                 vNewFacesOut.push_back(new RefTriType(vrts[3], vrts[0], newFaceVertex));
     493            0 :                                 return true;
     494              :                         }
     495              : 
     496              :                         // in case the mid point does not exists, we need a simple copy
     497              :                         // This may happen when the quad belongs to a hexahedron being anisotropically refined
     498              :                         // and the volume on the other side is not being refined.
     499            0 :                         vNewFacesOut.push_back(new RefQuadType(vrts[0], vrts[1], vrts[2], vrts[3]));
     500            0 :                         return true;
     501              :                         
     502            0 :                 case 1:
     503              :                 {
     504            0 :                         if(newFaceVertex){
     505              :                                 assert(!"Problem in CustomQuadrilateral::refine: refine with newFaceVertex and one newEdgeVertex is not yet supported.");
     506              :                                 return false;
     507              :                         }
     508              :                         
     509              :                         int iNew = -1;
     510            0 :                         for(int i = 0; i < 4; ++i){
     511            0 :                                 if(edgeVrts[i]){
     512              :                                         iNew = i;
     513              :                                         break;
     514              :                                 }
     515              :                         }
     516              : 
     517            0 :                         if(snapPointIndex != -1 && (snapPointIndex == iNew || snapPointIndex == (iNew + 1) % 4)){
     518              :                                 UG_LOG("WARNING: Invalid snap-point distribution detected. Ignoring snap-points for this element.\n");
     519              :                                 snapPointIndex = -1;
     520              :                         }
     521              :                         
     522              :                 //      the corners in a local ordering relative to iNew. Keeping ccw order.
     523              :                         Vertex* corner[4];
     524            0 :                         const int rot = (iNew + 3) % 4;
     525              :                         ReorderCornersCCW(corner, vrts, 4, rot);
     526              : 
     527              :                 //      create the new elements
     528            0 :                         if(snapPointIndex == -1){
     529            0 :                                 vNewFacesOut.push_back(new RefTriType(corner[0], corner[1], edgeVrts[iNew]));
     530            0 :                                 vNewFacesOut.push_back(new RefTriType(corner[0], edgeVrts[iNew], corner[3]));
     531            0 :                                 vNewFacesOut.push_back(new RefTriType(corner[3], edgeVrts[iNew], corner[2]));
     532              :                         }
     533              :                         else{
     534            0 :                                 snapPointIndex = (snapPointIndex + 4 - rot) % 4;
     535            0 :                                 if(snapPointIndex == 0){
     536            0 :                                         vNewFacesOut.push_back(new RefTriType(corner[0], corner[1], edgeVrts[iNew]));
     537            0 :                                         vNewFacesOut.push_back(new RefQuadType(corner[0], edgeVrts[iNew], corner[2], corner[3]));
     538              :                                 }
     539            0 :                                 else if(snapPointIndex == 3){
     540            0 :                                         vNewFacesOut.push_back(new RefQuadType(corner[0], corner[1], edgeVrts[iNew], corner[3]));
     541            0 :                                         vNewFacesOut.push_back(new RefTriType(corner[3], edgeVrts[iNew], corner[2]));
     542              :                                 }
     543              :                                 else{
     544            0 :                                         UG_THROW("Unexpected snap-point index: " << snapPointIndex << ". This is an implementation error!");
     545              :                                 }
     546              :                         }
     547              : 
     548              :                         return true;
     549              :                 }
     550              : 
     551            0 :                 case 2:
     552              :                 {
     553            0 :                         if(newFaceVertex){
     554              :                                 assert(!"Problem in CustomQuadrilateral::refine: refine with newFaceVertex and two newEdgeVertices is not yet supported.");
     555              :                                 return false;
     556              :                         }
     557              : 
     558              :                 //      there are two cases (refined edges are adjacent or opposite to each other)
     559              :                         int iNew[2];
     560              :                         int counter = 0;
     561            0 :                         for(int i = 0; i < 4; ++i){
     562            0 :                                 if(edgeVrts[i]){
     563            0 :                                         iNew[counter] = i;
     564            0 :                                         ++counter;
     565              :                                 }
     566              :                         }
     567              : 
     568              :                 //      corners will be filled later on
     569              :                         Vertex* corner[4];
     570              : 
     571              :                 //      check which case applies
     572            0 :                         if(iNew[1] - iNew[0] == 2){
     573              :                         //      edges are opposite to each other
     574              :                         //      the corners in a local ordering relative to iNew[0]. Keeping ccw order.
     575            0 :                                 ReorderCornersCCW(corner, vrts, 4, (iNew[0] + 3) % 4);
     576              :                                 
     577              :                         //      create new faces
     578            0 :                                 vNewFacesOut.push_back(new RefQuadType(corner[0], corner[1],
     579            0 :                                                                                                         edgeVrts[iNew[0]], edgeVrts[iNew[1]]));
     580              : 
     581            0 :                                 vNewFacesOut.push_back(new RefQuadType(edgeVrts[iNew[1]], edgeVrts[iNew[0]],
     582              :                                                                                                                 corner[2], corner[3]));
     583              :                         }
     584              :                         else{
     585              :                         //      edges are adjacent
     586              :                         //      we want that (iNew[0] + 1) % 4 == iNew[1]
     587            0 :                                 if((iNew[0] + 1) % 4 != iNew[1])
     588              :                                         swap(iNew[0], iNew[1]);
     589              :                         
     590              :                         //      the corners in a local ordering relative to iNew[0]. Keeping ccw order.
     591            0 :                                 const int rot = (iNew[0] + 3) % 4;
     592              :                                 ReorderCornersCCW(corner, vrts, 4, rot);
     593              : 
     594            0 :                                 if(snapPointIndex != -1 && ((snapPointIndex + 4 - rot) % 4) != 0){
     595              :                                         snapPointIndex = -1;
     596              :                                         UG_LOG("WARNING: Invalid snap-point distribution detected. Ignoring snap-points for this element.\n");
     597              :                                 }
     598              : 
     599              : 
     600              :                         //      create new faces
     601              :                                 if(snapPointIndex == -1){
     602            0 :                                         vNewFacesOut.push_back(new RefTriType(corner[0], corner[1], edgeVrts[iNew[0]]));
     603            0 :                                         vNewFacesOut.push_back(new RefTriType(edgeVrts[iNew[0]], corner[2], edgeVrts[iNew[1]]));
     604            0 :                                         vNewFacesOut.push_back(new RefTriType(corner[3], corner[0], edgeVrts[iNew[1]]));
     605            0 :                                         vNewFacesOut.push_back(new RefTriType(corner[0], edgeVrts[iNew[0]], edgeVrts[iNew[1]]));
     606              :                                 }
     607              :                                 else{
     608            0 :                                         vNewFacesOut.push_back(new RefTriType(corner[0], corner[1], edgeVrts[iNew[0]]));
     609            0 :                                         vNewFacesOut.push_back(new RefTriType(corner[3], corner[0], edgeVrts[iNew[1]]));
     610            0 :                                         vNewFacesOut.push_back(new RefQuadType(corner[0], edgeVrts[iNew[0]], corner[2], edgeVrts[iNew[1]]));
     611              :                                 }
     612              :                         }
     613              : 
     614              :                         return true;
     615              :                 }
     616              : 
     617            0 :                 case 3:
     618              :                 {
     619            0 :                         if(newFaceVertex){
     620              :                                 assert(!"Problem in CustomQuadrilateral::refine: refine with newFaceVertex and three newEdgeVertices is not yet supported.");
     621              :                                 return false;
     622              :                         }
     623              : 
     624              :                         int iFree = -1;
     625            0 :                         for(int i = 0; i < 4; ++i){
     626            0 :                                 if(!edgeVrts[i]){
     627              :                                         iFree = i;
     628              :                                         break;
     629              :                                 }
     630              :                         }
     631              :                         
     632              :                 //      the vertices on the edges:
     633              :                         Vertex* nvrts[3];
     634            0 :                         nvrts[0] = edgeVrts[(iFree + 1) % 4];
     635            0 :                         nvrts[1] = edgeVrts[(iFree + 2) % 4];
     636            0 :                         nvrts[2] = edgeVrts[(iFree + 3) % 4];
     637              : 
     638              :                 //      the corners in a local ordering relative to iNew. Keeping ccw order.
     639              :                         Vertex* corner[4];
     640              :                         ReorderCornersCCW(corner, vrts, 4, (iFree + 1) % 4);
     641              : 
     642              :                 //      create the faces
     643            0 :                         vNewFacesOut.push_back(new RefQuadType(corner[0], nvrts[0], nvrts[2], corner[3]));
     644            0 :                         vNewFacesOut.push_back(new RefTriType(corner[1], nvrts[1], nvrts[0]));
     645            0 :                         vNewFacesOut.push_back(new RefTriType(corner[2], nvrts[2], nvrts[1]));
     646            0 :                         vNewFacesOut.push_back(new RefTriType(nvrts[0], nvrts[1], nvrts[2]));
     647              : 
     648            0 :                         return true;
     649              :                 }
     650              : 
     651            0 :                 case 4:
     652              :                 {
     653              :                 //      we'll create 4 new quads. create a new center if required.
     654            0 :                         if(!newFaceVertex)
     655            0 :                                 newFaceVertex = new RegularVertex;
     656              : 
     657            0 :                         *newFaceVertexOut = newFaceVertex;
     658              :                 
     659            0 :                         vNewFacesOut.push_back(new RefQuadType(vrts[0], edgeVrts[0], newFaceVertex, edgeVrts[3]));
     660            0 :                         vNewFacesOut.push_back(new RefQuadType(vrts[1], edgeVrts[1], newFaceVertex, edgeVrts[0]));
     661            0 :                         vNewFacesOut.push_back(new RefQuadType(vrts[2], edgeVrts[2], newFaceVertex, edgeVrts[1]));
     662            0 :                         vNewFacesOut.push_back(new RefQuadType(vrts[3], edgeVrts[3], newFaceVertex, edgeVrts[2]));
     663            0 :                         return true;
     664              :                 }
     665              :         }
     666              : 
     667              :         return false;
     668              : }
     669              : 
     670              : template <class ConcreteQuadrilateralType, class BaseClass, class RefTriType, class RefQuadType>
     671              : bool
     672            0 : CustomQuadrilateral<ConcreteQuadrilateralType, BaseClass, RefTriType, RefQuadType>::
     673              : is_regular_ref_rule(int edgeMarks) const
     674              : {
     675              :         static const int allEdges = 15; // 1111
     676              :         static const int hEdges = 5;    // 0101
     677              :         static const int vEdges = 10;   // 1010
     678              : 
     679            0 :         return          (edgeMarks == allEdges)
     680            0 :                         ||      (edgeMarks == hEdges)
     681            0 :                         ||      (edgeMarks == vEdges);
     682              : }
     683              : 
     684              : 
     685              : template <class ConcreteQuadrilateralType, class BaseClass, class RefTriType, class RefQuadType>
     686              : bool
     687            0 : CustomQuadrilateral<ConcreteQuadrilateralType, BaseClass, RefTriType, RefQuadType>::
     688              : collapse_edge(std::vector<Face*>& vNewFacesOut,
     689              :                                 int edgeIndex, Vertex* newVertex,
     690              :                                 Vertex** pSubstituteVertices)
     691              : {
     692              : //      if an edge of the triangle is collapsed, nothing remains
     693              :         vNewFacesOut.clear();
     694              : 
     695              : //      handle substitute vertices.
     696              :         Vertex** vrts;
     697            0 :         if(pSubstituteVertices)
     698              :                 vrts = pSubstituteVertices;
     699              :         else
     700            0 :                 vrts = m_vertices;
     701              : 
     702              : //      the collapsed edge connects vertices at ind0 and ind1.
     703              :         int ind0 = edgeIndex; //edge-index equals the index of its first vertex.
     704            0 :         int ind1 = (ind0 + 1) % 4;
     705            0 :         int ind2 = (ind1 + 1) % 4;
     706            0 :         int ind3 = (ind2 + 1) % 4;
     707              : 
     708              : //      ind0 and ind1 will be replaced by newVertex.
     709            0 :         vNewFacesOut.push_back(new RefTriType(newVertex, vrts[ind2], vrts[ind3]));
     710            0 :         return true;
     711              : }
     712              : 
     713              : template <class ConcreteQuadrilateralType, class BaseClass, class RefTriType, class RefQuadType>
     714              : bool
     715            0 : CustomQuadrilateral<ConcreteQuadrilateralType, BaseClass, RefTriType, RefQuadType>::
     716              : collapse_edges(std::vector<Face*>& vNewFacesOut,
     717              :                                 std::vector<Vertex*>& vNewEdgeVertices,
     718              :                                 Vertex** pSubstituteVertices)
     719              : {
     720            0 :         if(vNewEdgeVertices.size() > BaseClass::num_edges())
     721              :         {
     722              :                 assert(!"WARNING in Quadrilateral::collapse_edges(...): bad number of newEdgeVertices.");
     723              :                 LOG("WARNING in Quadrilateral::collapse_edges(...): bad number of newEdgeVertices.");
     724            0 :                 return false;
     725              :         }
     726              : 
     727              :         vNewFacesOut.clear();
     728              : 
     729              : //      check if there is a valid entry in vNewEdgeVertices
     730              :         int collapseIndex = -1;
     731              :         int numCollapses = 0;
     732            0 :         for(uint i = 0; i < 4; ++i)
     733              :         {
     734            0 :                 if(i < vNewEdgeVertices.size())
     735              :                 {
     736            0 :                         if(vNewEdgeVertices[i] != NULL)
     737              :                         {
     738            0 :                                 ++numCollapses;
     739            0 :                                 collapseIndex = i;
     740              :                         }
     741              :                 }
     742              :         }
     743              : 
     744              : //      if more than 1 edge is collapsed, nothing remains.
     745            0 :         if(numCollapses == 0)
     746              :         {
     747              :                 assert(!"WARNING in Quadrilateral::collapse:edges(...): no new vertex was specified.");
     748              :                 LOG("WARNING in Quadrilateral::collapse:edges(...): no new vertex was specified.");
     749            0 :                 return false;
     750              :         }
     751            0 :         else if(numCollapses == 1)
     752              :         {
     753              :         //      call collapse_edge with the edges index.
     754            0 :                 collapse_edge(vNewFacesOut, collapseIndex, vNewEdgeVertices[collapseIndex], pSubstituteVertices);
     755              :         }
     756              : 
     757              :         return true;
     758              : }
     759              : 
     760              : //      explicit instantiation
     761              : template class CustomTriangle<Triangle, Face, Triangle, Quadrilateral>;
     762              : template class CustomTriangle<ConstrainedTriangle, ConstrainedFace,
     763              :                                                           ConstrainedTriangle, ConstrainedQuadrilateral>;
     764              : template class CustomTriangle<ConstrainingTriangle, ConstrainingFace,
     765              :                                                           ConstrainingTriangle, ConstrainingQuadrilateral>;
     766              : 
     767              : template class CustomQuadrilateral<Quadrilateral, Face, Triangle, Quadrilateral>;
     768              : template class CustomQuadrilateral<ConstrainedQuadrilateral, ConstrainedFace,
     769              :                                                                    ConstrainedTriangle, ConstrainedQuadrilateral>;
     770              : template class CustomQuadrilateral<ConstrainingQuadrilateral, ConstrainingFace,
     771              :                                                                    ConstrainingTriangle, ConstrainingQuadrilateral>;
     772              : 
     773              : 
     774              : ////////////////////////////////////////////////////////////////////////////////
     775              : //      CONSTRAINING FACE
     776              : template <> size_t
     777            0 : ConstrainingFace::
     778              : num_constrained<Vertex>() const
     779              : {
     780            0 :         return num_constrained_vertices();
     781              : }
     782              : 
     783              : template <> size_t
     784            0 : ConstrainingFace::
     785              : num_constrained<Edge>() const
     786              : {
     787            0 :         return num_constrained_edges();
     788              : }
     789              : 
     790              : template <> size_t
     791            0 : ConstrainingFace::
     792              : num_constrained<Face>() const
     793              : {
     794            0 :         return num_constrained_faces();
     795              : }
     796              : 
     797              : 
     798              : template <> Vertex*
     799            0 : ConstrainingFace::
     800              : constrained<Vertex>(size_t ind) const
     801              : {
     802            0 :         return constrained_vertex(ind);
     803              : }
     804              : 
     805              : template <> Edge*
     806            0 : ConstrainingFace::
     807              : constrained<Edge>(size_t ind) const
     808              : {
     809            0 :         return constrained_edge(ind);
     810              : }
     811              : 
     812              : template <> Face*
     813            0 : ConstrainingFace::
     814              : constrained<Face>(size_t ind) const
     815              : {
     816            0 :         return constrained_face(ind);
     817              : }
     818              : 
     819              : }//     end of namespace
        

Generated by: LCOV version 2.0-1