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

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2009-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 <stack>
      35              : #include <cassert>
      36              : #include "vertex_util.h"
      37              : #include "face_util.h"
      38              : #include "../attachment_util.h"
      39              : 
      40              : using namespace std;
      41              : 
      42              : namespace ug
      43              : {
      44              : 
      45              : ////////////////////////////////////////////////////////////////////////
      46            0 : int GetFaceIndex(Volume* vol, Face* f)
      47              : {
      48            0 :         size_t numFaces = vol->num_faces();
      49            0 :         FaceDescriptor fd;
      50            0 :         for(uint i = 0; i < numFaces; ++i)
      51              :         {
      52            0 :                 vol->face_desc(i, fd);
      53            0 :                 if(CompareVertices(f, &fd))
      54            0 :                         return (int)i;
      55              :         }
      56              :         return -1;
      57              : }
      58              : 
      59              : 
      60              : ////////////////////////////////////////////////////////////////////////
      61              : //      CalculateNormal
      62            0 : void CalculateNormal(vector3& vNormOut, const FaceVertices* face,
      63              :                                         Grid::AttachmentAccessor<Vertex, APosition>& aaPos)
      64              : {
      65            0 :         if(face->num_vertices() == 3)
      66              :         {
      67            0 :                 CalculateTriangleNormal(vNormOut, aaPos[face->vertex(0)],
      68            0 :                                                                 aaPos[face->vertex(1)], aaPos[face->vertex(2)]);
      69            0 :                 return;
      70              :         }
      71            0 :         else if(face->num_vertices() == 4)
      72              :         {
      73              :                 vector3 n1, n2;
      74            0 :                 CalculateTriangleNormalNoNormalize(n1, aaPos[face->vertex(0)],
      75            0 :                                                                 aaPos[face->vertex(1)], aaPos[face->vertex(2)]);
      76            0 :                 CalculateTriangleNormalNoNormalize(n2, aaPos[face->vertex(2)],
      77            0 :                                                                 aaPos[face->vertex(3)], aaPos[face->vertex(0)]);
      78              :                 VecAdd(vNormOut, n1, n2);
      79            0 :                 VecNormalize(vNormOut, vNormOut);
      80              : 
      81              :                 return;
      82              :         }
      83            0 :         else if(face->num_vertices() > 4)
      84              :         {
      85            0 :                 CalculateTriangleNormal(vNormOut, aaPos[face->vertex(0)],
      86            0 :                                                                 aaPos[face->vertex(1)], aaPos[face->vertex(2)]);
      87            0 :                 return;
      88              :         }
      89              : 
      90              :         vNormOut = vector3(0, 0, 0);
      91            0 :         return;
      92              : }
      93              : 
      94            0 : void CalculateNormalNoNormalize(vector3& vNormOut, FaceVertices* face,
      95              :                                                                 Grid::AttachmentAccessor<Vertex, APosition>& aaPos)
      96              : {
      97            0 :         if(face->num_vertices() == 3)
      98              :         {
      99            0 :                 CalculateTriangleNormalNoNormalize(vNormOut, aaPos[face->vertex(0)],
     100            0 :                                                                 aaPos[face->vertex(1)], aaPos[face->vertex(2)]);
     101            0 :                 return;
     102              :         }
     103            0 :         else if(face->num_vertices() == 4)
     104              :         {
     105              :                 vector3 n1, n2;
     106            0 :                 CalculateTriangleNormalNoNormalize(n1, aaPos[face->vertex(0)],
     107            0 :                                                                 aaPos[face->vertex(1)], aaPos[face->vertex(2)]);
     108            0 :                 CalculateTriangleNormalNoNormalize(n2, aaPos[face->vertex(2)],
     109            0 :                                                                 aaPos[face->vertex(3)], aaPos[face->vertex(0)]);
     110              :                 VecAdd(vNormOut, n1, n2);
     111              :                 VecScale(vNormOut, vNormOut, 0.5);
     112              : 
     113              :                 return;
     114              :         }
     115            0 :         else if(face->num_vertices() > 4)
     116              :         {
     117            0 :                 CalculateTriangleNormalNoNormalize(vNormOut, aaPos[face->vertex(0)],
     118            0 :                                                                 aaPos[face->vertex(1)], aaPos[face->vertex(2)]);
     119            0 :                 return;
     120              :         }
     121              : 
     122              :         vNormOut = vector3(0, 0, 0);
     123            0 :         return;
     124              : }
     125              : 
     126              : ////////////////////////////////////////////////////////////////////////
     127              : //      CalculateFaceNormals
     128            0 : void CalculateFaceNormals(Grid& grid, const FaceIterator& facesBegin,
     129              :                                                 const FaceIterator& facesEnd,
     130              :                                                 AVector3& aPos, AVector3& aNorm)
     131              : {
     132            0 :         if(!grid.has_vertex_attachment(aPos))
     133            0 :                 return;
     134              : 
     135            0 :         if(!grid.has_face_attachment(aNorm))
     136            0 :                 grid.attach_to_faces(aNorm);
     137              : 
     138              :         Grid::VertexAttachmentAccessor<AVector3> aaPos(grid, aPos);
     139              :         Grid::FaceAttachmentAccessor<AVector3> aaNorm(grid, aNorm);
     140              : 
     141              : //      iterate through the specified faces and calculate normals.
     142            0 :         for(FaceIterator iter = facesBegin; iter != facesEnd; ++iter)
     143            0 :                 CalculateNormal(aaNorm[*iter], *iter, aaPos);
     144              : }
     145              : 
     146              : ////////////////////////////////////////////////////////////////////////
     147            0 : int NumAssociatedVolumes(Grid& grid, Face* f)
     148              : {
     149              : //      check if FACEOPT_STORE_ASSOCIATED_VOLUMES is enabled.
     150              : //      if so, use it to count the number of adjacent volumes.
     151              :         int counter = 0;
     152            0 :         if(grid.option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES))
     153              :         {
     154            0 :                 for(Grid::AssociatedVolumeIterator iter = grid.associated_volumes_begin(f);
     155            0 :                         iter != grid.associated_volumes_end(f); iter++)
     156              :                 {
     157            0 :                         ++counter;
     158              :                 }
     159              :         }
     160              :         else
     161              :         {
     162              :         //      iterate over all volumes which are connected to the first vertex
     163              :         //      and check if they contain the face...
     164            0 :                 Grid::AssociatedVolumeIterator iterEnd = grid.associated_volumes_end(f->vertex(0));
     165            0 :                 for(Grid::AssociatedVolumeIterator iter = grid.associated_volumes_begin(f->vertex(0));
     166            0 :                         iter != iterEnd; iter++)
     167              :                 {
     168            0 :                         if(VolumeContains(*iter, f))
     169            0 :                                 ++counter;
     170              :                 }
     171              :         }
     172              : 
     173            0 :         return counter;
     174              : }
     175              : 
     176              : ////////////////////////////////////////////////////////////////////////
     177            0 : bool IsVolumeBoundaryFace(Grid& grid, Face* f)
     178              : {
     179            0 :         return NumAssociatedVolumes(grid, f) == 1;
     180              : }
     181              : 
     182            0 : bool IsVolumeBoundaryFace(Grid& grid, ConstrainedFace* f)
     183              : {
     184            0 :         static vector<Volume*> vols;//avoid repeated reallocation
     185            0 :         CollectVolumes(vols, grid, f);
     186            0 :         if(vols.empty())
     187            0 :                 return true;
     188              :         return false;
     189              : }
     190              : 
     191            0 : bool IsVolumeBoundaryFace(Grid& grid, ConstrainingFace* f)
     192              : {
     193            0 :         static vector<Volume*> vols;//avoid repeated reallocation
     194            0 :         CollectVolumes(vols, grid, f);
     195            0 :         if(vols.empty())
     196            0 :                 return true;
     197              :         return false;
     198              : }
     199              : 
     200              : 
     201              : ////////////////////////////////////////////////////////////////////////
     202              : //      FaceQuality
     203            0 : number FaceQuality(FaceVertices* f,
     204              :                                 Grid::VertexAttachmentAccessor<APosition> aaPos)
     205              : {
     206              : //      take dot-products at the corners.
     207              :         number quality = 1;
     208            0 :         uint numVrts = f->num_vertices();
     209              : 
     210              :         vector3 v1, v2;
     211              :         number len1, len2;
     212              : 
     213              : //      calculate the direction from first to last vertex.
     214            0 :         VecSubtract(v1, aaPos[f->vertex(numVrts-1)], aaPos[f->vertex(0)]);
     215              :         len1 = VecLength(v1);
     216              : 
     217              :         //VecNormalize(v1, v1);
     218              : 
     219            0 :         for(uint i = 0; i < numVrts; ++i)
     220              :         {
     221            0 :                 VecSubtract(v2, aaPos[f->vertex((i+1)%numVrts)], aaPos[f->vertex(i)]);
     222              :                 len2 = VecLength(v2);
     223              :                 //VecNormalize(v2, v2);
     224              : 
     225            0 :                 number nQual = 1. - fabs(VecDot(v1, v2) / (len1 * len2));
     226            0 :                 if(nQual < quality)
     227              :                         quality = nQual;
     228              :         //      v1 of the next iteration equals -v2 of this iteration
     229              :                 VecScale(v1, v2, -1);
     230              :                 len1 = len2;
     231              :         }
     232              : 
     233            0 :         if(numVrts == 3){
     234              :         //      since at least one angle is <= 60, we have to normalize the return value
     235            0 :                 return quality * 2.;
     236              :         }
     237              :         return quality;
     238              : }
     239              : 
     240              : ////////////////////////////////////////////////////////////////////////
     241              : //      TriangleQuality
     242            0 : number TriangleQuality(vector3& v1, vector3& v2, vector3& v3)
     243              : {
     244              : //      take dot-products at the corners.
     245              :         number quality = 1;
     246              : 
     247              : //      required for the iteration.
     248              :         vector3* pv[3];
     249            0 :         pv[0] = &v1; pv[1] = &v2; pv[2] = &v3;
     250              : 
     251              :         vector3 d1, d2;
     252              : //      calculate the direction from first to last vertex.
     253              :         VecSubtract(d1, v3, v1);
     254            0 :         VecNormalize(d1, d1);
     255              : 
     256            0 :         for(uint i = 0; i < 3; ++i)
     257              :         {
     258            0 :                 VecSubtract(d2, *pv[i], *pv[(i+1)%3]);
     259            0 :                 VecNormalize(d2, d2);
     260            0 :                 number nQual = 1.f - fabs(VecDot(d1, d2));
     261            0 :                 if(nQual < quality)
     262              :                         quality = nQual;
     263              :         //      v1 of the next iteration equals -v2 of this iteration
     264              :                 VecScale(d1, d2, -1);
     265              :         }
     266              : 
     267              : //      since at least one angle is <= 60, we have to normalize the return value
     268            0 :         return quality * 2.;
     269              : }
     270              : 
     271              : ////////////////////////////////////////////////////////////////////////
     272              : //      Triangulate
     273            0 : void Triangulate(Grid& grid, Quadrilateral* q,
     274              :                                 Grid::VertexAttachmentAccessor<APosition>* paaPos)
     275              : {
     276              : //      there are two ways to triangulate a quadrilateral.
     277              : //      if quality is set to false, we simply choose the first way.
     278            0 :         if(!paaPos)
     279              :         {
     280            0 :                 grid.create<Triangle>(TriangleDescriptor(q->vertex(0), q->vertex(1), q->vertex(2)), q);
     281            0 :                 grid.create<Triangle>(TriangleDescriptor(q->vertex(2), q->vertex(3), q->vertex(0)), q);
     282              :         }
     283              :         else
     284              :         {
     285              :                 Grid::VertexAttachmentAccessor<APosition>& aaPos = *paaPos;
     286              : 
     287              :                 number q1 = 0;
     288              :                 number q2 = 0;
     289              : 
     290              :         //      first check whether normals in the corners should affect the direction of the edge
     291            0 :                 vector3 n[4];
     292            0 :                 for(int i = 0; i < 4; ++i)
     293            0 :                         CalculateVertexNormal(n[i], grid, q->vertex(i), aaPos);
     294              :                 
     295              :                 // vector3 dir[2];
     296              :                 // VecSubtract(dir[0], aaPos[q->vertex(2)], aaPos[q->vertex(0)]);
     297              :                 // VecNormalize(dir[0], dir[0]);
     298              :                 // VecSubtract(dir[1], aaPos[q->vertex(3)], aaPos[q->vertex(1)]);
     299              :                 // VecNormalize(dir[1], dir[1]);
     300              : 
     301              :                 // number maxDot[2] = {0, 0};
     302              :                 // for(int i = 0; i < 4; ++i){
     303              :                 //      for(int j = 0; j < 2; ++j){
     304              :                 //              maxDot[j] = std::max(maxDot[j], fabs(VecDot(dir[j], n[i])));
     305              :                 //      }
     306              :                 // }
     307              : 
     308              :                 // int imin = maxDot[0] < maxDot[1] ? 0 : 1;
     309              :                 // int imax = maxDot[0] < maxDot[1] ? 1 : 0;
     310              : 
     311              :                 // if(maxDot[imax] > 0 && maxDot[imax] - maxDot[imin] > SMALL){
     312              :                 //      q1 = 1. - maxDot[0];
     313              :                 //      q2 = 1. - maxDot[1];
     314              :                 // }
     315              : 
     316              :                 q1 = VecDot(n[0], n[2]);
     317              :                 q2 = VecDot(n[1], n[3]);
     318              :                 
     319            0 :                 if(fabs(q1-q2) < SMALL)
     320              :                 {
     321              :                 //      if normals are equal we check which way produces the better triangles.
     322            0 :                         q1 = std::min(
     323            0 :                                         TriangleQuality(aaPos[q->vertex(0)], aaPos[q->vertex(1)], aaPos[q->vertex(2)]),
     324            0 :                                         TriangleQuality(aaPos[q->vertex(2)], aaPos[q->vertex(3)], aaPos[q->vertex(0)]));
     325              : 
     326            0 :                         q2 = std::min(
     327            0 :                                         TriangleQuality(aaPos[q->vertex(1)], aaPos[q->vertex(2)], aaPos[q->vertex(3)]),
     328            0 :                                         TriangleQuality(aaPos[q->vertex(3)], aaPos[q->vertex(0)], aaPos[q->vertex(1)]));
     329              :                 }
     330              : 
     331            0 :                 if(q1 >= q2)
     332              :                 {
     333            0 :                         grid.create<Triangle>(TriangleDescriptor(q->vertex(0), q->vertex(1), q->vertex(2)), q);
     334            0 :                         grid.create<Triangle>(TriangleDescriptor(q->vertex(2), q->vertex(3), q->vertex(0)), q);
     335              :                 }
     336              :                 else
     337              :                 {
     338            0 :                         grid.create<Triangle>(TriangleDescriptor(q->vertex(1), q->vertex(2), q->vertex(3)), q);
     339            0 :                         grid.create<Triangle>(TriangleDescriptor(q->vertex(3), q->vertex(0), q->vertex(1)), q);
     340              :                 }
     341              :         }
     342              : 
     343            0 :         grid.erase(q);
     344            0 : }
     345              : 
     346              : ////////////////////////////////////////////////////////////////////////
     347              : //      Triangulate
     348            0 : void Triangulate(Grid& grid,
     349              :                                 QuadrilateralIterator iterBegin,
     350              :                                 QuadrilateralIterator iterEnd,
     351              :                                 Grid::VertexAttachmentAccessor<APosition>* paaPos)
     352              : {
     353            0 :         while(iterBegin != iterEnd)
     354              :         {
     355              :                 Quadrilateral* q = *iterBegin;
     356              :                 iterBegin++;
     357            0 :                 Triangulate(grid, q, paaPos);
     358              :         }
     359            0 : }
     360              : 
     361              : ////////////////////////////////////////////////////////////////////////
     362              : //      GetNeighbours
     363            0 : void GetNeighbours(std::vector<Face*>& vFacesOut, Grid& grid, Face* f,
     364              :                                         int side, bool clearContainer)
     365              : {
     366              : //      in the current implementation this method requires, that all edges
     367              : //      are created for all faces.
     368              : //TODO: improve this!
     369            0 :         if(!grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES))
     370              :         {
     371              :                 LOG("WARNING: autoenabling FACEOPT_AUTOGENERATE_EDGES in GetNeighbours(Face).\n");
     372            0 :                 grid.enable_options(FACEOPT_AUTOGENERATE_EDGES);
     373              :         }
     374              :         
     375            0 :         if(clearContainer)
     376              :                 vFacesOut.clear();
     377              :                 
     378              : //      check if we can find an edge for the specified side
     379            0 :         Edge* e = grid.get_edge(f, side);
     380              :         assert(e && "edge not found though it should be there!");
     381              : 
     382              : //      get the connected faces
     383              :         vector<Face*> vFaces;
     384            0 :         CollectFaces(vFaces, grid, e);
     385              :         
     386              : //      push them to vFacesOut - except f
     387            0 :         for(size_t i = 0; i < vFaces.size(); ++i)
     388              :         {
     389            0 :                 if(vFaces[i] != f)
     390            0 :                         vFacesOut.push_back(vFaces[i]);
     391              :         }
     392            0 : }
     393              : 
     394            0 : void InsertCenterVertex(Grid& g, Face* f, Vertex* vrt, bool eraseOldFace)
     395              : {
     396              : //      get the sides of the face and create new elements
     397            0 :         EdgeDescriptor ed;
     398            0 :         for(size_t i = 0; i < f->num_edges(); ++i){
     399            0 :                 f->edge_desc(i, ed);
     400            0 :                 g.create<Triangle>(TriangleDescriptor(ed.vertex(0), ed.vertex(1), vrt), f);
     401              :         }
     402              : 
     403            0 :         if(eraseOldFace)
     404            0 :                 g.erase(f);
     405            0 : }
     406              : 
     407              : }//     end of namespace
        

Generated by: LCOV version 2.0-1