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

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 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 <algorithm>
      34              : #include <vector>
      35              : #include "horizontal_layers_mesher.h"
      36              : #include "lib_grid/callbacks/callbacks.h"
      37              : #include "lib_grid/algorithms/extrusion/extrude.h"
      38              : #include "lib_grid/algorithms/geom_obj_util/face_util.h"
      39              : #include "lib_grid/algorithms/geom_obj_util/vertex_util.h"
      40              : #include "lib_grid/file_io/file_io_asc.h"
      41              : #include "lib_grid/iterators/associated_elements_iterator.h"
      42              : #include "lib_grid/iterators/lg_for_each.h"
      43              : 
      44              : using namespace std;
      45              : 
      46              : namespace ug{
      47              : 
      48              : ////////////////////////////////////////////////////////////////////////////////
      49            0 : void MeshLayerBoundaries(Grid& grid, const RasterLayers& layers,
      50              :                                                  Grid::VertexAttachmentAccessor<AVector3> aaPos,
      51              :                                                  ISubsetHandler* pSH)
      52              : {
      53              :         int defSubInd = -1;
      54            0 :         if(pSH)
      55              :                 defSubInd = pSH->get_default_subset_index();
      56              : 
      57            0 :         for(size_t lvl = 0; lvl < layers.size(); ++lvl){
      58            0 :                 if(pSH)
      59            0 :                         pSH->set_default_subset_index((int)lvl);
      60            0 :                 CreateGridFromFieldBoundary(grid, layers.heightfield(lvl), aaPos);
      61              :         }
      62              : 
      63            0 :         if(pSH)
      64            0 :                 pSH->set_default_subset_index(defSubInd);
      65            0 : }
      66              : 
      67              : ////////////////////////////////////////////////////////////////////////////////
      68            0 : void MeshLayers(Grid& grid, const RasterLayers& layers,
      69              :                                 Grid::VertexAttachmentAccessor<AVector3> aaPos,
      70              :                                 ISubsetHandler* pSH)
      71              : {
      72              :         int defSubInd = -1;
      73            0 :         if(pSH)
      74              :                 defSubInd = pSH->get_default_subset_index();
      75              : 
      76            0 :         for(size_t lvl = 0; lvl < layers.size(); ++lvl){
      77            0 :                 if(pSH)
      78            0 :                         pSH->set_default_subset_index((int)lvl);
      79            0 :                 CreateGridFromField(grid, layers.heightfield(lvl), aaPos);
      80              :         }
      81              : 
      82            0 :         if(pSH)
      83            0 :                 pSH->set_default_subset_index(defSubInd);
      84            0 : }
      85              : 
      86              : 
      87              : ////////////////////////////////////////////////////////////////////////////////
      88              : ////////////////////////////////////////////////////////////////////////////////
      89              : //      EXTRUDE LAYERS
      90              : struct ConnectedToOneMarkedVrt{
      91              :         ConnectedToOneMarkedVrt(Grid& grid) : m_grid(grid) {}
      92            0 :         bool operator() (Edge* e) const{
      93            0 :                 return  (m_grid.is_marked(e->vertex(0)) || m_grid.is_marked(e->vertex(1)))
      94            0 :                         && !(m_grid.is_marked(e->vertex(0)) && m_grid.is_marked(e->vertex(1)));
      95              :         }
      96              :         Grid& m_grid;
      97              : };
      98              : 
      99            0 : void ExtrudeLayers (
     100              :                 Grid& grid, 
     101              :                 const RasterLayers& layers,
     102              :                 Grid::VertexAttachmentAccessor<AVector3> aaPos,
     103              :                 ISubsetHandler& sh,
     104              :                 bool allowForTetsAndPyras,
     105              :                 const ANumber* aRelZOut)
     106              : {
     107            0 :         if(allowForTetsAndPyras){
     108            0 :                 ExtrudeLayersMixed(grid, layers, aaPos, sh, aRelZOut);
     109            0 :                 return;
     110              :         }
     111              : 
     112            0 :         UG_COND_THROW(layers.size() < 2, "At least 2 layers are required to perform extrusion!");
     113              : 
     114            0 :         grid.begin_marking();
     115              : 
     116              :         vector<Vertex*> curVrts;  // list of vertices that are considered for extrusion
     117              :         vector<Vertex*> tmpVrts;  // used to determine the set of vertices that can be extruded
     118              :         vector<Vertex*> smoothVrts;
     119              :         vector<Face*> curFaces;           // list of faces that are considered for extrusion
     120              :         vector<Face*> tmpFaces;           // used to determine the set of faces that can be extruded
     121              :         vector<number> vrtHeightVals;     // here we'll record height-values at which new vertices will be placed
     122              :         vector<number> volHeightVals;     // here we'll record height-values at the center of new volumes
     123              :         vector<number> curUpperLayerHeight;
     124              :         vector<int> volSubsetInds;
     125              :         vector<Volume*> newVols;
     126              :         queue<Volume*> volCandidates;
     127              : 
     128              :         Grid::edge_traits::callback cbIsMarked = IsMarked(grid);
     129              :         Grid::edge_traits::callback cbConnectedToOneMarkedVrt = ConnectedToOneMarkedVrt(grid);
     130            0 :         AssocElemIter<Vertex, Edge> assocVrtEdgeIterMarkedEdge(cbIsMarked);
     131            0 :         AssocElemIter<Vertex, Edge> assocVrtEdgeIterOneMarked(cbConnectedToOneMarkedVrt);
     132            0 :         AssocElemIter<Face, Edge> assocFaceEdgeIter;
     133            0 :         AssocElemIter<Volume, Edge> assocVolEdgeIter(cbConnectedToOneMarkedVrt);
     134              :         
     135            0 :         grid.reserve<Vertex>(grid.num_vertices() * layers.size());
     136            0 :         grid.reserve<Volume>(grid.num_faces() * layers.size() - 1);
     137              : 
     138              : //      todo: this accessor is primarily used during smoothing. Maybe it can be removed?
     139              :         ANumber aHeight;
     140              :         grid.attach_to_vertices(aHeight);
     141              :         Grid::VertexAttachmentAccessor<ANumber> aaHeight(grid, aHeight);
     142              : 
     143              :         Grid::VertexAttachmentAccessor<ANumber> aaRelZOut;
     144            0 :         if(aRelZOut){
     145              :                 ANumber aRelZ = *aRelZOut;
     146            0 :                 if(!grid.has_vertex_attachment(aRelZ))
     147              :                         grid.attach_to_vertices(aRelZ);
     148              :                 aaRelZOut.access(grid, aRelZ);
     149              :         }
     150              : 
     151              : //      we have to determine the vertices that can be projected onto the top of the
     152              : //      given layers-stack. Only those will be used during extrusion
     153              : //      all considered vertices will be marked.
     154              :         const RasterLayers::layer_t& top = layers.top();
     155            0 :         const int topLayerInd = (int)layers.num_layers() - 1;
     156            0 :         for(VertexIterator i = grid.begin<Vertex>(); i != grid.end<Vertex>(); ++i){
     157            0 :                 Vertex* v = *i;
     158            0 :                 vector2 c(aaPos[v].x(), aaPos[v].y());
     159              :                 // number val = top.heightfield.interpolate(c);
     160            0 :                 number val = layers.relative_to_global_height(c, topLayerInd);
     161            0 :                 if(val != top.heightfield.no_data_value()){
     162            0 :                         aaPos[v].z() = val;
     163            0 :                         curVrts.push_back(v);
     164            0 :                         curUpperLayerHeight.push_back(val);
     165              :                         grid.mark(v);
     166            0 :                         sh.assign_subset(v, topLayerInd);
     167              :                 }
     168              :         }
     169              : 
     170            0 :         if(curVrts.size() < 3){
     171              :                 UG_LOG("Not enough vertices lie in the region of the surface layer\n");
     172              :                 return;
     173              :         }
     174              : 
     175            0 :         if(aaRelZOut.valid()){
     176            0 :                 for(size_t ivrt = 0; ivrt < curVrts.size(); ++ivrt)
     177            0 :                         aaRelZOut[curVrts[ivrt]] = topLayerInd;
     178              :         }
     179              : 
     180              : //      all faces of the initial triangulation that are only connected to marked
     181              : //      vertices are considered for extrusion
     182            0 :         for(FaceIterator fi = grid.begin<Face>(); fi != grid.end<Face>(); ++fi){
     183            0 :                 Face* f = *fi;
     184              :                 bool allMarked = true;
     185            0 :                 Face::ConstVertexArray vrts = f->vertices();
     186            0 :                 const size_t numVrts = f->num_vertices();
     187            0 :                 for(size_t i = 0; i < numVrts; ++i){
     188            0 :                         if(!grid.is_marked(vrts[i])){
     189              :                                 allMarked = false;
     190              :                                 break;
     191              :                         }
     192              :                 }
     193            0 :                 if(allMarked)
     194            0 :                         curFaces.push_back(f);
     195              :         }
     196              : 
     197            0 :         if(curFaces.empty()){
     198              :                 UG_LOG("Not enough faces lie in the region of the surface layer\n");
     199              :                 return;
     200              :         }
     201              : 
     202              : 
     203            0 :         tmpVrts.reserve(curVrts.size());
     204            0 :         smoothVrts.reserve(curVrts.size());
     205            0 :         curUpperLayerHeight.reserve(curVrts.size());
     206            0 :         tmpFaces.reserve(curFaces.size());
     207            0 :         newVols.reserve(curFaces.size());
     208            0 :         volHeightVals.reserve(curFaces.size());
     209            0 :         volSubsetInds.reserve(curFaces.size());
     210            0 :         const int invalidSub = max<int>(sh.num_subsets(), layers.size() + 1);
     211              :         vector<Volume*> invalidVols;
     212              : 
     213            0 :         for(int ilayer = (int)layers.size() - 2; ilayer >= 0; --ilayer){
     214              : 
     215              :                 tmpVrts.clear();
     216              :                 vrtHeightVals.clear();
     217              :                 tmpFaces.clear();
     218              :                 newVols.clear();
     219              :                 volHeightVals.clear();
     220              :                 volSubsetInds.clear();
     221            0 :                 grid.clear_marks();
     222              :         //      trace rays from the current vertices down through the layers until the
     223              :         //      next valid entry is found. If none is found, the vertex will either be ignored
     224              :         //      from then on (allowForTetsAndPyras == false) or a dummy vertex will be inserted.
     225            0 :                 for(size_t icur = 0; icur < curVrts.size(); ++icur){
     226            0 :                         Vertex* v = curVrts[icur];
     227            0 :                         vector2 c(aaPos[v].x(), aaPos[v].y());
     228            0 :                         number upperVal = curUpperLayerHeight[icur];
     229            0 :                         number height = layers.relative_to_global_height(c, (number) ilayer);
     230              : 
     231              :                         // bool searching = true;
     232              :                         int curLayer = ilayer;
     233              : 
     234              :                         // while(searching && curLayer >= 0){
     235              :                                 // searching = false;
     236            0 :                                 pair<int, number> val = layers.trace_line_down(c, curLayer);
     237              :                                 number lowerVal = 0;
     238            0 :                                 if(val.first >= 0)
     239            0 :                                         lowerVal = layers.relative_to_global_height(c, (number) val.first);
     240              : 
     241              :                                 // if(curLayer == 0 && val.first >= 0
     242              :                                 //      && upperVal - lowerVal < layers.min_height(curLayer))
     243              :                                 // {
     244              :                                 //      val.first = -1;
     245              :                                 // }
     246              :                                 
     247            0 :                                 if(val.first >= 0){
     248              :                                         // if(upperVal - lowerVal < layers.min_height(curLayer)){
     249              :                                         //      searching = true;
     250              :                                         //      --curLayer;
     251              :                                         //      continue;
     252              :                                         // }
     253              :                                 //      if val.first == curLayer height will equal lowerVal. If not,
     254              :                                 //      a linear interpolation is performed, considering the height-val
     255              :                                 //      of the current vertex, the layer distance and the target value.
     256            0 :                                         tmpVrts.push_back(v);
     257            0 :                                         vrtHeightVals.push_back(height);
     258            0 :                                         aaHeight[v] = upperVal - lowerVal;//total height of curLayer
     259            0 :                                         sh.assign_subset(v, val.first);
     260              :                                         grid.mark(v);
     261            0 :                                         if(val.first == ilayer){
     262              :                                                 // UG_LOG("DBG: setting upper value: " << lowerVal << "(old: " << upperVal << ")\n");
     263            0 :                                                 curUpperLayerHeight[icur] = lowerVal;
     264              :                                         }
     265              :                                 }
     266              :                                 else if(allowForTetsAndPyras){
     267              :                                 //      we insert a dummy-vertex which will later on allow for easier
     268              :                                 //      edge-collapses of inner vertical rim edges
     269              :                                         tmpVrts.push_back(v);
     270              :                                         vrtHeightVals.push_back(height);
     271              :                                         aaHeight[v] = upperVal - val.second;//total height of ilayer
     272              :                                         sh.assign_subset(v, invalidSub);
     273              :                                         grid.mark(v);
     274              :                                 }
     275              :                         // }
     276              :                 }
     277              :         //      now find the faces which connect those vertices
     278            0 :                 for(size_t iface = 0; iface < curFaces.size(); ++iface){
     279            0 :                         Face* f = curFaces[iface];
     280              : 
     281            0 :                         vector3 center = CalculateCenter(f, aaPos);
     282            0 :                         vector2 c(center.x(), center.y());
     283            0 :                         pair<int, number> val = layers.trace_line_down(c, ilayer);
     284            0 :                         if((val.first < 0) && !allowForTetsAndPyras)
     285            0 :                                 continue;
     286              : 
     287              :                 //      now check whether all vertices are marked
     288              :                         bool allMarked = true;
     289            0 :                         Face::ConstVertexArray vrts = f->vertices();
     290            0 :                         size_t numVrts = f->num_vertices();
     291            0 :                         for(size_t i = 0; i < numVrts; ++i){
     292            0 :                                 if(!grid.is_marked(vrts[i])){
     293              :                                         allMarked = false;
     294              :                                         break;
     295              :                                 }
     296              :                         }
     297              : 
     298            0 :                         if(allMarked){
     299            0 :                                 int subsetIndex = invalidSub;
     300              : 
     301              :                                 // if(val.first >= 0) {
     302              :                                 // //   subset from center trace down
     303              :                                 //      subsetIndex = val.first;
     304              :                                 // }
     305              :                                 // else {
     306              :                                 //      the highest valid side of the volume determines its subset.
     307              :                                         number maxHeight = 0;
     308            0 :                                         for(size_t i = 0; i < numVrts; ++i){
     309            0 :                                                 int si = sh.get_subset_index(vrts[i]);
     310            0 :                                                 if(si == invalidSub)
     311            0 :                                                         continue;
     312              : 
     313            0 :                                                 number vh = aaHeight[vrts[i]];
     314            0 :                                                 if(vh > maxHeight){
     315              :                                                         maxHeight = vh;
     316            0 :                                                         subsetIndex = si;
     317              :                                                 }
     318              :                                         }
     319              :                                 // }
     320              : 
     321              : 
     322              : 
     323            0 :                                 pair<int, number> upVal = layers.trace_line_up(c, ilayer+1);
     324            0 :                                 if(val.first < 0 || upVal.first < 0){
     325              :                                         if(allowForTetsAndPyras){
     326              :                                                 tmpFaces.push_back(f);
     327              :                                                 // volSubsetInds.push_back(invalidSub);
     328              :                                                 volSubsetInds.push_back(subsetIndex);
     329              :                                                 volHeightVals.push_back(layers.min_height(ilayer));
     330              :                                         }
     331              :                                 }
     332              :                                 else{
     333            0 :                                         tmpFaces.push_back(f);
     334              :                                         // volSubsetInds.push_back(val.first);
     335            0 :                                         volSubsetInds.push_back(subsetIndex);
     336            0 :                                         volHeightVals.push_back(upVal.second - val.second);
     337              :                                 }
     338              :                         }
     339              :                 }
     340              : 
     341            0 :                 if(tmpFaces.empty())
     342              :                         break;
     343              : 
     344              :         //      swap containers and perform extrusion
     345              :                 curVrts.swap(tmpVrts);
     346              :                 curFaces.swap(tmpFaces);
     347            0 :                 Extrude(grid, &curVrts, NULL, &curFaces, vector3(0, 0, 0), aaPos,
     348              :                                 EO_DEFAULT, &newVols);
     349              : 
     350              :         // assign pre-determined subsets
     351            0 :                 for(size_t ivol = 0; ivol < newVols.size(); ++ivol){
     352            0 :                         sh.assign_subset(newVols[ivol], volSubsetInds[ivol]);
     353            0 :                         if(volSubsetInds[ivol] == invalidSub)
     354            0 :                                 invalidVols.push_back(newVols[ivol]);
     355              :                 }
     356              : 
     357              :         //      set the precalculated height of new vertices
     358            0 :                 for(size_t ivrt = 0; ivrt < curVrts.size(); ++ivrt){
     359            0 :                         aaPos[curVrts[ivrt]].z() = vrtHeightVals[ivrt];
     360              :                 }
     361              : 
     362            0 :                 if(aaRelZOut.valid()){
     363            0 :                         for(size_t ivrt = 0; ivrt < curVrts.size(); ++ivrt)
     364            0 :                                 aaRelZOut[curVrts[ivrt]] = ilayer;
     365              :                 }
     366              :         }
     367              :         
     368              : //      remove unnecessary prisms through edge-collapses and thus introduce pyramids and tetrahedra
     369              :         if(allowForTetsAndPyras){
     370              :                 ABool aInterface;
     371              :                 grid.attach_to_vertices_dv(aInterface, false, true);
     372              :                 Grid::VertexAttachmentAccessor<ABool> aaInterface(grid, aInterface);
     373              : 
     374              :                 Grid::volume_traits::secure_container   assVols;
     375              : 
     376              :         //      all triangle-interface-elements shall store 'true' in aaIsInterface
     377              :                 lg_for_each(Face, f, grid){
     378              :                         if(f->num_vertices() != 3)
     379              :                                 continue;
     380              : 
     381              :                         grid.associated_elements(assVols, f);
     382              :                         if(assVols.size() == 1){
     383              :                                 lg_for_each_vertex_in_elem(vrt, f){
     384              :                                         aaInterface[vrt] = true;
     385              :                                 }lg_end_for;
     386              :                         }
     387              :                         else{
     388              :                                 int si = -1;
     389              :                                 for_each_in_vec(Volume* v, assVols){
     390              :                                         if(si == -1)
     391              :                                                 si = sh.get_subset_index(v);
     392              :                                         else if(sh.get_subset_index(v) != si){
     393              :                                                 lg_for_each_vertex_in_elem(vrt, f){
     394              :                                                         aaInterface[vrt] = true;
     395              :                                                 }lg_end_for;
     396              :                                                 break;
     397              :                                         }
     398              :                                 }end_for;
     399              :                         }
     400              :                 }lg_end_for;
     401              : 
     402              :         //      all lower vertices of elements in invalidSub are collapse candidates and
     403              :         //      are thus not considered to be interface elements
     404              :                 Grid::edge_traits::secure_container assEdges;
     405              :                 for_each_in_vec(Volume* vol, invalidVols){
     406              :                         grid.associated_elements(assEdges, vol);
     407              :                         for_each_in_vec(Edge* e, assEdges){
     408              :                                 Vertex* v0 = e->vertex(0);
     409              :                                 Vertex* v1 = e->vertex(1);
     410              : 
     411              :                                 vector3 dir;
     412              :                                 VecSubtract(dir, aaPos[v1], aaPos[v0]);
     413              :                                 if((dir.z() > SMALL) && (fabs(dir.x()) < SMALL) && (fabs(dir.y()) < SMALL)){
     414              :                                         aaInterface[v0] = false;
     415              :                                 }
     416              :                                 else if((-dir.z() > SMALL) && (fabs(dir.x()) < SMALL) && (fabs(dir.y()) < SMALL)){
     417              :                                         aaInterface[v1] = false;
     418              :                                 }
     419              :                         }end_for;
     420              :                 }end_for;
     421              : 
     422              :         //      all unmarked vertices are collapse candidates
     423              :                 vector<Vertex*> candidates;
     424              :                 lg_for_each(Vertex, vrt, grid){
     425              :                         if(!aaInterface[vrt])
     426              :                                 candidates.push_back(vrt);
     427              :                 }lg_end_for;
     428              : 
     429              :         //      merge each candidate with the next upper vertex.
     430              :                 for_each_in_vec(Vertex* vrt, candidates){
     431              :                         grid.associated_elements(assEdges, vrt);
     432              :                         for_each_in_vec(Edge* e, assEdges){
     433              :                                 Vertex* cv = GetConnectedVertex(e, vrt);
     434              :                                 if(cv == vrt)
     435              :                                         continue;
     436              : 
     437              :                                 vector3 dir;
     438              :                                 VecSubtract(dir, aaPos[cv], aaPos[vrt]);
     439              :                                 if((dir.z() > SMALL) && (fabs(dir.x()) < SMALL) && (fabs(dir.y()) < SMALL)){
     440              :                                         CollapseEdge(grid, e, cv);
     441              :                                         break;
     442              :                                 }
     443              :                         }end_for;
     444              :                 }end_for;
     445              : 
     446              :         //      clean up
     447              :                 grid.detach_from_vertices(aInterface);
     448              : 
     449              :         //      delete invalidSub from the subset handler
     450              :                 if(invalidSub < sh.num_subsets())
     451              :                         sh.erase_subset(invalidSub);
     452              :         }
     453            0 :         grid.end_marking();
     454              :         grid.detach_from_vertices(aHeight);
     455            0 : }
     456              : 
     457              : 
     458            0 : void ExtrudeLayersMixed (
     459              :                 Grid& grid, 
     460              :                 const RasterLayers& layers,
     461              :                 Grid::VertexAttachmentAccessor<AVector3> aaPos,
     462              :                 ISubsetHandler& sh,
     463              :                 const ANumber* aRelZOut)
     464              : {
     465            0 :         UG_COND_THROW(layers.size() < 2, "At least 2 layers are required to perform extrusion!");
     466              : 
     467              :         vector<Vertex*> curVrts;  // list of vertices that are considered for extrusion
     468              :         vector<Vertex*> nextVrts; // used to determine the set of vertices that can be extruded
     469              :         vector<Face*> curFaces;           // list of faces that are considered for extrusion
     470              :         vector<Face*> nextFaces;          // used to determine the set of faces that can be extruded
     471              : 
     472            0 :         grid.reserve<Vertex>(grid.num_vertices() * layers.size());
     473            0 :         grid.reserve<Volume>(grid.num_faces() * layers.size() - 1);
     474              :         
     475              :         AInt aVrtInd;
     476              :         grid.attach_to_vertices(aVrtInd);
     477              :         Grid::VertexAttachmentAccessor<AInt> aaVrtInd(grid, aVrtInd);
     478              : 
     479              :         Grid::VertexAttachmentAccessor<ANumber> aaRelZOut;
     480            0 :         if(aRelZOut){
     481              :                 ANumber aRelZ = *aRelZOut;
     482            0 :                 if(!grid.has_vertex_attachment(aRelZ))
     483              :                         grid.attach_to_vertices(aRelZ);
     484              :                 aaRelZOut.access(grid, aRelZ);
     485              :         }
     486              : 
     487              : //      we have to determine the vertices that can be projected onto the top of the
     488              : //      given layers-stack. Only those will be used during extrusion
     489              : //      all considered vertices will be marked.
     490              :         const RasterLayers::layer_t& top = layers.top();
     491            0 :         const int topLayerInd = (int)layers.num_layers() - 1;
     492            0 :         for(VertexIterator i = grid.begin<Vertex>(); i != grid.end<Vertex>(); ++i){
     493            0 :                 Vertex* v = *i;
     494            0 :                 vector2 c(aaPos[v].x(), aaPos[v].y());
     495              :                 // number val = layers.relative_to_global_height(c, topLayerInd);
     496            0 :                 number val = layers.heightfield(topLayerInd).interpolate(c, 1);
     497            0 :                 if(val != top.heightfield.no_data_value()){
     498            0 :                         aaPos[v].z() = val;
     499            0 :                         aaVrtInd[v] = (int)curVrts.size();
     500            0 :                         curVrts.push_back(v);
     501            0 :                         sh.assign_subset(v, topLayerInd);
     502              :                 }
     503              :                 else
     504            0 :                         aaVrtInd[v] = -1;
     505              :         }
     506              : 
     507            0 :         if(curVrts.size() < 3){
     508              :                 UG_LOG("Not enough vertices lie in the region of the surface layer\n");
     509              :                 return;
     510              :         }
     511              : 
     512            0 :         if(aaRelZOut.valid()){
     513            0 :                 for(size_t ivrt = 0; ivrt < curVrts.size(); ++ivrt)
     514            0 :                         aaRelZOut[curVrts[ivrt]] = topLayerInd;
     515              :         }
     516              : 
     517              : //      make sure that only triangles are used
     518            0 :         if(grid.num<Quadrilateral>() > 0){
     519              :                 UG_LOG("WARNING: Converting all quadrilaterals to triangles\n");
     520            0 :                 Triangulate(grid, grid.begin<Quadrilateral>(), grid.end<Quadrilateral>(), &aaPos);
     521              :         }
     522              : 
     523              : //      all faces of the initial triangulation that are only connected to marked
     524              : //      vertices are considered for extrusion
     525            0 :         for(FaceIterator fi = grid.begin<Face>(); fi != grid.end<Face>(); ++fi){
     526            0 :                 Face* f = *fi;
     527              :                 bool allConsidered = true;
     528            0 :                 Face::ConstVertexArray vrts = f->vertices();
     529            0 :                 const size_t numVrts = f->num_vertices();
     530            0 :                 for(size_t i = 0; i < numVrts; ++i){
     531            0 :                         if(aaVrtInd[vrts[i]] == -1){
     532              :                                 allConsidered = false;
     533              :                                 break;
     534              :                         }
     535              :                 }
     536            0 :                 if(allConsidered)
     537            0 :                         curFaces.push_back(f);
     538              :         }
     539              : 
     540            0 :         if(curFaces.empty()){
     541              :                 UG_LOG("Not enough faces lie in the region of the surface layer\n");
     542              :                 return;
     543              :         }
     544              : 
     545              : 
     546            0 :         nextVrts.reserve(curVrts.size());
     547            0 :         nextFaces.reserve(curFaces.size());
     548              : 
     549              :         
     550            0 :         for(int ilayer = (int)layers.size() - 1; ilayer > 0; --ilayer){
     551              : 
     552              :                 nextVrts.clear();
     553              :                 nextFaces.clear();
     554              : 
     555            0 :                 const int nextLayer = ilayer - 1;
     556              : 
     557              :         //      trace rays from the current vertices down through the layers until the
     558              :         //      next valid entry is found. If none is found, the vertex will either be ignored
     559              :         //      from then on (allowForTetsAndPyras == false) or a dummy vertex will be inserted.
     560            0 :                 for(size_t icur = 0; icur < curVrts.size(); ++icur){
     561            0 :                         Vertex* v = curVrts[icur];
     562            0 :                         vector2 c(aaPos[v].x(), aaPos[v].y());
     563            0 :                         number curH = aaPos[v].z();
     564              :                         // number nextH = layers.relative_to_global_height(c, (number) nextLayer);
     565            0 :                         number nextH = layers.heightfield(nextLayer).interpolate(c, 1);
     566            0 :                         if(curH - nextH < layers.min_height(nextLayer)){
     567            0 :                                 nextVrts.push_back(v);
     568              :                         }
     569              :                         else{
     570            0 :                                 Vertex* nextVrt = *grid.create<RegularVertex>(v);
     571            0 :                                 aaVrtInd[nextVrt] = aaVrtInd[v];
     572              :                                 aaPos[nextVrt] = aaPos[v];
     573            0 :                                 aaPos[nextVrt].z() = nextH;
     574            0 :                                 sh.assign_subset(nextVrt, nextLayer);
     575            0 :                                 nextVrts.push_back(nextVrt);
     576              : 
     577            0 :                                 if(aaRelZOut.valid()){
     578            0 :                                         aaRelZOut[nextVrt] = nextLayer;
     579              :                                 }
     580              :                         }
     581              :                 }
     582              : 
     583              :         //      now find the faces which connect those vertices
     584            0 :                 for(size_t iface = 0; iface < curFaces.size(); ++iface){
     585            0 :                         Face* f = curFaces[iface];
     586            0 :                         Face::ConstVertexArray vrts = f->vertices();
     587              :                         int numNew = 0;
     588              :                         int firstSame = -1;
     589              :                         int firstNew = -1;
     590              :                         TriangleDescriptor nextTriDesc;
     591            0 :                         for(int i = 0; i < 3; ++i){
     592            0 :                                 int vrtInd = aaVrtInd[vrts[i]];
     593            0 :                                 nextTriDesc.set_vertex(i, nextVrts[vrtInd]);
     594            0 :                                 if(nextVrts[vrtInd] == curVrts[vrtInd]){
     595            0 :                                         if(firstSame == -1)
     596              :                                                 firstSame = i;
     597              :                                 }
     598              :                                 else{
     599            0 :                                         ++numNew;
     600            0 :                                         if(firstNew == -1)
     601              :                                                 firstNew = i;
     602              :                                 }
     603              :                         }
     604              : 
     605            0 :                         Face* nextFace = f;
     606            0 :                         if(numNew > 0){
     607            0 :                                 nextFace = *grid.create<Triangle>(nextTriDesc, f);
     608            0 :                                 sh.assign_subset (nextFace, nextLayer);
     609              :                         }
     610            0 :                         nextFaces.push_back(nextFace);
     611              : 
     612              :                         Volume* newVol = NULL;
     613              : 
     614            0 :                         switch(numNew){
     615              :                                 case 0:// no new volume to be built.
     616              :                                         break;
     617            0 :                                 case 1: {// build a tetrahedron
     618              :                                         TetrahedronDescriptor   tetDesc (nextTriDesc.vertex(0),
     619              :                                                                          nextTriDesc.vertex(1),
     620              :                                                                                                          nextTriDesc.vertex(2),
     621            0 :                                                                                                          vrts[firstNew]);
     622            0 :                                         newVol = *grid.create<Tetrahedron>(tetDesc);
     623            0 :                                 } break;
     624              : 
     625            0 :                                 case 2: {// build a pyramid
     626            0 :                                         int i0 = (firstSame + 1) % 3;
     627            0 :                                         int i1 = (firstSame + 2) % 3;
     628              :                                         PyramidDescriptor       pyrDesc (nextTriDesc.vertex(i0),
     629              :                                                                      nextTriDesc.vertex(i1),
     630            0 :                                                                      vrts[i1],
     631            0 :                                                                      vrts[i0],
     632            0 :                                                                      vrts[firstSame]);
     633            0 :                                         newVol = *grid.create<Pyramid>(pyrDesc);
     634            0 :                                 } break;
     635              : 
     636            0 :                                 case 3: {// build a prism
     637              :                                         PrismDescriptor         prismDesc (nextTriDesc.vertex(0),
     638              :                                                                                                    nextTriDesc.vertex(1),
     639              :                                                                                                    nextTriDesc.vertex(2),
     640              :                                                                                                    vrts[0],
     641              :                                                                                                    vrts[1],
     642            0 :                                                                                                    vrts[2]);
     643            0 :                                         newVol = *grid.create<Prism>(prismDesc);
     644            0 :                                 } break;
     645              :                         }
     646              : 
     647            0 :                         if(newVol)
     648            0 :                                 sh.assign_subset(newVol, nextLayer);
     649              :                 }
     650              : 
     651              :         //      swap containers and perform extrusion
     652              :                 curVrts.swap(nextVrts);
     653              :                 curFaces.swap(nextFaces);
     654              :         }
     655              :         
     656              : //      clean up
     657              :         grid.detach_from_vertices(aVrtInd);
     658            0 : }
     659              : 
     660              : ///     projects the given (surface-) grid to the specified raster
     661            0 : void ProjectToLayer(
     662              :                 Grid& grid,
     663              :                 const RasterLayers& layers,
     664              :                 int layerIndex,
     665              :                 Grid::VertexAttachmentAccessor<AVector3> aaPos)
     666              : {
     667            0 :         UG_COND_THROW(layerIndex < 0 || layerIndex >= (int)layers.size(),
     668              :                                   "Bad layerIndex in ProjectToLayer");
     669              : 
     670            0 :         const RasterLayers::layer_t& layer = layers.layer(layerIndex);
     671            0 :         for(VertexIterator i = grid.begin<Vertex>(); i != grid.end<Vertex>(); ++i){
     672              :                 Vertex* v = *i;
     673            0 :                 vector2 c(aaPos[v].x(), aaPos[v].y());
     674            0 :                 number val = layers.relative_to_global_height(c, layerIndex);
     675              : 
     676            0 :                 if(val != layer.heightfield.no_data_value()){
     677            0 :                         aaPos[v].z() = val;
     678              :                 }
     679              :         }
     680            0 : }
     681              : 
     682              : 
     683            0 : void SnapToHorizontalRaster(
     684              :                 Grid& grid,
     685              :                 const RasterLayers& layers,
     686              :                 Grid::VertexAttachmentAccessor<AVector3> aaPos)
     687              : {
     688            0 :         UG_COND_THROW(layers.empty(), "Can't snap to empty raster!");
     689              : 
     690            0 :         const Heightfield& field = layers.top().heightfield;
     691              : 
     692              :         for(VertexIterator ivrt = grid.vertices_begin();
     693            0 :                 ivrt != grid.vertices_end(); ++ivrt)
     694              :         {
     695              :                 Vertex* vrt = *ivrt;
     696              :                 vector3& v = aaPos[vrt];
     697            0 :                 pair<int, int> ci = field.coordinate_to_index(v.x(), v.y());
     698            0 :                 vector2 nv = field.index_to_coordinate(ci.first, ci.second);
     699            0 :                 v.x() = nv.x();
     700            0 :                 v.y() = nv.y();
     701              :         }
     702            0 : }
     703              : 
     704              : }//     end of namespace
        

Generated by: LCOV version 2.0-1