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

            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 <fstream>
      34              : #include <queue>
      35              : #include "lib_grid/lg_base.h"
      36              : #include "common/profiler/profiler.h"
      37              : #include "simple_grid.h"
      38              : #include "edge_length_adjustment.h"
      39              : #include "lib_grid/refinement/regular_refinement.h"
      40              : #include "common/node_tree/node_tree.h"
      41              : #include "lib_grid/algorithms/trees/octree.h"
      42              : #include "lib_grid/callbacks/callbacks.h"
      43              : #include "../trees/octree.h"
      44              : 
      45              : using namespace std;
      46              : 
      47              : namespace ug
      48              : {
      49              : 
      50              : ///     only for debugging purposes!!!
      51              : /**     Output value pairs to gnuplot...
      52              :  * \{ */
      53              : //#define EDGE_LENGTH_ADJUSTMENT__GPLOT_ENABLED
      54              : #ifdef EDGE_LENGTH_ADJUSTMENT__GPLOT_ENABLED
      55              :         typedef vector<pair<number, number> > GnuplotData;
      56              :         static GnuplotData gplotLengthFac;
      57              :         static GnuplotData gplotMinCurvature;
      58              :         static GnuplotData gplotAverageCurvature;
      59              : 
      60              :         void WriteGnuplotData(const char* filename, const GnuplotData& data)
      61              :         {
      62              :                 ofstream out(filename);
      63              :                 if(!out)
      64              :                         return;
      65              : 
      66              :                 for(size_t i = 0; i < data.size(); ++i)
      67              :                         out << data[i].first << " " << data[i].second << endl;
      68              : 
      69              :                 out.close();
      70              :         }
      71              : 
      72              :         #define GPLOTPOINT(dataName, x, y) dataName.push_back(make_pair<number, number>((x), (y)));
      73              :         #define GPLOTSAVE()     {WriteGnuplotData("length_fac.gplot", gplotLengthFac);\
      74              :                                                 WriteGnuplotData("min_curvature.gplot", gplotMinCurvature);\
      75              :                                                 WriteGnuplotData("average_curvature.gplot", gplotAverageCurvature);}
      76              : #else
      77              : //      do nothing if EDGE_LENGTH_ADJUSTMENT__GPLOT_ENABLED is false
      78              :         #define GPLOTPOINT(dataName, x, y)
      79              :         #define GPLOTSAVE()
      80              : #endif
      81              : /** \} */
      82              : 
      83              : 
      84              : /*
      85              : vector3 PNTrianglePos(const vector3& p0, const vector3& p1, const vector3& p2,
      86              :                                           const vector3& n0, const vector3& n1, const vector3& n2);
      87              : 
      88              : vector3 PNTriangleNorm(const vector3& p0, const vector3& p1, const vector3& p2,
      89              :                                            const vector3& n0, const vector3& n1, const vector3& n2);
      90              : 
      91              : vector3 PNCTrianglePos(const vector3& p0, const vector3& p1, const vector3& p2,
      92              :                                                 const vector3& n0, const vector3& n1, const vector3& n2,
      93              :                                                 const vector3& cn0, const vector3& cn1, const vector3& cn2);
      94              : 
      95              : vector3 PNCTriangleNorm(const vector3& p0, const vector3& p1, const vector3& p2,
      96              :                                                 const vector3& n0, const vector3& n1, const vector3& n2,
      97              :                                                 const vector3& cn0, const vector3& cn1, const vector3& cn2);
      98              : 
      99              : 
     100              :                 vector3 pos(number bc0, number bc1);
     101              :                 vector3 norm(number bc0, number bc1);
     102              : };
     103              : 
     104              : class ProjectedVertex{
     105              :         Vertex* vertex();
     106              :         vector3 vertex_position();
     107              :         vector3 vertex_normal();
     108              :         vector3 surface_normal();
     109              :         vector3 surface_position();
     110              :         size_t num_barycentric_coords();
     111              :         number barycentric_coord(size_t index);
     112              : };
     113              : 
     114              : class SurfaceRepresentation{
     115              :         public:
     116              : 
     117              : };
     118              : */
     119              : 
     120              : ////////////////////////////////////////////////////////////////////////
     121            0 : static void AssignFixedVertices(Grid& grid, SubsetHandler& shMarks)
     122              : {       
     123            0 :         grid.begin_marking();
     124              :         
     125              : //      mark all vertices that are not regular crease-vertices as fixed
     126              :         for(EdgeIterator iter = shMarks.begin<Edge>(REM_CREASE);
     127            0 :                 iter != shMarks.end<Edge>(REM_CREASE); ++iter)
     128              :         {
     129              :                 Edge* e = *iter;
     130            0 :                 for(size_t i = 0; i < 2; ++i){
     131            0 :                         Vertex* vrt = e->vertex(i);
     132            0 :                         if(!grid.is_marked(vrt)){
     133              :                                 grid.mark(vrt);
     134              :                                 int counter = 0;
     135            0 :                                 for(Grid::AssociatedEdgeIterator nbIter = grid.associated_edges_begin(vrt);
     136            0 :                                         nbIter != grid.associated_edges_end(vrt); ++nbIter)
     137              :                                 {
     138            0 :                                         if(shMarks.get_subset_index(*nbIter) != REM_NONE)
     139            0 :                                                 ++counter;
     140              :                                 }
     141              :                                 
     142            0 :                                 if(counter != 2)
     143            0 :                                         shMarks.assign_subset(vrt, REM_FIXED);
     144              :                         }
     145              :                 }
     146              :         }
     147              :         
     148            0 :         grid.end_marking();
     149              :         
     150              : //      mark all vertices that lie on a fixed edge as fixed vertex
     151              :         for(EdgeIterator iter = shMarks.begin<Edge>(REM_FIXED);
     152            0 :                 iter != shMarks.end<Edge>(REM_FIXED); ++iter)
     153              :         {
     154              :                 Edge* e = *iter;
     155            0 :                 shMarks.assign_subset(e->vertex(0), REM_FIXED);
     156            0 :                 shMarks.assign_subset(e->vertex(1), REM_FIXED);
     157              :         }
     158            0 : }
     159              : 
     160            0 : static void AssignCreaseVertices(Grid& grid, SubsetHandler& shMarks)
     161              : {
     162              : //      mark all vertices that lie on a crease and which are not fixed
     163              : //      as crease vertices.
     164            0 :         if(shMarks.num_subsets() <= REM_CREASE)
     165              :                 return;
     166              : 
     167              :         for(EdgeIterator iter = shMarks.begin<Edge>(REM_CREASE);
     168            0 :                 iter != shMarks.end<Edge>(REM_CREASE); ++iter)
     169              :         {
     170              :                 Edge* e = *iter;
     171            0 :                 for(uint i = 0; i < 2; ++i)
     172            0 :                         if(shMarks.get_subset_index(e->vertex(i)) != REM_FIXED)
     173            0 :                                 shMarks.assign_subset(e->vertex(i), REM_CREASE);
     174              :         }
     175              : }
     176              : 
     177              : 
     178              : ////////////////////////////////////////////////////////////////////////
     179              : template <class TVertexPositionAccessor>
     180              : number CalculateNormalDot(TriangleDescriptor& td1, TriangleDescriptor& td2,
     181              :                                                   TVertexPositionAccessor& aaPos)
     182              : {
     183              :         vector3 n1;
     184              :         CalculateTriangleNormal(n1, aaPos[td1.vertex(0)],
     185              :                                                         aaPos[td1.vertex(1)], aaPos[td1.vertex(2)]);
     186              :         vector3 n2;
     187              :         CalculateTriangleNormal(n2, aaPos[td2.vertex(0)],
     188              :                                                         aaPos[td2.vertex(1)], aaPos[td2.vertex(2)]);
     189              :         return VecDot(n1, n2);
     190              : }
     191              : 
     192              : 
     193              : ////////////////////////////////////////////////////////////////////////
     194              : //      CalculateCurvature
     195              : template <class TAAPosVRT>
     196            0 : number CalculateMinCurvature(Grid& grid, SubsetHandler& shMarks,
     197              :                                                         Vertex* vrt, TAAPosVRT& aaPos)
     198              : {
     199              : //TODO: check whether static vNormals brings any benefits.
     200              : //TODO: special cases for crease vertices
     201              : 
     202              : //      face normals
     203            0 :         static vector<vector3>    vNormals;
     204              : //      vertex normal (mean face normal)
     205              :         vector3 n(0, 0, 0);
     206              :         
     207              : //      calculate the normals of associated faces
     208              :         vNormals.clear();
     209            0 :         Grid::AssociatedFaceIterator iterEnd = grid.associated_faces_end(vrt);
     210            0 :         for(Grid::AssociatedFaceIterator iter = grid.associated_faces_begin(vrt);
     211            0 :                 iter != iterEnd; ++iter)
     212              :         {
     213              :                 vector3 nTmp;
     214            0 :                 CalculateNormal(nTmp, *iter, aaPos);
     215            0 :                 vNormals.push_back(nTmp);
     216              :                 VecAdd(n, n, nTmp);
     217              :         }
     218              : 
     219              : //      the vertex normal
     220            0 :         VecNormalize(n, n);
     221              :         
     222              : //      get the min dot-product of the vertex normal with associated faces-normals
     223            0 :         number minDot = 1;
     224            0 :         for(size_t i = 0; i < vNormals.size(); ++i)
     225            0 :                 minDot = std::min(minDot, VecDot(n, vNormals[i]));
     226              : 
     227              : //todo: Think about converting to radiants.
     228              :         //minDot = acos(minDot) / (0.5 * PI);
     229              :         //...
     230              : //      done
     231              :         GPLOTPOINT(gplotMinCurvature, 0, minDot);
     232            0 :         return minDot;  
     233              : }                                                       
     234              : 
     235              : ////////////////////////////////////////////////////////////////////////
     236              : template <class TAAPosVRT>
     237            0 : number CalculateAverageCurvature(Grid& grid, SubsetHandler& shMarks,
     238              :                                                                 Edge* e, TAAPosVRT& aaPos)
     239              : {
     240            0 :         number avCurv = 0.5 * (CalculateMinCurvature(grid, shMarks, e->vertex(0), aaPos)
     241            0 :                                 + CalculateMinCurvature(grid, shMarks, e->vertex(1), aaPos));
     242              :         GPLOTPOINT(gplotAverageCurvature, 0.5, avCurv);
     243            0 :         return avCurv;
     244              : }
     245              : 
     246              : ////////////////////////////////////////////////////////////////////////
     247              : template <class TAAPosVRT>
     248              : number CalculateLengthFac(Grid& grid, SubsetHandler& shMarks,
     249              :                                                                 Edge* e, TAAPosVRT& aaPos)
     250              : {
     251            0 :         number lenFac = CalculateAverageCurvature(grid, shMarks, e, aaPos);
     252            0 :         lenFac = (lenFac - 0.95) / 0.05;
     253            0 :         lenFac = max(number(0.25), lenFac);
     254              :         GPLOTPOINT(gplotLengthFac, 0.5, lenFac);
     255              :         return lenFac;
     256              : }
     257              : 
     258              : ////////////////////////////////////////////////////////////////////////
     259              : ////////////////////////////////////////////////////////////////////////
     260              : template <class TAAPosVRT, class TAANormVRT, class TAAIntVRT>
     261            0 : bool TrySwap(Grid& grid, Edge* e, TAAPosVRT& aaPos, TAANormVRT& aaNorm,
     262              :                         TAAIntVRT& aaInt, SubsetHandler* pshMarks = NULL,
     263              :                         EdgeSelector* pCandidates = NULL)
     264              : {
     265              : //      swaps are neither allowed for crease edges nor for fixed edges
     266            0 :         if(pshMarks){
     267            0 :                 if(pshMarks->get_subset_index(e) == REM_FIXED ||
     268              :                         pshMarks->get_subset_index(e) == REM_CREASE)
     269            0 :                         return false;
     270              :         }
     271              : 
     272              : //      get the associated faces. we need two of them
     273              :         Face* f[2];
     274            0 :         if(GetAssociatedFaces(f, grid, e, 2) != 2)
     275              :                 return false;
     276              : 
     277              : //      make sure both faces are triangles
     278            0 :         if((f[0]->num_vertices() != 3) || (f[1]->num_vertices() != 3))
     279            0 :                 return false;
     280              : 
     281              : //      create a simple grid
     282              :         SimpleGrid sg;
     283            0 :         if(!ObtainSimpleGrid(sg, grid, e->vertex(0), e->vertex(1), 0,
     284              :                                                 aaPos, aaNorm, aaInt))
     285              :         {
     286              :                 LOG("ObtainSimpleGrid failed. ignoring edge...\n");
     287              :                 return false;
     288              :         }
     289              : 
     290              : //      calculate geometric-approximation-degree and triangle quality
     291              :         //number approxDeg = GeometricApproximationDegree(sg);
     292            0 :         number shapeDeg = ShapeQualityDegree(sg);
     293              : 
     294              :         number smoothDeg = VecDot(sg.triangleNormals[0], sg.triangleNormals[1]);
     295              : 
     296              : //      this is a new test. the idea is that each edge should be orthogonal to
     297              : //      the normals of its endpoints - at least in a perfectly smooth surface.
     298              : 
     299              :         number approxDeg;
     300              :         number newApproxDeg;
     301              :         {
     302              :                 vector3 v;
     303              :                 VecSubtract(v, sg.vertices[1], sg.vertices[0]);
     304            0 :                 VecNormalize(v, v);
     305            0 :                 approxDeg = 1. - 0.5*(fabs(VecDot(v, sg.vertexNormals[0])) +
     306            0 :                                                         fabs(VecDot(v, sg.vertexNormals[1])));
     307              :                                                 
     308              :                 VecSubtract(v, sg.vertices[3], sg.vertices[2]);
     309            0 :                 VecNormalize(v, v);
     310            0 :                 newApproxDeg = 1. - 0.5*(fabs(VecDot(v, sg.vertexNormals[2])) +
     311            0 :                                                                 fabs(VecDot(v, sg.vertexNormals[3])));
     312              :         }
     313              : 
     314              : //      perform a swap on the simple grid
     315            0 :         if(!SwapEdge(sg))
     316              :         {
     317              :                 LOG("swap edge failed...\n");
     318              :                 return false;
     319              :         }
     320              : 
     321              : //      calculate new geometric-approximation-degree and triangle quality
     322              :         //number newApproxDeg = GeometricApproximationDegree(sg);
     323            0 :         number newShapeDeg = ShapeQualityDegree(sg);
     324              :         number newSmoothDeg = VecDot(sg.triangleNormals[0], sg.triangleNormals[1]);
     325              : 
     326              : //      neither the shapeDeg nor the approxDeg may get too bad.
     327            0 :         if((newApproxDeg < 0.5 * approxDeg) || (newShapeDeg < 0.5 * shapeDeg))
     328              :                 return false;
     329              :         
     330              : //      make sure that the swap does not destroy the smoothness
     331            0 :         if(newSmoothDeg < 0.1 * smoothDeg)
     332              :                 return false;
     333              : 
     334            0 :         if(0.2 * (newApproxDeg - approxDeg) + 0.8 * (newShapeDeg - shapeDeg) > 0)
     335              :         //if(newShapeDeg > shapeDeg)
     336              :         //if(newApproxDeg > approxDeg)
     337              :         {
     338              :         //      swap the edge
     339            0 :                 e = SwapEdge(grid, e);
     340              : 
     341            0 :                 if(e){
     342              :                 //      swap was successful
     343              :                 //      if pCandidates was specified then add new candidates
     344            0 :                         if(pCandidates){
     345            0 :                                 for(int i = 0; i < 2; ++i)
     346            0 :                                         pCandidates->select(grid.associated_edges_begin(e->vertex(i)),
     347            0 :                                                                                 grid.associated_edges_end(e->vertex(i)));
     348              :                         //      e was selected but is not really a candidate
     349            0 :                                 pCandidates->deselect(e);
     350              :                         }
     351              :                         
     352            0 :                         return true;
     353              :                 }
     354              :         }
     355              :         
     356              :         return false;
     357            0 : }
     358              : 
     359              : ////////////////////////////////////////////////////////////////////////
     360              : template <class TAAPosVRT, class TAANormVRT, class TAAIntVRT>
     361            0 : bool PerformSwaps(Grid& grid, SubsetHandler& shMarks, EdgeSelector& esel,
     362              :                                 TAAPosVRT& aaPos, TAANormVRT& aaNorm, TAAIntVRT& aaInt)
     363              : {       
     364              :         PROFILE_FUNC();
     365              :         LOG("  performing swaps\n");
     366              :         int numSwaps = 0;
     367            0 :         int maxNumSwaps = esel.num<Edge>() * 2;
     368              :                 
     369            0 :         while(!esel.empty())
     370              :         {
     371              :                 Edge* e = *esel.begin<Edge>();
     372            0 :                 esel.deselect(e);
     373              : 
     374            0 :                 if(TrySwap(grid, e, aaPos, aaNorm, aaInt, &shMarks, &esel)){
     375            0 :                         ++numSwaps;
     376            0 :                         if(numSwaps > maxNumSwaps){
     377              :                                 UG_LOG("  aborting since maxNumSwaps was reached...");
     378            0 :                                 esel.clear();
     379              :                         }
     380              :                 }
     381              :         }
     382            0 :         LOG("  swaps performed: " << numSwaps << endl);
     383              :         
     384            0 :         return true;
     385              : }
     386              : 
     387              : /**     returns the resulting vertex or NULL, if no collapse was performed.*/
     388              : template <class TAAPosVRT, class TAANormVRT, class TAAIntVRT>
     389            0 : Vertex* TryCollapse(Grid& grid, Edge* e,
     390              :                                 TAAPosVRT& aaPos, TAANormVRT& aaNorm, 
     391              :                                 TAAIntVRT& aaInt, SubsetHandler* pshMarks = NULL,
     392              :                                 EdgeSelector* pCandidates = NULL)
     393              : {
     394            0 :         if(pshMarks)
     395              :         {
     396              :                 SubsetHandler& shMarks = *pshMarks;
     397              :         //      collapses are not allowed for fixed edges
     398            0 :                 if(shMarks.get_subset_index(e) == REM_FIXED)
     399              :                         return NULL;
     400              :                         
     401              :         //      if both endpoints of are fixed vertices then
     402              :         //      we may not collapse
     403              :                 int vrtSI[2];
     404            0 :                 vrtSI[0] = shMarks.get_subset_index(e->vertex(0));
     405            0 :                 vrtSI[1] = shMarks.get_subset_index(e->vertex(1));
     406              : 
     407            0 :                 if((vrtSI[0] == REM_FIXED) && (vrtSI[1] == REM_FIXED))
     408              :                         return NULL;
     409              : 
     410              :         //      if both endpoints are somehow marked, e has to be a
     411              :         //      crease edge
     412            0 :                 if((vrtSI[0] != REM_NONE) && (vrtSI[1] != REM_NONE)
     413            0 :                         &&      (shMarks.get_subset_index(e) != REM_CREASE))
     414              :                         return NULL;
     415              :         }
     416              : 
     417              : //      check whether the edge can be collapsed
     418            0 :         if(EdgeCollapseIsValid(grid, e))
     419              :         {
     420              :         //      test the collapse using a simple-grid
     421              :                 SimpleGrid sgSrc;
     422            0 :                 if(!ObtainSimpleGrid(sgSrc, grid, e->vertex(0), e->vertex(1), 1,
     423              :                                                         aaPos, aaNorm, aaInt))
     424              :                 {
     425              :                         LOG("ObtainSimpleGrid failed. ignoring edge...\n");
     426              :                         return NULL;
     427              :                 }
     428              :                 
     429              :         //      calculate geometric-approximation-degree and triangle quality
     430            0 :                 number approxDeg = GeometricApproximationDegree(sgSrc);
     431            0 :                 number shapeDeg = ShapeQualityDegree(sgSrc);
     432              : 
     433              :         //      perform a collapse on the simple grid
     434              :                 SimpleGrid sgDest;
     435            0 :                 if(!ObtainSimpleGrid_CollapseEdge(sgDest, grid, e,
     436              :                                                                         1, aaPos, aaNorm, aaInt))
     437              :                 {
     438              :                         LOG("collapse edge failed...\n");
     439              :                         return NULL;
     440              :                 }
     441              : 
     442              :         //      get the positions of the old endpoints
     443              :                 static const int numTestPositions = 3;
     444              :                 int newInd = 0;
     445            0 :                 vector3 v[numTestPositions];
     446            0 :                 v[0] = aaPos[e->vertex(0)];
     447            0 :                 v[1] = aaPos[e->vertex(1)];
     448              :                 v[2] = sgDest.vertices[newInd];
     449              :                 
     450              :         //      we'll compare 3 approximation degrees and three shape degrees
     451              :                 number newApproxDeg[numTestPositions];
     452              :                 number newShapeDeg[numTestPositions];
     453              :                 
     454              :         //      check which position is the best
     455              :                 int bestIndex = -1;
     456              :         //      the vertex subset index is used to support marks (crease and fixed vertices)
     457              :                 int vrtSI[2];
     458              :                 vrtSI[0] = vrtSI[1] = REM_NONE;
     459              : 
     460            0 :                 if(pshMarks)
     461              :                 {
     462            0 :                         vrtSI[0] = pshMarks->get_subset_index(e->vertex(0));
     463            0 :                         vrtSI[1] = pshMarks->get_subset_index(e->vertex(1));
     464              : 
     465            0 :                         if((vrtSI[0] == REM_FIXED) || ((vrtSI[0] != REM_NONE) && (vrtSI[1] == REM_NONE))){
     466              :                                 bestIndex = 0;
     467              :                                 sgDest.vertices[newInd] = v[0];
     468            0 :                                 newApproxDeg[0] = GeometricApproximationDegree(sgDest);
     469            0 :                                 newShapeDeg[0] = ShapeQualityDegree(sgDest);
     470              :                         }
     471            0 :                         else if((vrtSI[1] == REM_FIXED) || ((vrtSI[1] != REM_NONE) && (vrtSI[0] == REM_NONE))){
     472              :                                 bestIndex = 1;
     473              :                                 sgDest.vertices[newInd] = v[1];
     474            0 :                                 newApproxDeg[1] = GeometricApproximationDegree(sgDest);
     475            0 :                                 newShapeDeg[1] = ShapeQualityDegree(sgDest);
     476              :                         }
     477              :                 }
     478              : 
     479              :                 if(bestIndex == -1){
     480              :                 //      check all three approximation degrees
     481            0 :                         for(int i = 0; i < numTestPositions; ++i){
     482              :                         //      we'll compute all qualities with the averaged normal
     483              :                                 sgDest.vertices[newInd] = v[i];
     484            0 :                                 CalculateTriangleNormals(sgDest);
     485            0 :                                 newApproxDeg[i] = GeometricApproximationDegree(sgDest);
     486            0 :                                 newShapeDeg[i] = ShapeQualityDegree(sgDest);
     487              :                         }
     488              :                 //      get the best one
     489              :                         bestIndex = 0;
     490              :                 /*
     491              :                         for(int i = 1; i < numTestPositions; ++i){
     492              :                                 if(newApproxDeg[i] > newApproxDeg[bestIndex])
     493              :                                         bestIndex = i;
     494              :                         }
     495              :                 */
     496            0 :                         for(int i = 1; i < numTestPositions; ++i){
     497            0 :                                 if(newShapeDeg[i] > newShapeDeg[bestIndex])
     498              :                                         bestIndex = i;
     499              :                         }
     500              :                 }
     501              : 
     502              :         //      if the shape-degree of the collapsed region is too bad, we'll skip the collapse
     503            0 :                 if(newShapeDeg[bestIndex] < 0.5 * shapeDeg)
     504              :                         return NULL;
     505              : /*
     506              :         //      the approximation degree is only interesting if both endpoints of the
     507              :         //      edge are regular surface vertices
     508              :                 bool regularNeighbourhood = IsRegularSurfaceVertex(grid, e->vertex(0)) &&    
     509              :                                                                         IsRegularSurfaceVertex(grid, e->vertex(1));
     510              : */
     511              : 
     512              :         //      if the best approximation degree is not too bad, we'll perform the collapse
     513            0 :                 if(/*!regularNeighbourhood || */(newApproxDeg[bestIndex] > 0.95 * approxDeg))
     514              :                 {                                               
     515              :                 //      pick one of the endpoints to be the one that resides
     516              :                 //      This has to be done with care, since the residing vertex
     517              :                 //      determines which edges will be removed and which will remain
     518              :                 //      (this is important, since we want crease edges to remain!).
     519              :                 //      If only one of the endpoints lies on a crease or is fixed, the
     520              :                 //      decision is easy (the marked one has to remain).
     521              :                 //      If both are marked, we have to investigate the triangles which
     522              :                 //      are adjacent to the collapsed edge (quadrilaterals don't make
     523              :                 //      problems here).
     524              :                 //      - If all three corner vertices are marked we have to distinguish:
     525              :                 //              (a) all three edges are marked -> abort
     526              :                 //              (b) two edges are marked -> the vertex connecting both remains.
     527              :                 //              (c) one edge is marked -> the chosen vertex doesn't affect edge-marks.
     528              :                 //      - If only the two are marked they don't affect the edge-marks.
     529              :                 //      
     530              :                 //      Even more care has to be taken if a fixed vertex is involved.
     531              :                 //      If case (b) applies and the creas-vertex is has to remain, it
     532              :                 //      has to be moved to the position of the fixed-vertex and has to
     533              :                 //      be marked fixed itself.
     534              :                                         
     535              :                 //      choose the vertex that shall remain.
     536            0 :                         Vertex* vrt = e->vertex(0);
     537              : 
     538            0 :                         if(vrtSI[0] != REM_FIXED && vrtSI[1] != REM_NONE)
     539              :                         {
     540            0 :                                 vrt = e->vertex(1);
     541              :                         }
     542              : 
     543            0 :                         if(vrtSI[0] != REM_NONE && vrtSI[1] != REM_NONE){
     544              :                         //      both are marked. Things are getting complicated now!
     545              :                         //      get adjacent faces of e
     546              :                                 vector<Face*> vFaces;
     547            0 :                                 vFaces.reserve(2);
     548            0 :                                 CollectFaces(vFaces, grid, e);
     549              :                         
     550              :                                 vector<Edge*> vEdges;
     551            0 :                                 vEdges.reserve(4);
     552            0 :                                 for(size_t i = 0; i < vFaces.size(); ++i){
     553            0 :                                         Face* f = vFaces[i];
     554              :                                 //      only triangles are interesting
     555            0 :                                         if(f->num_edges() == 3){
     556              :                                         //      get the number of marked edges
     557            0 :                                                 CollectEdges(vEdges, grid, f);
     558              :                                         //      count the marked edges
     559              :                                                 int numMarked = 0;
     560            0 :                                                 for(size_t j = 0; j < vEdges.size(); ++j){
     561              :                                                 //      note that pshMarks exists since vrtSI != REM_NONE
     562            0 :                                                         if(pshMarks->get_subset_index(vEdges[j]) != REM_NONE)
     563            0 :                                                                 ++numMarked;
     564              :                                                 }
     565              :                                         
     566            0 :                                                 if(numMarked == 3){
     567              :                                                         return NULL;    //      case (a) applies
     568              :                                                 }
     569            0 :                                                 else if(numMarked == 2){
     570              :                                                 //      check which of the vrts is connected to two
     571              :                                                 //      marked edges of the triangle
     572            0 :                                                         for(size_t j = 0; j < 2; ++j){
     573              :                                                                 int numMarked = 0;
     574            0 :                                                                 for(size_t k = 0; k < vEdges.size(); ++k){
     575            0 :                                                                         if(pshMarks->get_subset_index(vEdges[k]) != REM_NONE){
     576            0 :                                                                                 if(EdgeContains(vEdges[k], e->vertex(j)))
     577            0 :                                                                                         ++numMarked;
     578              :                                                                         }
     579              :                                                                 }
     580              :                                                         //      if numMarked == 2 we found it
     581            0 :                                                                 if(numMarked == 2){
     582              :                                                                 //      the connected edge has to be marked as a crease
     583            0 :                                                                         Edge* ce = GetConnectedEdge(grid, e->vertex(j), f);
     584            0 :                                                                         if(ce)
     585            0 :                                                                                 pshMarks->assign_subset(ce, REM_CREASE);
     586              :                                                                 //      we're done. break
     587              :                                                                         break;
     588              :                                                                 }
     589              :                                                         }
     590              :                                                 }
     591              :                                                 else{
     592              :                                                 }
     593              :                                         }
     594              :                                 }
     595            0 :                         }
     596              : 
     597              :                 //      collapse the edge
     598            0 :                         CollapseEdge(grid, e, vrt);
     599              :                         
     600              :                 //      assign best position
     601              :                         aaPos[vrt] = v[bestIndex];
     602              :                 //      assign the normal
     603              :                         aaNorm[vrt] = sgDest.vertexNormals[newInd];
     604              : /*
     605              :                         if(pCandidates){
     606              : //TODO: all edges that belong to associated faces are new candidates.                                           
     607              :                         //      associated edges of vrt are possible new candidates
     608              :                                 pCandidates->select(grid.associated_edges_begin(vrt),
     609              :                                                         grid.associated_edges_end(vrt));
     610              :                         }*/
     611              : 
     612            0 :                         return vrt;
     613              :                 }
     614            0 :         }
     615              : 
     616              :         return NULL;
     617              : }
     618              : 
     619              : ////////////////////////////////////////////////////////////////////////
     620              : template <class TAAPosVRT, class TAANormVRT, class TAAIntVRT>
     621            0 : bool PerformCollapses(Grid& grid, SubsetHandler& shMarks, EdgeSelector& esel,
     622              :                                           number minEdgeLen, TAAPosVRT& aaPos, TAANormVRT& aaNorm,
     623              :                                           TAAIntVRT& aaInt, bool adaptive = true)
     624              : {       
     625              :         PROFILE_FUNC();
     626              :         LOG("  performing collapses\n");
     627              :         vector<Edge*>     edges;
     628              :         int numCollapses = 0;
     629              : //      compare squares
     630            0 :         minEdgeLen *= minEdgeLen;
     631              : 
     632            0 :         while(!esel.empty())
     633              :         {
     634              :                 Edge* e = *esel.begin<Edge>();
     635            0 :                 esel.deselect(e);
     636              :                 
     637              :         //      the higher the curvature the smaller the maxEdgeLen.
     638              :         //      minimal lenFac is 0.1
     639              :                 number lenFac = 1.0;
     640            0 :                 if(adaptive)
     641              :                         lenFac = CalculateLengthFac(grid, shMarks, e, aaPos);
     642              : 
     643              :         //      check whether the edge is short enough
     644            0 :                 if(VecDistanceSq(aaPos[e->vertex(0)], aaPos[e->vertex(1)]) < lenFac * minEdgeLen)
     645              :                 {
     646            0 :                         Vertex* vrt = TryCollapse(grid, e, aaPos, aaNorm, aaInt, &shMarks, &esel);
     647            0 :                         if(vrt){
     648            0 :                                 ++numCollapses;
     649              : 
     650              :                         //      we'll deselect associated edges of vrt, to avoid cascade-collapses
     651              :                                 CollectAssociated(edges, grid, vrt);
     652              :                                 esel.deselect(edges.begin(), edges.end());
     653              :                         }
     654              :                 }
     655              :         }
     656            0 :         LOG("  collapses performed: " << numCollapses << endl);
     657              :         
     658            0 :         return true;
     659            0 : }
     660              : 
     661              : ////////////////////////////////////////////////////////////////////////
     662              : template <class TAAPosVRT, class TAANormVRT>
     663            0 : bool TrySplit(Grid& grid, Edge* e, TAAPosVRT& aaPos, TAANormVRT& aaNorm,
     664              :                           EdgeSelector* pCandidates = NULL, SubsetHandler* pshMarks = NULL)
     665              : {
     666              :         bool bCreaseEdge = false;
     667              : //      splits are not allowed for fixed edges
     668            0 :         if(pshMarks){
     669            0 :                 if(pshMarks->get_subset_index(e) == REM_FIXED)
     670              :                         return false;
     671            0 :                 else if(pshMarks->get_subset_index(e) == REM_CREASE)
     672              :                         bCreaseEdge = true;
     673              :         }
     674              : 
     675              : //      get the center of the edges
     676            0 :         vector3 vCenter = CalculateCenter(e, aaPos);
     677              : 
     678              : //      the new normal
     679              :         vector3 n;
     680            0 :         if(bCreaseEdge){                
     681              :         //      interpolating the normal can cause severe problems at highly
     682              :         //      irregular vertices or if one vertecs lies on a very
     683              :         //      sharp edge (the normals of the endpoints thus point
     684              :         //      in different directions.)
     685              : //              VecAdd(n, aaNorm[e->vertex(0)], aaNorm[e->vertex(1)]);
     686              : //              VecNormalize(n, n);
     687            0 :                 CalculateNormal(n, grid, e, aaPos);
     688              :         }
     689              : 
     690              : //      split the edge
     691              :         RegularVertex* vrt = SplitEdge<RegularVertex>(grid, e, false);
     692              : 
     693              : //      assign the new position
     694              :         aaPos[vrt] = vCenter;
     695              : 
     696              : //      assign the new normal. calculate it if required
     697            0 :         if(!bCreaseEdge)
     698            0 :                 CalculateVertexNormal(n, grid, vrt, aaPos);                     
     699              : 
     700              :         aaNorm[vrt] = n;
     701              : 
     702              : //      associated edges of vrt are candidates again
     703            0 :         if(pCandidates)
     704            0 :                 pCandidates->select(grid.associated_edges_begin(vrt),
     705              :                                                         grid.associated_edges_end(vrt));
     706              : 
     707              :         return true;
     708              : }
     709              : 
     710              : ////////////////////////////////////////////////////////////////////////
     711              : template <class TAAPosVRT, class TAANormVRT>
     712            0 : bool PerformSplits(Grid& grid, SubsetHandler& shMarks, EdgeSelector& esel,
     713              :                                           number maxEdgeLen, TAAPosVRT& aaPos, TAANormVRT& aaNorm,
     714              :                                           bool adaptive = true)
     715              : {
     716              :         PROFILE_FUNC();
     717              : //      compare squares
     718            0 :         maxEdgeLen *= maxEdgeLen;
     719              : 
     720              :         LOG("  performing splits\n");
     721              :         int numSplits = 0;
     722              : 
     723            0 :         while(!esel.empty())
     724              :         {
     725              :         //      get an edge
     726              :                 Edge* e = *esel.begin<Edge>();
     727            0 :                 esel.deselect(e);
     728              :                 
     729              :         //      the higher the curvature the smaller the maxEdgeLen.
     730              :         //      minimal lenFac is 0.1
     731              :                 number lenFac = 1.0;
     732            0 :                 if(adaptive)
     733              :                         lenFac = CalculateLengthFac(grid, shMarks, e, aaPos);
     734              : 
     735              :         //      check whether the edge should be splitted
     736            0 :                 if(VecDistanceSq(aaPos[e->vertex(0)], aaPos[e->vertex(1)]) > lenFac * maxEdgeLen)
     737              :                 {
     738            0 :                         if(TrySplit(grid, e, aaPos, aaNorm, &esel, &shMarks))
     739            0 :                                 ++numSplits;
     740              :                 }
     741              :         }
     742              : 
     743            0 :         LOG("  splits performed: " << numSplits << endl);
     744            0 :         return true;
     745              : }
     746              : 
     747              : ////////////////////////////////////////////////////////////////////////
     748              : //      relocate point by smoothing
     749              : // static void RelocatePointBySmoothing(vector3& vOut, const vector3&v,
     750              : //                                                std::vector<vector3>& vNodes,
     751              : //                                                size_t numIterations, number stepSize,
     752              : //                                                std::vector<number>* pvWeights = NULL)
     753              : // {
     754              : //      if(vNodes.empty())
     755              : //              return;
     756              : 
     757              : // //TODO:      incorporate weights
     758              : // //   iterate through all nodes, calculate the direction
     759              : // //   from v to each node, and add the scaled sum to v.
     760              : //      vector3 t, vOld;
     761              : //      vOut = v;
     762              : //      stepSize /= (number)vNodes.size();
     763              : 
     764              : //      for(size_t j = 0; j < numIterations; ++j){
     765              : //              vOld = vOut;
     766              : //              for(size_t i = 0; i < vNodes.size(); ++i){
     767              : //                      VecSubtract(t, vNodes[i], vOld);
     768              : //                      VecScale(t, t, stepSize);
     769              : //                      VecAdd(vOut, vOut, t);
     770              : //              }
     771              : //      }
     772              : // }
     773              : 
     774              : ////////////////////////////////////////////////////////////////////////
     775              : //      FixBadTriangles
     776              : // template <class TAAPosVRT, class TAANormVRT>
     777              : // static bool FixBadTriangles(Grid& grid, SubsetHandler& shMarks, EdgeSelector& esel,
     778              : //                                      TAAPosVRT& aaPos, TAANormVRT& aaNorm,
     779              : //                                      number qualityThreshold)
     780              : // {
     781              : //      LOG("  fixing bad triangles... ");
     782              : // //   iterate through marked edges and check whether adjacent triangles are
     783              : // //   badly shaped. If this is the case, then split the non-marked
     784              : // //   edges of the triangle.
     785              : // //   store newly inserted vertices and smooth them at the end of the algo
     786              : //      vector<Vertex*> vNewVrts;
     787              : //      vector<Face*> vFaces;
     788              : //      vector<Edge*> vEdges;
     789              :         
     790              : // //   we wont assign this selector to the grid until it is clear that
     791              : // //   we'll need it.
     792              : //      Selector sel;
     793              :         
     794              :         
     795              : //      EdgeIterator iter = esel.begin<Edge>();
     796              : //      while(iter != esel.end<Edge>())
     797              : //      {
     798              : //      //      store edge and increase iterator immediatly
     799              : //              Edge* e = *iter;
     800              : //              ++iter;
     801              :                 
     802              : //      //      get the adjacent faces
     803              : //              CollectFaces(vFaces, grid, e);
     804              :                 
     805              : //      //      check whether one of them is degenerated.
     806              : //              for(size_t i = 0; i < vFaces.size(); ++i){
     807              : //                      Face* f = vFaces[i];
     808              : //                      number q = FaceQuality(f, aaPos);
     809              : //              //      if the quality is smaller than threshold, we have to
     810              : //              //      do something
     811              : //                      if(q < qualityThreshold){
     812              : //                      //      make sure that the selector is connected to the grid
     813              : //                              if(sel.grid() == NULL)
     814              : //                                      sel.assign_grid(grid);
     815              :                                         
     816              : //                      //      get associated edges and mark them for refinement
     817              : //                              CollectEdges(vEdges, grid, f);
     818              : 
     819              : //                              for(size_t j = 0; j < vEdges.size(); ++j){
     820              : //                                      if(shMarks.get_subset_index(vEdges[j]) == REM_NONE)
     821              : //                                              sel.select(vEdges[j]);
     822              : //                              }
     823              : //                      }
     824              : //              }
     825              : //      }
     826              :         
     827              : // //   if edges have been selected, we'll now call refine.
     828              : //      if(sel.grid() != NULL){
     829              : //              if(sel.num<Edge>() > 0){
     830              : //                      if(Refine(grid, sel)){
     831              : //                              LOG(sel.num<Vertex>() << " new vertices... ");
     832              : //                      //      retriangulate surface
     833              : //                              if(grid.num<Quadrilateral>() > 0)
     834              : //                                      Triangulate(grid, grid.begin<Quadrilateral>(), grid.end<Quadrilateral>());
     835              :                                 
     836              : //                      //      calculate normals, then
     837              : //                      //      smooth new vertices (all vertices selected in sel).
     838              : //                              vector<Vertex*> vNeighbours;
     839              : //                              vector<vector3> vNodes;
     840              :                                 
     841              : //                      //      calculate normals
     842              : //                              for(VertexIterator iter = sel.begin<Vertex>();
     843              : //                                              iter != sel.end<Vertex>(); ++iter)
     844              : //                              {
     845              : //                              //      collect neighbour nodes
     846              : //                                      Vertex* vrt = *iter;
     847              : //                                      CollectNeighbors(vNeighbours, grid, vrt);
     848              :                                         
     849              : //                              //      sum their normals and interpolate it
     850              : //                              //      make sure to only add valid normals
     851              : //                                      vector3 n(0, 0, 0);
     852              : //                                      for(size_t i = 0; i < vNeighbours.size(); ++i){
     853              : //                                              if(!sel.is_selected(vNeighbours[i]))
     854              : //                                                      VecAdd(n, n, aaNorm[vNeighbours[i]]);
     855              : //                                      }
     856              : //                                      VecNormalize(aaNorm[vrt], n);
     857              : //                              }
     858              :                                 
     859              : //                      //      repeat smoothing.
     860              : //                              for(size_t i = 0; i < 5; ++i){
     861              : //                                      for(VertexIterator iter = sel.begin<Vertex>();
     862              : //                                              iter != sel.end<Vertex>(); ++iter)
     863              : //                                      {
     864              : //                                              Vertex* vrt = *iter;
     865              : 
     866              : //                                      //      collect the neighbours and project them to the plane
     867              : //                                      //      that is defined by vrt and its normal
     868              : //                                              vector3 v = aaPos[vrt];
     869              : //                                              vector3 n = aaNorm[vrt];
     870              : 
     871              : //                                              CollectNeighbors(vNeighbours, grid, vrt);
     872              : //                                              vNodes.resize(vNeighbours.size());
     873              :                                                 
     874              : //                                              for(size_t j = 0; j < vNodes.size(); ++j)
     875              : //                                                      ProjectPointToPlane(vNodes[j], aaPos[vNeighbours[j]], v, n);
     876              :                                                 
     877              : //                                      //      perform point relocation
     878              : //                                              RelocatePointBySmoothing(aaPos[vrt], v, vNodes, 5, 0.05);
     879              : //                                      }
     880              : //                              }
     881              : //                      }
     882              : //                      else{
     883              : //                              LOG("refine failed!\n");
     884              : //                              return false;
     885              : //                      }
     886              : //              }
     887              : //      }
     888              :         
     889              : //      LOG("done\n");
     890              : //      return true;
     891              : // }
     892              : 
     893              : // ////////////////////////////////////////////////////////////////////////
     894              : // //   PerformSmoothing
     895              : // template <class TAAPosVRT, class TAANormVRT>
     896              : // static void PerformSmoothing(Grid& grid, SubsetHandler& shMarks,
     897              : //                                      TAAPosVRT& aaPos, TAANormVRT& aaNorm,
     898              : //                                      size_t numIterations, number stepSize)
     899              : // {
     900              : //      vector<vector3> vNodes;
     901              : //      vector<Vertex*> vNeighbours;
     902              : //      for(size_t i = 0; i < numIterations; ++i){
     903              : //              CalculateVertexNormals(grid, aaPos, aaNorm);
     904              : //              for(VertexIterator iter = grid.begin<Vertex>();
     905              : //                      iter != grid.end<Vertex>(); ++iter)
     906              : //              {
     907              : //                      Vertex* vrt = *iter;
     908              : //              //      if the vertex is fixed then leave it where it is.
     909              : //                      if(shMarks.get_subset_index(vrt) == REM_FIXED)
     910              : //                              continue;
     911              : // /*
     912              : // if(shMarks.get_subset_index(vrt) == REM_CREASE)
     913              : //      continue;
     914              : // */
     915              : //              //      collect the neighbours and project them to the plane
     916              : //              //      that is defined by vrt and its normal
     917              : //                      vector3 v = aaPos[vrt];
     918              : //                      vector3 n = aaNorm[vrt];
     919              : 
     920              : //                      bool bProjectPointsToPlane = true;
     921              :                         
     922              : //                      if(shMarks.get_subset_index(vrt) == REM_CREASE){
     923              : //                              CollectNeighbors(vNeighbours, grid, vrt, NHT_EDGE_NEIGHBORS,
     924              : //                                                                      IsInSubset(shMarks, REM_CREASE));
     925              : 
     926              : //                      //      we have to choose a special normal
     927              : //                              if(vNeighbours.size() != 2){
     928              : //                                      UG_LOG("n"<<vNeighbours.size());
     929              : //                                      continue;
     930              : //                              }
     931              : //                              else{
     932              : //                                      vector3 v1, v2;
     933              : //                                      VecSubtract(v1, v, aaPos[vNeighbours[0]]);
     934              : //                                      VecSubtract(v2, v, aaPos[vNeighbours[1]]);
     935              : //                                      VecNormalize(v1, v1);
     936              : //                                      VecNormalize(v2, v2);
     937              : //                                      VecAdd(n, v1, v2);
     938              : //                                      if(VecLengthSq(n) > SMALL)
     939              : //                                              VecNormalize(n, n);
     940              : //                                      else {
     941              : //                                      //      both edges have the same direction.
     942              : //                                      //      don't project normals
     943              : //                                              bProjectPointsToPlane = false;
     944              : //                                      }
     945              : //                              }
     946              : //                      }
     947              : //                      else{
     948              : //                              CollectNeighbors(vNeighbours, grid, vrt);
     949              : //                      }
     950              :                         
     951              : //                      vNodes.resize(vNeighbours.size());
     952              : 
     953              : //                      if(bProjectPointsToPlane){
     954              : //                              for(size_t j = 0; j < vNodes.size(); ++j)
     955              : //                                      ProjectPointToPlane(vNodes[j], aaPos[vNeighbours[j]], v, n);
     956              : //                      }
     957              : //                      else{
     958              : //                              for(size_t j = 0; j < vNodes.size(); ++j)
     959              : //                                      vNodes[j] = aaPos[vNeighbours[j]];
     960              : //                      }
     961              : //              //      perform point relocation
     962              : //                      RelocatePointBySmoothing(aaPos[vrt], v, vNodes, 5, stepSize);
     963              : //              }
     964              : //      }
     965              : // }
     966              : 
     967              : /**     Make sure that elements in gridOut directly correspond to
     968              :  *      elements in gridIn*/
     969              : template <class TGeomObj>
     970              : void CopySelectionStatus(Selector& selOut, Grid& gridOut,
     971              :                                                  Selector& selIn, Grid& gridIn)
     972              : {
     973              :         typedef typename geometry_traits<TGeomObj>::iterator GeomObjIter;
     974              :         GeomObjIter endOut = gridOut.end<TGeomObj>();
     975              :         GeomObjIter endIn = gridIn.end<TGeomObj>();
     976              :         GeomObjIter iterOut = gridOut.begin<TGeomObj>();
     977              :         GeomObjIter iterIn = gridIn.begin<TGeomObj>();
     978              :         
     979              :         for(; (iterOut != endOut) && (iterIn != endIn); ++iterOut, ++iterIn)
     980              :         {
     981              :                 if(selIn.is_selected(*iterIn))
     982              :                         selOut.select(*iterOut);
     983              :         }
     984              : }
     985              : 
     986              : ////////////////////////////////////////////////////////////////////////
     987            0 : bool AdjustEdgeLength(Grid& grid, SubsetHandler& shMarks,
     988              :                                           number minEdgeLen, number maxEdgeLen, int numIterations,
     989              :                                           bool projectPoints, bool adaptive)
     990              : {
     991              :         PROFILE_FUNC();
     992              : 
     993              : //TODO: replace this by a template parameter
     994              :         APosition aPos = aPosition;
     995              : 
     996              : //      we have to make sure that the mesh consist of triangles only,
     997              : //      since the algorithm would produce bad results if not.
     998            0 :         if(grid.num<Quadrilateral>() > 0)
     999              :         {
    1000              :                 UG_LOG("  INFO: grid contains quadrilaterals. Converting to triangles...\n");
    1001              :                                 
    1002              : //TODO: not gridIn but a copy of gridIn (pRefGrid) should be triangulated.
    1003            0 :                 Triangulate(grid, grid.begin<Quadrilateral>(),
    1004            0 :                                         grid.end<Quadrilateral>());
    1005              :         }
    1006              :                 
    1007              : //      make sure that grid and pRefGrid have position-attachments
    1008            0 :         if(!grid.has_vertex_attachment(aPos)){
    1009              :                 UG_LOG("  vertex-position-attachment missing in AdjustEdgeLength. Aborting.\n");
    1010              :                 return false;
    1011              :         }
    1012              :         
    1013              : //      make sure that faces create associated edges
    1014            0 :         if(!grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES))
    1015              :         {
    1016              :                 LOG("  INFO: auto-enabling FACEOPT_AUTOGENERATE_EDGES in AdjustEdgeLength.\n");
    1017            0 :                 grid.enable_options(FACEOPT_AUTOGENERATE_EDGES);
    1018              :         }
    1019              : 
    1020              : //      position attachment
    1021              :         Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPos);
    1022              : 
    1023              : //      we need an integer attachment (a helper for ObtainSimpleGrid)
    1024              :         AInt aInt;
    1025            0 :         grid.attach_to<Vertex>(aInt);
    1026              :         Grid::AttachmentAccessor<Vertex, AInt> aaInt(grid, aInt);
    1027              : 
    1028              : //      TODO: normals shouldn't be created here but instead be passed to the method.
    1029              : //      attach the vertex normals.
    1030              :         ANormal aNorm;
    1031            0 :         grid.attach_to<Vertex>(aNorm);
    1032              :         Grid::AttachmentAccessor<Vertex, ANormal> aaNorm(grid, aNorm);
    1033            0 :         CalculateVertexNormals(grid, aPos, aNorm);
    1034              : 
    1035              : //      assign vertex marks
    1036            0 :         AssignFixedVertices(grid, shMarks);
    1037            0 :         AssignCreaseVertices(grid, shMarks);
    1038              : 
    1039              : //      we need an selector that holds all edges that are candidates for a operation
    1040            0 :         EdgeSelector esel(grid);
    1041            0 :         esel.enable_selection_inheritance(false);
    1042              :         
    1043              : //      sort the triangles of pRefGrid into a octree to speed-up projection performance
    1044              :         SPOctree octree;
    1045            0 :         node_tree::Traverser_ProjectPoint pojectionTraverser;
    1046            0 :         if(projectPoints){
    1047              :                 //PROFILE_BEGIN(octree_construction);
    1048            0 :                 octree = CreateOctree(grid, grid.begin<Triangle>(),
    1049            0 :                                                                         grid.end<Triangle>(),
    1050            0 :                                                                         10, 30, false, aPos);
    1051              : 
    1052              :                 //PROFILE_END();
    1053            0 :                 if(!octree.valid()){
    1054              :                         UG_LOG("  Octree creation failed in AdjustEdgeLength. Aborting.\n");
    1055              :                         return false;
    1056              :                 }
    1057              :         }
    1058              :         
    1059              : //      start the main iteration
    1060            0 :         for(int iteration = 0; iteration < numIterations; ++iteration)
    1061              :         {
    1062              :         //      perform splits
    1063            0 :                 esel.select(grid.begin<Edge>(), grid.end<Edge>());
    1064            0 :                 if(!PerformSplits(grid, shMarks, esel, maxEdgeLen, aaPos, aaNorm, adaptive))
    1065              :                         return false;
    1066              : 
    1067              :         //      perform collapses
    1068            0 :                 esel.select(grid.begin<Edge>(), grid.end<Edge>());
    1069            0 :                 if(!PerformCollapses(grid, shMarks, esel, minEdgeLen, aaPos, aaNorm, aaInt, adaptive))
    1070              :                         return false;
    1071              : 
    1072              :         //      perform swaps
    1073            0 :                 esel.select(grid.begin<Edge>(), grid.end<Edge>());
    1074            0 :                 if(!PerformSwaps(grid, shMarks, esel, aaPos, aaNorm, aaInt))
    1075              :                         return false;
    1076              : 
    1077              : /*
    1078              : //      This is commented out, since it didn't help with the problems encountered
    1079              : //      in the geometries at that time.
    1080              : //      The algorithm however works and may prove useful in the future.
    1081              :         //      fix bad triangles
    1082              :         //      adjacent to crease-edges badly shaped triangles may occur,
    1083              :         //      which have to be treated somehow.
    1084              :                 esel.clear();
    1085              :                 esel.select(shMarks.begin<Edge>(REM_CREASE), shMarks.end<Edge>(REM_CREASE));
    1086              :                 esel.select(shMarks.begin<Edge>(REM_FIXED), shMarks.end<Edge>(REM_FIXED));
    1087              :                 FixBadTriangles(grid, shMarks, esel, aaPos, aaNorm, 0.1);
    1088              : */
    1089              :         //      relocate points
    1090              :                 /*LOG("  smoothing points...");
    1091              :                 PerformSmoothing(grid, shMarks, aaPos, aaNorm, 10, 0.1);
    1092              :                 LOG(" done\n");*/
    1093              : 
    1094              :                 LOG("  updating normals...\n");
    1095            0 :                 CalculateVertexNormals(grid, aPos, aNorm);
    1096              : 
    1097              :         //      project points back on the surface
    1098            0 :                 if(projectPoints)
    1099              :                 {
    1100              :                         LOG("  projecting points...");
    1101              :                         //PROFILE_BEGIN(projecting_points);
    1102              :                         for(VertexIterator iter = grid.vertices_begin();
    1103            0 :                                 iter != grid.vertices_end(); ++iter)
    1104              :                         {
    1105              : //TODO: project crease vertices onto creases only! Don't project fixed vertices
    1106            0 :                                 if(shMarks.get_subset_index(*iter) != REM_FIXED){
    1107              :                                         vector3 vNew;
    1108            0 :                                         if(pojectionTraverser.project(aaPos[*iter], octree/*, &aaNorm[*iter]*/)){
    1109              :                                                 aaPos[*iter] = pojectionTraverser.get_closest_point();
    1110              :                                         }
    1111              :                                         else{
    1112              :                                                 LOG("f");
    1113              :                                         }
    1114              :                                 }
    1115              :                         }
    1116              :                         //PROFILE_END();
    1117              :                         LOG(" done\n");
    1118              :                 }
    1119              : 
    1120            0 :                 if(iteration < numIterations - 1){
    1121              :                         LOG("  updating normals...");
    1122            0 :                         CalculateVertexNormals(grid, aPos, aNorm);
    1123              :                 }
    1124              :         }
    1125              : 
    1126              : 
    1127              : //      detach
    1128              :         grid.detach_from<Vertex>(aInt);
    1129              :         grid.detach_from<Vertex>(aNorm);
    1130              : 
    1131              :         GPLOTSAVE();
    1132              :         return true;
    1133            0 : }
    1134              : 
    1135              : 
    1136              : 
    1137              : 
    1138              : /*
    1139              : ////////////////////////////////////////////////////////////////////////
    1140              : //      This is an alternative version for PerformSplits.
    1141              : //      It uses the Refine method.
    1142              : //      It is not yet optimized for maximum speed.
    1143              : //      While it performs a little less splits, overall runtime of
    1144              : //      AdjustEdgeLength is not better than with the original
    1145              : //      PerformSplits method.
    1146              : template <class TAAPosVRT, class TAANormVRT>
    1147              : bool PerformSplits(Grid& grid, SubsetHandler& shMarks, EdgeSelector& esel,
    1148              :                                           number maxEdgeLen, TAAPosVRT& aaPos, TAANormVRT& aaNorm)
    1149              : {
    1150              :         AInt aInt;
    1151              :         grid.attach_to_edges(aInt);
    1152              : 
    1153              : //      compare squares
    1154              :         maxEdgeLen *= maxEdgeLen;
    1155              : 
    1156              :         Selector sel(grid);
    1157              :         sel.enable_autoselection(true);
    1158              :         sel.select(esel.begin<Edge>(), esel.end<Edge>());
    1159              : 
    1160              :         LOG("  performing splits\n");
    1161              :         int numSplits = 0;
    1162              : 
    1163              :         while(!sel.empty()){
    1164              :         //      deselect all vertices and faces
    1165              :                 sel.clear_selection<Vertex>();
    1166              :                 sel.clear_selection<Face>();
    1167              :                 sel.clear_selection<Volume>();
    1168              : 
    1169              :         //      deselect all edges that shall not be splitted
    1170              :                 EdgeIterator iter = sel.begin<Edge>();
    1171              :                 while(iter != sel.end<Edge>()){
    1172              :                         Edge* e = *iter;
    1173              :                         ++iter;
    1174              : 
    1175              :                 //      the higher the curvature the smaller the maxEdgeLen.
    1176              :                 //      minimal lenFac is 0.1
    1177              :                         number lenFac = CalculateLengthFac(grid, shMarks, e, aaPos);
    1178              : 
    1179              :                 //      fixed edges will not be refined
    1180              :                         if(shMarks.get_subset_index(e) == REM_FIXED)
    1181              :                                 sel.deselect(e);
    1182              :                         else if(VecDistanceSq(aaPos[e->vertex(0)], aaPos[e->vertex(1)]) < lenFac * maxEdgeLen)
    1183              :                                 sel.deselect(e);
    1184              :                 }
    1185              : 
    1186              :         //      refine the grid
    1187              :                 Refine(grid, sel, aInt);
    1188              : 
    1189              :         //      new vertices are selected
    1190              :                 numSplits += sel.num<Vertex>();
    1191              : 
    1192              :         //      re-triangulate
    1193              :                 Triangulate(grid, &aaPos);
    1194              : 
    1195              :         //      calculate normal for new vertices
    1196              : //TODO: be careful with crease edges
    1197              :                 for(VertexIterator iter = sel.begin<Vertex>();
    1198              :                         iter != sel.end<Vertex>(); ++iter)
    1199              :                 {
    1200              :                         CalculateVertexNormal(aaNorm[*iter], grid, *iter, aaPos);
    1201              :                 }
    1202              : 
    1203              :                 sel.clear_selection<Vertex>();
    1204              :                 sel.clear_selection<Face>();
    1205              :                 sel.clear_selection<Volume>();
    1206              :         }
    1207              : 
    1208              :         grid.detach_from_edges(aInt);
    1209              :         LOG("  splits performed: " << numSplits << endl);
    1210              :         return true;
    1211              : }
    1212              : */
    1213              : 
    1214              : }//     end of namespace
        

Generated by: LCOV version 2.0-1