LCOV - code coverage report
Current view: top level - ugbase/lib_grid/algorithms/extrusion - expand_layers_arte.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 755 0
Test Date: 2026-01-06 04:48:21 Functions: 0.0 % 10 0

            Line data    Source code
       1              : /*
       2              :  * expand_layers_arte.cpp
       3              :  *
       4              :  *  Created on: 5.8.2024
       5              :  *      Author: Markus M. Knodel
       6              :   * This file is part of UG4.
       7              :  * 
       8              :  * UG4 is free software: you can redistribute it and/or modify it under the
       9              :  * terms of the GNU Lesser General Public License version 3 (as published by the
      10              :  * Free Software Foundation) with the following additional attribution
      11              :  * requirements (according to LGPL/GPL v3 §7):
      12              :  * 
      13              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      14              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      15              :  * 
      16              :  * (2) The following notice must be displayed at a prominent place in the
      17              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      18              :  * 
      19              :  * (3) The following bibliography is recommended for citation and must be
      20              :  * preserved in all covered files:
      21              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      22              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      23              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      24              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      25              :  *   flexible software system for simulating pde based models on high performance
      26              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      27              :  * 
      28              :  * This program is distributed in the hope that it will be useful,
      29              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      30              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      31              :  * GNU Lesser General Public License for more details.
      32              :  */
      33              : 
      34              : #include <boost/function.hpp>
      35              : 
      36              : #include "expand_layers.h"
      37              : #include "expand_layers_arte.h"
      38              : #include "lib_grid/algorithms/geom_obj_util/geom_obj_util.h"
      39              : #include "lib_grid/callbacks/callbacks.h"
      40              : #include "lib_grid/grid/grid_util.h"
      41              : 
      42              : #include <stack>
      43              : #include <utility>
      44              : #include <vector>
      45              : #include <type_traits>
      46              : #include <limits>
      47              : #include <atomic>
      48              : #include <cstddef>
      49              : #include <bitset>
      50              : #include <string>
      51              : #include <cmath>
      52              : 
      53              : #include "support.h"
      54              : 
      55              : 
      56              : using namespace std;
      57              : 
      58              : namespace ug
      59              : {
      60              : 
      61              : namespace arte
      62              : {
      63              : 
      64              : //using namespace ug::support;
      65              : 
      66              : using VertFracTrip = VertexFractureTriple<Edge*, Face*, vector3>;
      67              : 
      68              : //using VecVertFracTrip = std::vector<VertFracTrip>;
      69              : 
      70              : //using VvftIterator = VecVertFracTrip::iterator;
      71              : 
      72              : using AttVrtVec = Attachment<std::vector<Vertex*> >;
      73              : 
      74              : //using VertexOfFaceInfo = VertexFractureTriple< std::pair<Edge*, Edge*>, Face*, std::pair<vector3,vector3> >;
      75              : //
      76              : //using SegmentsFractExtrus = std::vector<VecVertexOfFaceInfo>;
      77              : 
      78              : using IndexType = unsigned short;
      79              : 
      80              : //using ShiftInfoBasis = std::pair<Edge*, vector3>;
      81              : //
      82              : //using ShiftInfoSegment = std::pair<ShiftInfoBasis,ShiftInfoBasis>;
      83              : 
      84              : //using CrossVertInf = CrossingVertexInfo<Vertex*, IndexType, Edge*, Face* >;
      85              : //using CrossVertInf = CrossingVertexInfo<Vertex*, IndexType, Edge*, ShiftInfoSegment  >;
      86              : using CrossVertInf = CrossingVertexInfo<Vertex*, IndexType >; //, Edge* >;
      87              : 
      88              : 
      89              : 
      90              : 
      91              : // for cases with one fracture and no crossing points
      92              : template <typename ASOF >
      93              : bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo,
      94              :                                                                           Edge * edgeOne, Edge * edgeTwo,
      95              :                                                                           Face * facOne, Face * facTwo,
      96              :                                                                           vector<FractureInfo> const & fracInfosBySubset,
      97              :                                                                           vector3 const & posOldVrt,
      98              :                                                                           Grid::VertexAttachmentAccessor<APosition> & aaPos,
      99              :                                                                           Grid & grid, SubsetHandler & sh,
     100              :                                                                           ASOF const & assoFaces,
     101              :                                                                           std::vector<Vertex *> const & nextFracVrt,
     102              :                                                                           Grid::FaceAttachmentAccessor<AttVrtVec> & aaVrtVecFace,
     103              :                                                                           int & dbg_flachen_passiert,
     104              :                                                                           Vertex * iterV                                                                          )
     105              : {
     106              : 
     107              :         CrossVertInf cvi( nullptr, 0 );
     108              : 
     109              :         return expandSingleFractureAtGivenSide( nOne, nTwo,
     110              :                           edgeOne, edgeTwo,
     111              :                           facOne, facTwo,
     112              :                           fracInfosBySubset,
     113              :                           posOldVrt,
     114              :                           aaPos,
     115              :                           grid, sh,
     116              :                           assoFaces,
     117              :                           nextFracVrt,
     118              :                           aaVrtVecFace,
     119              :                           dbg_flachen_passiert,
     120              :                           iterV,
     121              :                           cvi,
     122              :                           false
     123              :                           );
     124              : }
     125              : 
     126              : // for the case of crossing points
     127              : template <typename ASOF >
     128              : bool expandSingleFractureAtGivenSide( vector3 const & nOne, vector3 const & nTwo,
     129              :                                                                           Edge * edgeOne, Edge * edgeTwo,
     130              :                                                                           Face * facOne, Face * facTwo,
     131              :                                                                           vector<FractureInfo> const & fracInfosBySubset,
     132              :                                                                           vector3 const & posOldVrt,
     133              :                                                                           Grid::VertexAttachmentAccessor<APosition> & aaPos,
     134              :                                                                           Grid & grid, SubsetHandler & sh,
     135              :                                                                           ASOF const & assoFaces,
     136              :                                                                           std::vector<Vertex *> const & nextFracVrt,
     137              :                                                                           Grid::FaceAttachmentAccessor<AttVrtVec> & aaVrtVecFace,
     138              :                                                                           int & dbg_flachen_passiert,
     139              :                                                                           Vertex * iterV,
     140              :                                                                           CrossVertInf & crossVrtInf,
     141              :                                                                           bool insertCrossVrtInf = true
     142              :                                                                           )
     143              : {
     144              : 
     145              : #if 1
     146              :         // gleiche Seite vermutet oder gegeben
     147              : 
     148              :         // average the normals -- das wird wohl der Fehler sein, wenn n1 und n2 nicht fast parallel sind, wenn man davon ausgehend
     149              :         // bestimmt, auf welcher Seite benachbarte Dreiecke liegen, zur Berechnung des Verschiebevektors ist es aber gut
     150              : 
     151              :         vector3 normSum;
     152              : 
     153              :         VecAdd( normSum, nOne, nTwo );
     154              : 
     155              :         vector3 normSumNormed;
     156              : 
     157              :         VecNormalize(normSumNormed, normSum);
     158              : 
     159              :         UG_LOG("averaged normal " << normSumNormed << std::endl);
     160              : 
     161              :         std::vector<Edge * > attEdg;
     162              :         std::vector<Face * > attFac;
     163              : 
     164              :         attEdg.push_back( edgeOne );
     165              :         attEdg.push_back( edgeTwo );
     166              : 
     167              :         attFac.push_back( facOne );
     168              :         attFac.push_back( facTwo );
     169              : 
     170              :         // jetzt neuen Vertex erzeugen in Richtung der Normalen
     171              :         // sonst ist das attachment Schwachsinn!
     172              : 
     173              :         vector3 posNewVrt;
     174              : 
     175              :         vector3 moveVrt;
     176              : 
     177              :         auto subsIndEdgOne = sh.get_subset_index(edgeOne);
     178              : 
     179              :         auto subsIndEdgTwo = sh.get_subset_index(edgeTwo);
     180              : 
     181              :         if( subsIndEdgOne != subsIndEdgTwo )
     182              :         {
     183              :                 UG_THROW("subsets passen nicht Vereinheitlichung" << std::endl );
     184              :         }
     185              : 
     186              :         number width = fracInfosBySubset.at(subsIndEdgOne).width;
     187              : 
     188              :         // FALSCH
     189              :         // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden
     190              :         VecScale(moveVrt, normSumNormed, width/2. );
     191              : 
     192              :         VecAdd(posNewVrt, posOldVrt, moveVrt );
     193              : 
     194              :         UG_LOG("neuer Vertex " << posNewVrt << std::endl );
     195              : 
     196              :         // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex
     197              : 
     198              :         Vertex * newShiftVrtx = *grid.create<RegularVertex>();
     199              :         aaPos[newShiftVrtx] = posNewVrt;
     200              : 
     201              :         sh.assign_subset(newShiftVrtx, subsIndEdgOne );
     202              : 
     203              :         if( insertCrossVrtInf )
     204              :         {
     205              :                 crossVrtInf.addShiftVrtx(newShiftVrtx, true);
     206              :         }
     207              :         // only needed in case of crossing vertices
     208              : 
     209              : 
     210              : 
     211              :         // alle anhängenden faces müssen noch zu wissen bekommen
     212              :         // dass es diesen neuen Vertex gibt, nicht nur die
     213              :         // an den edges anhängenden
     214              :         // vielleicht gibt es einen Loop über attached faces des
     215              :         // Vertex, für die schon bekannten direkt angehängten klar
     216              :         // wenn auch dort vermerkt werden muss im Attachment von Seb
     217              :         // bei den anderen, die keine Edge haben von der Kluft
     218              :         // da muss man die Normale ins Zentrum bestimmen
     219              :         // um heraus zu finden, ob sie auf dieser seite sind
     220              :         // am besten dann das Attachment der faces für vertizes
     221              :         // von Seb recyclen
     222              : 
     223              :         // loop über assosciated faces des vertex am besten
     224              :         // vermutlich auch noch assosciated edges, um
     225              :         // zu markieren, welche weg fallen sollen, wenn
     226              :         // nicht von Kluft selber, sondern quasi verschoben
     227              :         // und neu erzeugt
     228              : 
     229              :         int dbg_FaceIterator = 0;
     230              : 
     231              :         for( auto const & ifac : assoFaces )
     232              :         {
     233              : 
     234              :                 bool isFromFrac = false;
     235              : 
     236              :                 int dbg_innterFacFracIt = 0;
     237              : 
     238              :                 for( auto const & facFrac : attFac )
     239              :                 {
     240              : 
     241              :                         // DEBUG ASSERT TEST static_assert( std::is_same<  decltype( (facFrac) ), decltype ( ifac ) >::value );
     242              : 
     243              :                         if( ifac == facFrac )
     244              :                         {
     245              :                                 isFromFrac = true;
     246              : 
     247              :                                 // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value  );
     248              :                                 // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value  );
     249              : 
     250              :                         }
     251              :                 }
     252              : 
     253              : //              if( ifac == facOne || ifac == facTwo )
     254              : //                      isFromFrac = true;
     255              : 
     256              : //              if( FaceContains(facOne,edgeOne) || FaceContains(facTwo,edgeTwo) )
     257              : //                      isFromFrac = true;
     258              : 
     259              : 
     260              :                 bool atRightSide = false;
     261              : 
     262              :                 if( isFromFrac )
     263              :                         atRightSide = true;
     264              : 
     265              :                 if( !isFromFrac )
     266              :                 {
     267              :                         // check if on same side of edge where the normal points to: compute cosinus between vector of face center
     268              :                         //  perpendicular to the edge
     269              :                         // hier liegt wohl aber ein Fehler vor, wenn die beiden Ecken in einem Winkel zueinander stehen, der nicht fast parallel ist
     270              : 
     271              :                         vector3 facCenter = CalculateCenter( ifac, aaPos );
     272              : 
     273              :                         vector3 perpendicu;
     274              : 
     275              :                         constexpr bool decideSideBasedOnAveragedEdges = false;
     276              : 
     277              :                         if( nextFracVrt.size() != 2 )
     278              :                         {
     279              :                                 UG_THROW("komische Groesse" << std::endl);
     280              :                         }
     281              : 
     282              :                         if( decideSideBasedOnAveragedEdges )
     283              :                         {
     284              :                                 DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]);
     285              : 
     286              :                                 vector3 tmpN;
     287              : 
     288              :                                 VecSubtract(tmpN, facCenter, perpendicu );
     289              : 
     290              :                                 VecNormalize(tmpN, tmpN);
     291              : 
     292              :                                 UG_LOG("Normale zum Face ist " << tmpN << std::endl);
     293              : 
     294              :                                 number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed );
     295              : 
     296              :                                 UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl);
     297              : 
     298              :                                 if( cosBetwFracEdgAndDirection2Face > 0 )
     299              :                                 {
     300              :                                         UG_LOG("assuming face to be on richt side" << std::endl);
     301              : 
     302              :                                         atRightSide = true;
     303              : 
     304              : 
     305              : #if ESTABLISH_DEBUG_SUDOS
     306              : 
     307              :                                         Vertex * otherFacCent = *grid.create<RegularVertex>();
     308              :                                         aaPos[otherFacCent] = facCenter;
     309              :         //                              sh.assign_subset(otherFacCent, 5 );
     310              :                                         sh.assign_subset(otherFacCent, sh.num_subsets() );
     311              : 
     312              :                                         Vertex * pp = *grid.create<RegularVertex>();
     313              :                                         aaPos[pp] = perpendicu;
     314              :                                         sh.assign_subset(pp, sh.num_subsets() );
     315              :         //                              sh.assign_subset(pp, 6 );
     316              : 
     317              :         //                              sh.assign_subset(*iterFac,7);
     318              :                                         sh.assign_subset( *iterFac, sh.num_subsets() );
     319              : #endif
     320              : 
     321              :                                 }
     322              :                                 else
     323              :                                 {
     324              :                                         UG_LOG("assuming face to be on wrong side" << std::endl);
     325              :                                 }
     326              :                         }
     327              :                         else // vielleicht besser so?
     328              :                         {
     329              : 
     330              :                                 // dicide first to which of the edges the center is more close
     331              : 
     332              :                                 vector3 perpendOne, perpendTwo;
     333              : 
     334              :                                 DropAPerpendicular(perpendOne, facCenter, aaPos[edgeOne->vertex(0)], aaPos[edgeOne->vertex(1)] );
     335              :                                 DropAPerpendicular(perpendTwo, facCenter, aaPos[edgeTwo->vertex(0)], aaPos[edgeTwo->vertex(1)] );
     336              : 
     337              :                                 vector3 distOne, distTwo;
     338              : 
     339              :                                 VecSubtract(distOne, facCenter, perpendOne );
     340              :                                 VecSubtract(distOne, facCenter, perpendTwo );
     341              : 
     342              :                                 auto lengthOne = VecLength(distOne);
     343              :                                 auto lengthTwo = VecLength(distTwo);
     344              : 
     345              :                                 // hier umgedreht, bewirkt Verbewwerung, wieso das?
     346              :                                 bool oneSmallerThanTwo = ( lengthOne < lengthTwo );
     347              :                                 // correct assumption?
     348              :                                 //Edge * closerEdge = ( lengthOne > lengthTwo ) ? edgeTwo : edgeOne;
     349              :                                 vector3 distMin = oneSmallerThanTwo ? distTwo : distOne;
     350              :                                 vector3 distNorm;
     351              :                                 VecNormalize(distNorm, distMin);
     352              : 
     353              :                                 UG_LOG("Normale zum Face ist " << distNorm << std::endl);
     354              : 
     355              :                                 vector3 normMin = oneSmallerThanTwo ? nTwo : nOne;
     356              :                                 number cosBetwFracEdgAndDirection2Face = VecDot(distNorm, normMin );
     357              : 
     358              :                                 UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl);
     359              : 
     360              :                                 if( cosBetwFracEdgAndDirection2Face > 0 )
     361              :                                 {
     362              :                                         UG_LOG("assuming face to be on richt side" << std::endl);
     363              : 
     364              :                                         atRightSide = true;
     365              : 
     366              : 
     367              : #if ESTABLISH_DEBUG_SUDOS
     368              : 
     369              :                                         Vertex * otherFacCent = *grid.create<RegularVertex>();
     370              :                                         aaPos[otherFacCent] = facCenter;
     371              :         //                              sh.assign_subset(otherFacCent, 5 );
     372              :                                         sh.assign_subset(otherFacCent, sh.num_subsets() );
     373              : 
     374              :                                         Vertex * pp = *grid.create<RegularVertex>();
     375              :                                         aaPos[pp] = perpendicu;
     376              :                                         sh.assign_subset(pp, sh.num_subsets() );
     377              :         //                              sh.assign_subset(pp, 6 );
     378              : 
     379              :         //                              sh.assign_subset(*iterFac,7);
     380              :                                         sh.assign_subset( *iterFac, sh.num_subsets() );
     381              : #endif
     382              :                                 }
     383              : 
     384              :                         }
     385              : 
     386              :                         dbg_flachen_passiert++;
     387              :                 }
     388              : 
     389              :                 if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein
     390              :                 {
     391              : 
     392              :                         // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden!
     393              :                         vector<Vertex*>& newVrts4Fac = aaVrtVecFace[ ifac ];
     394              : 
     395              :                         IndexType vrtxFnd = 0;
     396              : 
     397              :                         for(size_t indVrt = 0; indVrt < (ifac)->num_vertices();  indVrt++ )
     398              :                         {
     399              :                                 Vertex* facVrt = (ifac)->vertex(indVrt);
     400              : 
     401              :                                 if(  facVrt == iterV )
     402              :                                 {
     403              :                                         newVrts4Fac[ indVrt ] = newShiftVrtx;
     404              :                                         vrtxFnd++;
     405              :                                 }
     406              :                         }
     407              : 
     408              : //                      if( insertCrossVrtInf )
     409              : //                      {
     410              : ////                            crossVrtInf.setShiftVrtx(newVrts4Fac);
     411              : //                              crossVrtInf.addShiftVrtx(newVrts4Fac, true);
     412              : //                      }
     413              : //                      // only needed in case of crossing vertices
     414              : 
     415              :                         if( vrtxFnd <= 0 )
     416              :                         {
     417              :                                 UG_THROW("vertex not found!" << std::endl);
     418              :                                                                                                 }
     419              :                         else if( vrtxFnd > 1 )
     420              :                         {
     421              :                                 UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl );
     422              :                         }
     423              :                         else if ( vrtxFnd == 1 )
     424              :                         {
     425              :                         }
     426              :                         else
     427              :                         {
     428              :                                 UG_THROW("vertex finden komisch " << std::endl);
     429              :                         }
     430              : 
     431              : 
     432              :                 }
     433              : 
     434              :                 dbg_innterFacFracIt++;
     435              : 
     436              : 
     437              : 
     438              :                 dbg_FaceIterator++;
     439              : 
     440              :         }
     441              : #endif
     442              : 
     443              :         return true;
     444              : 
     445              : }
     446              : 
     447              : #if 0
     448              : void createShiftVertexPassingClefts( vector3 const & nOne, vector3 const nTwo, Vertex * & newShiftVrtx, SubsetHandler & sh,
     449              :                 vector3 const & posOldVrt, bool subsEqual = true )
     450              : {
     451              : 
     452              :         auto subsIndEdgOne = sh.get_subset_index(edgeOne);
     453              : 
     454              :         auto subsIndEdgTwo = sh.get_subset_index(edgeTwo);
     455              : 
     456              :         if( subsIndEdgOne != subsIndEdgTwo && subsEqual )
     457              :         {
     458              :                 UG_THROW("subsets passen nicht Vereinheitlichung" << std::endl );
     459              :         }
     460              : 
     461              :         vector3 moveVrt;
     462              : 
     463              :         number cosinus = VecDot(nOne,nTwo);
     464              : 
     465              :         number pi = 3.1415926535897932385;
     466              : 
     467              :         number cosinusLim = std::cos( pi/8. );
     468              : 
     469              :         if( cosinus > cosinusLim )
     470              :         {
     471              :                 vector3 normSum;
     472              : 
     473              :                 VecAdd( normSum, nOne, nTwo );
     474              : 
     475              :                 vector3 normSumNormed;
     476              : 
     477              :                 VecNormalize(normSumNormed, normSum);
     478              : 
     479              :                 UG_LOG("averaged normal " << normSumNormed << std::endl);
     480              : 
     481              :                 std::vector<Edge * > attEdg;
     482              :                 std::vector<Face * > attFac;
     483              : 
     484              :                 attEdg.push_back( edgeOne );
     485              :                 attEdg.push_back( edgeTwo );
     486              : 
     487              :                 attFac.push_back( facOne );
     488              :                 attFac.push_back( facTwo );
     489              : 
     490              :                 // jetzt neuen Vertex erzeugen in Richtung der Normalen
     491              :                 // sonst ist das attachment Schwachsinn!
     492              : 
     493              :                 number widthOne = fracInfosBySubset.at(subsIndEdgOne).width;
     494              :                 number widthTwo = fracInfosBySubset.at(subsIndEdgTwo).width;
     495              : 
     496              :                 number width = ( widthOne + widthTwo ) /2.;
     497              : 
     498              :                 // FALSCH
     499              :                 // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden
     500              :                 VecScale(moveVrt, normSumNormed, width/2. );
     501              : 
     502              :         }
     503              :         else // abknickende Fractures
     504              :         {
     505              : 
     506              :         }
     507              : 
     508              :         vector3 posNewVrt;
     509              : 
     510              :         VecAdd(posNewVrt, posOldVrt, moveVrt );
     511              : 
     512              :         UG_LOG("neuer Vertex " << posNewVrt << std::endl );
     513              : 
     514              :         // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex
     515              : 
     516              :         newShiftVrtx = *grid.create<RegularVertex>();
     517              :         aaPos[newShiftVrtx] = posNewVrt;
     518              : 
     519              :         sh.assign_subset(newShiftVrtx, subsIndEdgOne );
     520              : }
     521              : #endif
     522              : 
     523              : using VecVertFracTrip = std::vector<VertFracTrip>;
     524              : 
     525              : // needed for crossing points
     526              : using VertexOfFaceInfo = VertexFractureTriple< std::pair<Edge*, Edge*>, Face*, std::pair<vector3,vector3> >;
     527              : // all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges
     528              : // the size of the normal vector vector also must be two
     529              : // however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm
     530              : // for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple
     531              : 
     532              : using VecVertexOfFaceInfo = std::vector<VertexOfFaceInfo>;
     533              : 
     534              : using SegmentsFractExtrus = std::vector<VecVertexOfFaceInfo>;
     535              : 
     536              : 
     537              : 
     538              : 
     539              : template <>
     540              : // for the case of crossing points
     541            0 : bool expandSingleFractureAtGivenSide<VecVertexOfFaceInfo>
     542              :                                                                         ( vector3 const & nOne, vector3 const & nTwo,
     543              :                                                                           Edge * edgeOne, Edge * edgeTwo,
     544              :                                                                           Face * facOne, Face * facTwo,
     545              :                                                                           vector<FractureInfo> const & fracInfosBySubset,
     546              :                                                                           vector3 const & posOldVrt,
     547              :                                                                           Grid::VertexAttachmentAccessor<APosition> & aaPos,
     548              :                                                                           Grid & grid, SubsetHandler & sh,
     549              :                                                                           VecVertexOfFaceInfo const & segPart,
     550              :                                                                           std::vector<Vertex *> const & nextFracVrt,
     551              :                                                                           Grid::FaceAttachmentAccessor<AttVrtVec> & aaVrtVecFace,
     552              :                                                                           int & dbg_flachen_passiert,
     553              :                                                                           Vertex * crossPt,
     554              :                                                                           CrossVertInf & crossVrtInf,
     555              :                                                                           bool insertCrossVrtInf
     556              :                                                                           )
     557              : //
     558              : //                                                                      ( vector3 const & nOne, vector3 const & nTwo,
     559              : //                                                                        Edge * edgeOne, Edge * edgeTwo,
     560              : //                                                                        Face * facOne, Face * facTwo,
     561              : //                                                                        vector<FractureInfo> const & fracInfosBySubset,
     562              : //                                                                        vector3 const & posOldVrt,
     563              : //                                                                        Grid::VertexAttachmentAccessor<APosition> & aaPos,
     564              : //                                                                        Grid & grid, SubsetHandler & sh,
     565              : //                                                                        VecVertexOfFaceInfo const & segPart,
     566              : //                                                                        std::vector<Vertex *> const & nextFracVrt,
     567              : //                                                                        Grid::FaceAttachmentAccessor<AttVrtVec> & aaVrtVecFace,
     568              : //                                                                        int & dbg_flachen_passiert,
     569              : //                                                                        Vertex const * & crossPt,
     570              : //                                                                        CrossVertInf & crossVrtInf,
     571              : //                                                                        bool insertCrossVrtInf // = true
     572              : //                                                                        )
     573              : {
     574              : 
     575              :         // gleiche Seite gegeben
     576              : 
     577              :         // average the normals -- das wird wohl der Fehler sein, wenn n1 und n2 nicht fast parallel sind, wenn man davon ausgehend
     578              :         // bestimmt, auf welcher Seite benachbarte Dreiecke liegen, zur Berechnung des Verschiebevektors ist es aber gut
     579              : 
     580              :         // TODO FIXME fuer grossere Winkel die Methode von XCross Projektionen übernehmen!!!
     581              : 
     582              :         vector3 normSum;
     583              : 
     584              :         VecAdd( normSum, nOne, nTwo );
     585              : 
     586              :         vector3 normSumNormed;
     587              : 
     588            0 :         VecNormalize(normSumNormed, normSum);
     589              : 
     590            0 :         UG_LOG("averaged normal " << normSumNormed << std::endl);
     591              : 
     592              :         std::vector<Edge * > attEdg;
     593              :         std::vector<Face * > attFac;
     594              : 
     595            0 :         attEdg.push_back( edgeOne );
     596            0 :         attEdg.push_back( edgeTwo );
     597              : 
     598            0 :         attFac.push_back( facOne );
     599            0 :         attFac.push_back( facTwo );
     600              : 
     601              :         // jetzt neuen Vertex erzeugen in Richtung der Normalen
     602              :         // sonst ist das attachment Schwachsinn!
     603              : 
     604              :         vector3 posNewVrt;
     605              : 
     606              :         vector3 moveVrt;
     607              : 
     608            0 :         auto subsIndEdgOne = sh.get_subset_index(edgeOne);
     609              : 
     610            0 :         auto subsIndEdgTwo = sh.get_subset_index(edgeTwo);
     611              : 
     612            0 :         if( subsIndEdgOne != subsIndEdgTwo )
     613              :         {
     614            0 :                 UG_THROW("subsets passen nicht Vereinheitlichung" << std::endl );
     615              :         }
     616              : 
     617            0 :         number width = fracInfosBySubset.at(subsIndEdgOne).width;
     618              : 
     619              :         // FALSCH
     620              :         // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden
     621            0 :         VecScale(moveVrt, normSumNormed, width/2. );
     622              : 
     623              :         VecAdd(posNewVrt, posOldVrt, moveVrt );
     624              : 
     625            0 :         UG_LOG("neuer Vertex " << posNewVrt << std::endl );
     626              : 
     627              :         // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex
     628              : 
     629            0 :         Vertex * newShiftVrtx = *grid.create<RegularVertex>();
     630              :         aaPos[newShiftVrtx] = posNewVrt;
     631              : 
     632            0 :         sh.assign_subset(newShiftVrtx, subsIndEdgOne );
     633              : 
     634            0 :         if( insertCrossVrtInf )
     635              :         {
     636            0 :                 crossVrtInf.addShiftVrtx(newShiftVrtx, true);
     637              :         }
     638              :         // only needed in case of crossing vertices
     639              : 
     640              : 
     641              : 
     642              :         // alle anhängenden faces müssen noch zu wissen bekommen
     643              :         // dass es diesen neuen Vertex gibt, nicht nur die
     644              :         // an den edges anhängenden
     645              :         // vielleicht gibt es einen Loop über attached faces des
     646              :         // Vertex, für die schon bekannten direkt angehängten klar
     647              :         // wenn auch dort vermerkt werden muss im Attachment von Seb
     648              :         // bei den anderen, die keine Edge haben von der Kluft
     649              :         // da muss man die Normale ins Zentrum bestimmen
     650              :         // um heraus zu finden, ob sie auf dieser seite sind
     651              :         // am besten dann das Attachment der faces für vertizes
     652              :         // von Seb recyclen
     653              : 
     654              :         // loop über assosciated faces des vertex am besten
     655              :         // vermutlich auch noch assosciated edges, um
     656              :         // zu markieren, welche weg fallen sollen, wenn
     657              :         // nicht von Kluft selber, sondern quasi verschoben
     658              :         // und neu erzeugt
     659              : 
     660              :         // TODO FIXME in eigene Funktion stecken, taucht exakt gleich bei XCross auf am Ende!
     661              : 
     662            0 :         for( VertexOfFaceInfo const & vertFracInfoSeg : segPart )
     663              :         {
     664              :                 Face * fac = vertFracInfoSeg.getFace();
     665              : 
     666              : //                                              sh.assign_subset(fa,newSubsToAdd);
     667              : 
     668              : 
     669              :                 // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden!
     670              :                 vector<Vertex*>& newVrts4Fac = aaVrtVecFace[ fac ];
     671              : 
     672              :                 IndexType vrtxFnd = 0;
     673              : 
     674            0 :                 for(size_t indVrt = 0; indVrt < (fac)->num_vertices();  indVrt++ )
     675              :                 {
     676            0 :                         Vertex* facVrt = (fac)->vertex(indVrt);
     677              : 
     678            0 :                         if(  facVrt == crossPt )
     679              :                         {
     680            0 :                                 newVrts4Fac[ indVrt ] = newShiftVrtx;
     681            0 :                                 vrtxFnd++;
     682              : 
     683              : 
     684              :                         }
     685              :                 }
     686              : 
     687            0 :                 if( vrtxFnd <= 0 )
     688              :                 {
     689            0 :                         UG_THROW("vertex not found !" << std::endl);
     690              :                                                                                         }
     691            0 :                 else if( vrtxFnd > 1 )
     692              :                 {
     693            0 :                         UG_THROW("vertex zu oft gefunden  " << vrtxFnd << std::endl );
     694              :                 }
     695              :                 else if ( vrtxFnd == 1 )
     696              :                 {
     697              :                 }
     698              :                 else
     699              :                 {
     700              :                         UG_THROW("vertex finden komisch  " << std::endl);
     701              :                 }
     702              : 
     703              :         }
     704              : 
     705            0 :         return true;
     706              : 
     707            0 : }
     708              : 
     709              : 
     710              : template <>
     711              : // for cases with one fracture and no crossing points
     712            0 : bool expandSingleFractureAtGivenSide<VecVertexOfFaceInfo>
     713              :                                                                         ( vector3 const & nOne, vector3 const & nTwo,
     714              :                                                                           Edge * edgeOne, Edge * edgeTwo,
     715              :                                                                           Face * facOne, Face * facTwo,
     716              :                                                                           vector<FractureInfo> const & fracInfosBySubset,
     717              :                                                                           vector3 const & posOldVrt,
     718              :                                                                           Grid::VertexAttachmentAccessor<APosition> & aaPos,
     719              :                                                                           Grid & grid, SubsetHandler & sh,
     720              :                                                                           VecVertexOfFaceInfo const & segPart,
     721              :                                                                           std::vector<Vertex *> const & nextFracVrt,
     722              :                                                                           Grid::FaceAttachmentAccessor<AttVrtVec> & aaVrtVecFace,
     723              :                                                                           int & dbg_flachen_passiert,
     724              :                                                                           Vertex * iterV
     725              :                                                                           )
     726              : {
     727              : 
     728            0 :         CrossVertInf cvi( nullptr, 0 );
     729              : 
     730            0 :         return expandSingleFractureAtGivenSide( nOne, nTwo,
     731              :                           edgeOne, edgeTwo,
     732              :                           facOne, facTwo,
     733              :                           fracInfosBySubset,
     734              :                           posOldVrt,
     735              :                           aaPos,
     736              :                           grid, sh,
     737              :                           segPart,
     738              :                           nextFracVrt,
     739              :                           aaVrtVecFace,
     740              :                           dbg_flachen_passiert,
     741              :                           iterV,
     742              :                           cvi,
     743              :                           false
     744            0 :                           );
     745              : }
     746              : 
     747              : 
     748              : using VecEdge = std::vector<Edge*>;
     749              : using VecFace = std::vector<Face*>;
     750              : 
     751              : using ExpandCrossFracInfo = VertexFractureTriple< std::pair<Edge*, Edge*>, Face*, std::pair<Vertex*, Vertex*> >;
     752              : // Vertex nullptr wo original fracture, und shift vertex, wo Keilecke, die weg soll - Fall X Cross
     753              : 
     754              : using VecExpandCrossFracInfo = std::vector<ExpandCrossFracInfo>;
     755              : 
     756              : // leider erst ab 17er Standard möglich
     757              : //template <typename VRTCOMB >
     758              : //template < typename SHIVET > distinguish shiftVrtcs for TEnd and XCross, using static conxtexpr for isXCross in calling
     759              : // TODO FIXME change once std 17 available in UG4
     760            0 : bool SortFaces4DiamondCreation( SubsetHandler& sh, std::vector<Face *> & assoFacCrossCop, Edge * & firstEdgeFac, Edge * & secondEdgeFac,
     761              :                 Face * & assoFacConsider, VecEdge const & origFracEdg,
     762              :                 std::vector<Vertex * > const & shiftVrtcs,
     763              : //              std::vector<VRTCOMB > const & shiftVrtcs,
     764              :                 Vertex * const & crossPt, Edge * & assoFacEdgBeg2Fix, Edge * & assoFacEdgEnd2Fix, Grid& grid,
     765              :                 VecExpandCrossFracInfo & vecExpCrossFI,
     766              :                 bool isXCross = true // if false, then isTEnd, no other possibility
     767              :                 )
     768              : {
     769              : 
     770              :         // done noch die Abweichungen für den TEnd Fall einbauen
     771              : 
     772              :         bool atStartSort = true;
     773              : 
     774              :         bool boundAtShiftVrtEdg = isXCross; // false in case of TEnd at beginning
     775              : 
     776              : //                      auto shiftVrtcsCop = shiftVrtcs;
     777              : 
     778              : //                      UG_LOG("starting Rundlauf " << std::endl);
     779              : 
     780              :         IndexType dbg_rndl = 0;
     781              : 
     782            0 :         while( assoFacCrossCop.size() != 0 )
     783              :         {
     784              :                 //                              UG_LOG("Debug Rundlauf " << dbg_rndl << std::endl);
     785              : 
     786              :                 dbg_rndl++;
     787              : 
     788              :                 // Original X Cross ganz einfach
     789              : //              secondEdgeFac = nullptr;
     790              : 
     791              :                 // stattdessen bei T End
     792              : //              if( ! atStartSort )
     793              : //              {
     794              : //                      secondEdgeFac = nullptr;
     795              : //              }
     796              : 
     797              : //               zusammengefasst, hoffentlich richtig so:
     798            0 :                 if( isXCross || ( ! isXCross && ! atStartSort )  )
     799            0 :                         secondEdgeFac = nullptr;
     800              : 
     801              :                 // leider erst ab std 17, zu cool für älteren Standard
     802              : //              constexpr bool isXCross = std::is_same<Vertex*, VRTCOMB >::value;
     803              : //
     804              : //
     805              : //              if constexpr ( std::is_same<Vertex*, VRTCOMB >::value )
     806              : //              {
     807              : //                      secondEdgeFac = nullptr;
     808              : //              }
     809              : //
     810              : //              if constexpr ( std::is_same< VRTCOMB, std::pair<Vertex*, bool > )
     811              : //              {
     812              : //                      if( ! atStartSort )
     813              : //                              secondEdgeFac = nullptr;
     814              : //              }
     815              : 
     816              : 
     817              :                 Edge * fracEdge = nullptr;
     818              :                 Edge * shiftVrtxEdg = nullptr;
     819              : 
     820              :                 //                              IndexType fndEdgEnd = 0;
     821              : 
     822              :                 std::vector<Edge*> edgesThisFac;
     823              : 
     824              :                 edgesThisFac.clear();
     825              : 
     826              :                 //                              IndexType eoeo = edgesThisFac.size();
     827              :                 //
     828              :                 //                              auto eiei = eoeo;
     829              : 
     830              :                 //                              UG_LOG("Edges this fac Orig Orig " << eiei <<  " " << dbg_rndl << std::endl);
     831              : 
     832              : 
     833              :                 //                              UG_LOG("Debug Ecken " << std::endl);
     834              : 
     835              :                 IndexType dbg_itEd = 0;
     836              : 
     837            0 :                 for( std::vector<Edge *>::iterator iterEdgF = grid.associated_edges_begin(assoFacConsider);
     838            0 :                                 iterEdgF != grid.associated_edges_end(assoFacConsider); iterEdgF++ )
     839              :                 {
     840            0 :                         edgesThisFac.push_back(*iterEdgF);
     841              : 
     842              :                 //                                      UG_LOG("und noch eines dazu " << dbg_itEd << " " << dbg_rndl << std::endl);
     843              : 
     844              :                                                         //IndexType sudos = sh.num_subsets();
     845              : 
     846              :                                                         //sh.assign_subset(*iterEdgF,sudos);
     847              :                 }
     848              : 
     849              :                 //                              IndexType effsOrig = edgesThisFac.size();
     850              : 
     851              :                 //                              auto efeu = effsOrig;
     852              : 
     853              :                 //                              UG_LOG("Edges this fac Orig " << efeu <<  dbg_rndl << std::endl);
     854              : 
     855              : 
     856              :                                                 // figure out original fracture edge
     857              : 
     858              :                 IndexType fndFracEdg = 0;
     859              : 
     860            0 :                 for( auto const & etf : edgesThisFac )
     861              :                 {
     862            0 :                         for( auto const & ofe : origFracEdg )
     863              :                         {
     864            0 :                                 if( etf == ofe )
     865              :                                 {
     866            0 :                                         fndFracEdg++;
     867              :                                         fracEdge = etf;
     868              :                                 }
     869              :                         }
     870              :                 }
     871              : 
     872              :                 //                              UG_LOG("Debug Ofen  " << std::endl);
     873              : 
     874            0 :                 if( fracEdge == nullptr || fndFracEdg != 1 )
     875              :                 {
     876              :                         UG_LOG("Frac Orig Ecke nicht gefunden oder falsche Zahl " << fndFracEdg << " " << isXCross << std::endl );
     877              :                 //                                      return false;
     878            0 :                         UG_THROW("Frac Orig Ecke nicht gefunden oder falsche Zahl " << fndFracEdg << " " << isXCross << std::endl );
     879              :                 }
     880              : 
     881              : 
     882              :                                                 // find expanded shift vertex
     883              : 
     884              :                 Vertex * shiftVrtxFound = nullptr;
     885              :                 IndexType fndVrt = 0;
     886              : 
     887              :                 //                              IndexType suse = sh.num_subsets();
     888              : 
     889              :                                                 //sh.assign_subset(crossPt,suse);
     890              : 
     891              :                 //                              for( auto & sv : shiftVrtcsCop )
     892              :                 //                              {
     893              :                 //                                      IndexType suseV = sh.num_subsets();
     894              :                 //                                      //sh.assign_subset(sv,suseV);
     895              :                 //                              }
     896              : 
     897              :                 //                              return true;
     898              : 
     899              :                 //                              UG_LOG("Debug Entfernene    " << std::endl);
     900              : 
     901              :                 IndexType dbg_edgnum = 0;
     902              : 
     903              :                 IndexType helpVarEdges = 0;
     904              : 
     905              :                 //                              IndexType effs = edgesThisFac.size();
     906              :                 //                              IndexType shiffs = shiftVrtcs.size();
     907              : 
     908              :                 //                              UG_LOG("Edges this fac " <<  effs <<  dbg_rndl << std::endl);
     909              :                 //                              UG_LOG("Shift Vectors " <<  shiffs <<  dbg_rndl << std::endl);
     910              : 
     911              : 
     912            0 :                 for( auto const & etf : edgesThisFac )
     913              :                 {
     914              : 
     915            0 :                         if( helpVarEdges >= edgesThisFac.size() )
     916              :                         {
     917              :                                 UG_LOG("Indexueberschreitung Edges" << " " << isXCross <<  std::endl);
     918              :                                 break;
     919              :                         }
     920              : 
     921            0 :                         helpVarEdges++;
     922              : 
     923              :                         dbg_edgnum++;
     924              : 
     925              :                         IndexType helpShiVaNum = 0;
     926              : 
     927              :                         IndexType dbg_shiVe = 0;
     928              : 
     929              :                 //                                      for( Vertex * const & sv : shiftVrtcs )
     930            0 :                         for( auto const & sv : shiftVrtcs )
     931              :                         {
     932              : 
     933            0 :                                 if( helpShiVaNum >= shiftVrtcs.size() )
     934              :                                 {
     935              :                                         UG_LOG("Shift Vertex Index Verletzung " << " " << isXCross << std::endl);
     936              :                                         break;
     937              :                                 }
     938              : 
     939            0 :                                 helpShiVaNum++;
     940              : 
     941              :                                 dbg_shiVe++;
     942              : 
     943            0 :                                 if( EdgeContains(etf, crossPt ) && EdgeContains( etf, sv ) )
     944              :                                 {
     945            0 :                                         shiftVrtxFound = sv;
     946            0 :                                         fndVrt++;
     947            0 :                                         shiftVrtxEdg = etf;
     948              : 
     949              : //                                      UG_LOG("Shift Vertex " << aaPos[shiftVrtxFound] << " " << dbg_edgnum << " " << dbg_shiVe << " " << dbg_rndl << std::endl);
     950              : //                                      UG_LOG("Cross Vertex " << aaPos[crossPt] << " " << dbg_edgnum << " " << dbg_shiVe <<  " " << dbg_rndl <<  std::endl );
     951              : //
     952              : //                                      UG_LOG("dbg edgenu shive " << dbg_edgnum << " " << dbg_shiVe <<  " " << dbg_rndl <<  std::endl);
     953              : 
     954              : //                                      isAtFreeSideShiVe = svwi.second;
     955              :                                 }
     956              : 
     957              : 
     958              : //                              for( IndexType i = 0; i < 2; i++ )
     959              : //                              {
     960              : //
     961              : //                                      // done ersetzen durch ElementContains Funktion
     962              : //              //                                                      if( ( etf->vertex(i) == crossPt && etf->vertex((i+1)%2) == sv )  || (etf->vertex((i+1)%2) == crossPt && etf->vertex(i) == sv ))
     963              : //                                      if( etf->vertex(i) == crossPt && etf->vertex((i+1)%2) == sv )
     964              : //                                      {
     965              : //                                              shiftVrtxFound = sv;
     966              : //                                              fndVrt++;
     967              : //                                              shiftVrtxEdg = etf;
     968              : //
     969              : //              //                                                              UG_LOG("Shift Vertex " << aaPos[shiftVrtxFound] << " " << dbg_edgnum << " " << dbg_shiVe << " " << dbg_rndl << std::endl);
     970              : //              //                                                              UG_LOG("Cross Vertex " << aaPos[crossPt] << " " << dbg_edgnum << " " << dbg_shiVe <<  " " << dbg_rndl <<  std::endl );
     971              : //              //
     972              : //              //                                                              UG_LOG("dbg edgenu shive " << dbg_edgnum << " " << dbg_shiVe <<  " " << dbg_rndl <<  std::endl);
     973              : //                                      }
     974              : //                              }
     975              :                         }
     976              :                 }
     977              : 
     978              :                 //                              UG_LOG("Debug Entfert durch         " << std::endl);
     979              : 
     980              : 
     981            0 :                 if( fndVrt != 1 || shiftVrtxFound == nullptr || shiftVrtxEdg == nullptr )
     982              :                 {
     983              :                         UG_LOG("shift vertex komische Zahl oder null " << fndVrt << " " << isXCross << std::endl);
     984              :                 //                                      return false;
     985            0 :                         UG_THROW("shift vertex komische Zahl oder null " << fndVrt << " " << isXCross << std::endl);
     986              :                 }
     987              : 
     988              :                 //                              UG_LOG("Debug Entfert Text durch    " << std::endl);
     989              : 
     990              : 
     991              :                 //                              for( std::vector<Vertex*>::iterator itV = shiftVrtcsCop.begin(); itV != shiftVrtcsCop.end(); itV++ )
     992              :                 //                              {
     993              :                 //                                      Vertex * vrt = *itV;
     994              :                 //
     995              :                 //                                      if( vrt == shiftVrtxFound )
     996              :                 //                                      {
     997              :                 //                                              shiftVrtcsCop.erase(itV);
     998              :                 //                                              break;
     999              :                 //                                      }
    1000              :                 //                              }
    1001              :                 //
    1002              :                 //                              UG_LOG("Debug Rasieren durch        " << std::endl);
    1003              : 
    1004              : 
    1005              : //              if( atStartSort && isXCross )
    1006              : //              {
    1007              : //                      assoFacEdgBeg2Fix = fracEdge;
    1008              : //              }
    1009              : //
    1010              : //              if( atStartSort && ! isXCross )
    1011              : //              {
    1012              : //                      assoFacEdgBeg2Fix = fracEdge;
    1013              : //                      atStartSort = false;
    1014              : //              }
    1015              : 
    1016              : 
    1017            0 :                 if( atStartSort )
    1018              :                 {
    1019            0 :                         if( isXCross )
    1020              :                         {
    1021            0 :                                 assoFacEdgBeg2Fix = fracEdge;
    1022              :                         }
    1023              :                         else
    1024              :                         {
    1025            0 :                                 if( fracEdge != secondEdgeFac || shiftVrtxEdg != firstEdgeFac || assoFacEdgBeg2Fix != shiftVrtxEdg )
    1026            0 :                                         UG_THROW("ALler Anfang ist schwer TEnd " << std::endl);
    1027              :                         }
    1028              : 
    1029              :                         atStartSort = false;
    1030              :                 }
    1031              : 
    1032              : 
    1033              : 
    1034              :                 //                              Edge * firstEdgeFac = fracEdge;
    1035              :                 //                              Edge * secondEdgeFac = shiftEdge;
    1036            0 :                 firstEdgeFac = fracEdge;
    1037            0 :                 secondEdgeFac = shiftVrtxEdg;
    1038              : 
    1039              : 
    1040              :                 Vertex * firstVrt = nullptr;
    1041              :                 Vertex * secondVrt = shiftVrtxFound;
    1042              : 
    1043            0 :                 if( !boundAtShiftVrtEdg )
    1044              :                 {
    1045            0 :                         firstEdgeFac = shiftVrtxEdg;
    1046            0 :                         secondEdgeFac = fracEdge;
    1047              : 
    1048              :                         firstVrt = shiftVrtxFound;
    1049              :                         secondVrt = nullptr;
    1050              :                 }
    1051              : 
    1052              :                 //                              UG_LOG("Debug Paarbildung   " << std::endl);
    1053              : 
    1054              : 
    1055              :                 std::pair<Edge*, Edge*> edgesFac( firstEdgeFac, secondEdgeFac );
    1056              : 
    1057              :                 std::pair<Vertex*,Vertex*> vrtcsSF( firstVrt, secondVrt );
    1058              : 
    1059              :                 ExpandCrossFracInfo startFacInf( edgesFac, assoFacConsider, vrtcsSF );
    1060              : 
    1061            0 :                 vecExpCrossFI.push_back(startFacInf);
    1062              : 
    1063              : //              if( !isXCross )
    1064              : //              {
    1065              : //                      IndexType sui = sh.num_subsets();
    1066              : //
    1067              : //                      sh.assign_subset(assoFacConsider,sui);
    1068              : //              }
    1069              : 
    1070              :                 //                              UG_LOG("Debug Paarbildung  Rasieren " << std::endl);
    1071              : 
    1072              :                 IndexType dbg_it_er = 0;
    1073              : 
    1074            0 :                 for( std::vector<Face*>::iterator itFac = assoFacCrossCop.begin(); itFac != assoFacCrossCop.end(); itFac++ )
    1075              :                 {
    1076            0 :                         Face * iFa = *itFac;
    1077              : 
    1078              :                 //                                      UG_LOG("interieren " << dbg_it_er << std::endl );
    1079              : 
    1080              :                         dbg_it_er++;
    1081              : 
    1082              :                 //                                      UG_LOG("ifa " << iFa << std::endl );
    1083              :                 //                                      UG_LOG("assoFac " << assoFacConsider << std::endl );
    1084              : 
    1085              :                 //                                      bool enthaltung = FaceContains( iFa, firstEdgeFac );
    1086              :                 //
    1087              :                 ////                                    UG_LOG("Enthaltung " << std::endl);
    1088              :                 //
    1089              :                 //                                      bool entzwei = FaceContains(iFa, secondEdgeFac);
    1090              :                 //
    1091              :                 ////                                    UG_LOG("Entzweiung " << std::endl);
    1092              : 
    1093              : 
    1094            0 :                         if( iFa == assoFacConsider && FaceContains( iFa, firstEdgeFac ) && FaceContains(iFa, secondEdgeFac) )
    1095              :                         {
    1096              :                 //                                              UG_LOG("Erasieren " << std::endl);
    1097              :                                 assoFacCrossCop.erase(itFac);
    1098            0 :                                 break;
    1099              :                         }
    1100              :                 }
    1101              : 
    1102              :                 //                              UG_LOG("Debug Paarbildung  Rasieren durch " << std::endl);
    1103              : 
    1104              : 
    1105            0 :                 if( assoFacCrossCop.size() == 0 )
    1106              :                 {
    1107            0 :                         if( secondEdgeFac != assoFacEdgBeg2Fix )
    1108              :                         {
    1109              :                                 UG_LOG("Gesichter Diamant leer, aber keine Anfangsecke gefunden" << " " << isXCross << std::endl);
    1110              :                                 //return true;
    1111            0 :                                 UG_THROW("Gesichter Diamant leer, aber keine Anfangsecke gefunden" << " " << isXCross << std::endl);
    1112              :                         }
    1113              :                         else
    1114              :                         {
    1115            0 :                                 assoFacEdgEnd2Fix = secondEdgeFac;
    1116              : 
    1117              :                                 break; // while loop zu Ende, raus aus dem while loop, den Rest nicht mehr machen, würde schief gehen zwingendermassen
    1118              :                         }
    1119              : 
    1120              :                 }
    1121              : 
    1122              :                                                 // figure out the next face
    1123              : 
    1124            0 :                 firstEdgeFac = secondEdgeFac;
    1125            0 :                 secondEdgeFac = nullptr;
    1126              : 
    1127              :                 IndexType nextFaceFound = 0;
    1128              : 
    1129            0 :                 for( std::vector<Face*>::iterator itFac = assoFacCrossCop.begin(); itFac != assoFacCrossCop.end(); itFac++ )
    1130              :                 {
    1131            0 :                         Face * iFa = *itFac;
    1132              : 
    1133            0 :                         if( FaceContains(iFa, firstEdgeFac ) )
    1134              :                         {
    1135            0 :                                 nextFaceFound++;
    1136              :                         }
    1137              :                 }
    1138              : 
    1139            0 :                 if( nextFaceFound != 1 )
    1140              :                 {
    1141              :                         UG_LOG("folgendes Gesicht in falscher Anztahl gefunden Diamant " << nextFaceFound << " " << isXCross << std::endl);
    1142              :                 //                                      return false;
    1143            0 :                         UG_THROW("folgendes Gesicht in falscher Anztahl gefunden Diamant " << nextFaceFound << " " << isXCross << std::endl);
    1144              :                 }
    1145              : 
    1146            0 :                 for( std::vector<Face*>::iterator itFac = assoFacCrossCop.begin(); itFac != assoFacCrossCop.end(); itFac++ )
    1147              :                 {
    1148            0 :                         Face * iFa = *itFac;
    1149              : 
    1150            0 :                         if( FaceContains(iFa, firstEdgeFac ) )
    1151              :                         {
    1152            0 :                                 assoFacConsider = iFa;
    1153            0 :                                 break;
    1154              :                         }
    1155              :                 }
    1156              : 
    1157              : 
    1158            0 :                 boundAtShiftVrtEdg = ! boundAtShiftVrtEdg;
    1159              : 
    1160            0 :         }
    1161              : 
    1162            0 :         if( assoFacEdgEnd2Fix != assoFacEdgBeg2Fix || assoFacEdgEnd2Fix == nullptr || assoFacEdgBeg2Fix == nullptr )
    1163              :         {
    1164            0 :                 UG_THROW("Anfang und Ende stimmen nicht ueberein " << isXCross << std::endl);
    1165              : //                              return false;
    1166              :                 UG_THROW("Anfang und Ende stimmen nicht ueberein " << isXCross << std::endl);
    1167              :         }
    1168              : 
    1169              : //                      if( shiftVrtcsCop.size() != 0 )
    1170              : //                      {
    1171              : //                              UG_LOG("Shift vertizes nicht alle gefinden " << std::endl);
    1172              : //                              return false;
    1173              : //                              UG_THROW("Shift vertizes nicht alle gefinden " << std::endl);
    1174              : //                      }
    1175              : 
    1176            0 :         if( assoFacCrossCop.size() != 0 )
    1177              :         {
    1178              :                 UG_LOG("nicht alle asso facs gefunden " << isXCross << std::endl);
    1179              : //                              return false;
    1180            0 :                 UG_THROW("nicht alle asso facs gefunden " << isXCross << std::endl);
    1181              :         }
    1182              : 
    1183              : 
    1184            0 :         return true;
    1185              : }
    1186              : 
    1187            0 : void computeDiamondPointXCrossType( ExpandCrossFracInfo & expCFIBeforeFracEdg, ExpandCrossFracInfo & expCFIAfterFracEdg,
    1188              :                                                                         Vertex * const & crossPt, Grid::VertexAttachmentAccessor<APosition> & aaPos,
    1189              :                                                                         SubsetHandler & sh, Grid & grid, IndexType const & diamantSubsNum,
    1190              :                                                                         vector3 & distVecNewVrt2SCrossPt,
    1191              :                                                                         bool useTrianglesInDiamonds = false
    1192              : //                                                                      vector3 & distVecNewVrt2ShiVeBefore = vector3(), vector3 & distVecNewVrt2ShiVeAfter = vector3(),
    1193              : //                                                                      bool computeDistancesNewVrtsToOldShiVe = false
    1194              : )
    1195              : {
    1196              :         // compute cross point
    1197              : 
    1198              :         std::pair<Edge*, Edge*> edgesCrossSegBefore = expCFIBeforeFracEdg.getEdge();
    1199              :         std::pair<Edge*, Edge*> edgesCrossSegAfter = expCFIAfterFracEdg.getEdge();
    1200              : 
    1201              :         Edge * beforeShiftEdg = edgesCrossSegBefore.first;
    1202              :         Edge * beforeFracEdg = edgesCrossSegBefore.second;
    1203              :         Edge * afterFracEdg = edgesCrossSegAfter.first;
    1204              :         Edge * afterShiftEdg = edgesCrossSegAfter.second;
    1205              : 
    1206              :         std::pair<Vertex*,Vertex*> vrtcsCrossSegBefore = expCFIBeforeFracEdg.getNormal();
    1207              :         std::pair<Vertex*,Vertex*> vrtcsCrossSegAfter = expCFIAfterFracEdg.getNormal();
    1208              : 
    1209              :         Vertex * shiftBefore = vrtcsCrossSegBefore.first;
    1210              :         Vertex * shiftAfter = vrtcsCrossSegAfter.second;
    1211              : 
    1212              :         // zur Zielsetzung
    1213              : //                              Vertex * toBeEstablishedCutEdgeVrtBefore = vrtcsCrossSegBefore.second;
    1214              : //                              Vertex * toBeEstablishedCutEdgeVrtAfter = vrtcsCrossSegAfter.first;
    1215              : 
    1216            0 :         if(    vrtcsCrossSegBefore.second != nullptr ||  vrtcsCrossSegAfter.first != nullptr
    1217            0 :                 ||      shiftBefore == nullptr || shiftAfter == nullptr
    1218              : //                              if(    toBeEstablishedCutEdgeVrtBefore != nullptr ||  toBeEstablishedCutEdgeVrtAfter != nullptr
    1219              : //                                      ||      shiftBefore == nullptr || shiftAfter == nullptr
    1220              :           )
    1221            0 :                 UG_THROW("Nullpointer fehlen oder zu viel " << std::endl);
    1222              : 
    1223            0 :         if(    beforeFracEdg != afterFracEdg || beforeFracEdg == nullptr || afterFracEdg == nullptr
    1224            0 :                 || beforeShiftEdg == nullptr || afterShiftEdg == nullptr
    1225              :           )
    1226              :                 UG_LOG("Ecken Nullpunkter " << std::endl);
    1227              : 
    1228              :         // determin cut point of line between the shift vertices and the frac edge
    1229              : 
    1230              :         Edge * fracEdge = beforeFracEdg; // muss gleich sein offenkundig afterFracEdge, ist getestet auch
    1231              : 
    1232              :         // Gerade bestimmen, die durch fracEdge bestimmt wird, und Gerade, die durch Verbindungsvektor shift Verzices bestimmt wird
    1233              : 
    1234              :         // figure out frac vertex which is the cross point
    1235              : 
    1236              :         IndexType fracEdgInd = -1;
    1237              : 
    1238            0 :         for( IndexType fiv = 0; fiv < 2; fiv++ )
    1239              :         {
    1240            0 :                 if( fracEdge->vertex(fiv) == crossPt )
    1241              :                         fracEdgInd = fiv;
    1242              :         }
    1243              : 
    1244            0 :         if( fracEdgInd < 0 || fracEdgInd > 1 )
    1245            0 :                 UG_THROW("cross point nicht Teil von fracture edge" << std::endl );
    1246              : 
    1247            0 :         Vertex * fracEdgEnd = fracEdge->vertex( ( fracEdgInd + 1 ) % 2 );
    1248              : 
    1249            0 :         vector3 posCrossPt = aaPos[ crossPt ];
    1250              :         vector3 posFracEnd = aaPos[ fracEdgEnd ];
    1251              : 
    1252              :         vector3 posShiftBefore = aaPos[ shiftBefore ];
    1253              :         vector3 posShiftAfter = aaPos[ shiftAfter ];
    1254              : 
    1255              : //      vector3 directionFrac;
    1256              : //
    1257              : //      VecSubtract(directionFrac, posFracEnd, posCrossPt );
    1258              : 
    1259              :         vector3 directionShiftBefore;
    1260              : 
    1261              :         VecSubtract(directionShiftBefore, posShiftBefore, posCrossPt);
    1262              : 
    1263              :         vector3 directionShiftAfter;
    1264              : 
    1265              :         VecSubtract(directionShiftAfter, posShiftAfter, posCrossPt );
    1266              : 
    1267              :         vector3 sumShift;
    1268              : 
    1269              :         VecAdd(sumShift, directionShiftBefore, directionShiftAfter);
    1270              : 
    1271              :         vector3 halfSumShift;
    1272              : 
    1273            0 :         number scaFa = useTrianglesInDiamonds ? 1 : 0.5;
    1274              : 
    1275              : //      VecScale(halfSumShift, sumShift, 0.5);
    1276              :         VecScale( halfSumShift, sumShift, scaFa );
    1277              : 
    1278              :         vector3 posNewVrtOnEdg;
    1279              : 
    1280              :         VecAdd( posNewVrtOnEdg, posCrossPt, halfSumShift );
    1281              : 
    1282              :         // check if not shifting into the wrong direction TODO FIXME
    1283              :         // if length between posFracEnd and posNewVrtOnEdg bigger than length between posFracEnd and crossPt
    1284              :         // then shifted into the wrong direction, Kommando zurück dann!
    1285              : 
    1286              : //      if( useTrianglesInDiamonds )
    1287              : //      {
    1288              :         // always
    1289              : 
    1290              :         vector3 distVecOld;
    1291              :         VecSubtract(distVecOld, posFracEnd, posCrossPt );
    1292              :         vector3 distVecNew;
    1293              :         VecSubtract(distVecNew, posFracEnd, posNewVrtOnEdg);
    1294              :         number oldDistSq = VecLength(distVecOld);
    1295              :         number newDistSq = VecLength(distVecNew);
    1296              : 
    1297            0 :         if( oldDistSq < newDistSq )
    1298              :         {
    1299            0 :                 VecScale( halfSumShift, sumShift, - scaFa);
    1300              :                 VecAdd(posNewVrtOnEdg, posCrossPt, halfSumShift);
    1301              :         }
    1302            0 :         else if( oldDistSq == newDistSq ) // cross pt would equal new position
    1303              :         {
    1304            0 :                 if( posNewVrtOnEdg != posCrossPt || distVecNew != distVecOld )
    1305            0 :                         UG_THROW("Denkfehler, Implementation extemer Spezialfall checken" << std::endl);
    1306              : 
    1307              :                 vector3 distCorr;
    1308              :                 VecScale( distCorr, distVecOld, 0.05 );
    1309              :                 VecAdd( posNewVrtOnEdg, posCrossPt, distCorr );
    1310              :                 // Versuch, den Punkt ein wenig zu verschieben
    1311              :         }
    1312              : 
    1313              :         // TODO FIXME eventuell noch testen, ob die beiden Punkte in einem kleinen Radius liegen und korrigieren,
    1314              :         // eventuell schon vorher, statt zu werfen
    1315            0 :         if( posNewVrtOnEdg == posCrossPt )
    1316            0 :                 UG_THROW("Denkfehler Typ 2, Implementation extemer Spezialfall checken" << std::endl);
    1317              : 
    1318              : //      }
    1319              : 
    1320            0 :         Vertex * newEdgVrtx = *grid.create<RegularVertex>();
    1321              :         aaPos[newEdgVrtx] = posNewVrtOnEdg;
    1322              : 
    1323            0 :         IndexType sudoEdg = sh.get_subset_index(fracEdge);
    1324              : 
    1325              :         Face * faceBefore = expCFIBeforeFracEdg.getFace();
    1326              :         Face * faceAfter = expCFIAfterFracEdg.getFace();
    1327              : 
    1328            0 :         IndexType sudoBefore = sh.get_subset_index(faceBefore);
    1329            0 :         IndexType sudoAfter = sh.get_subset_index(faceAfter);
    1330              : 
    1331            0 :         if( sudoEdg != sudoBefore || sudoBefore != sudoAfter )
    1332            0 :                 UG_THROW("komische sudos vor Diamant " << std::endl);
    1333              : 
    1334              : //      sh.assign_subset(newEdgVrtx, sudoEdg);
    1335            0 :         sh.assign_subset(newEdgVrtx, diamantSubsNum );
    1336              : 
    1337              : 
    1338            0 :         UG_LOG("neuer Diamant Vorbereitungs Vertex " << posNewVrtOnEdg << std::endl);
    1339              : 
    1340              :         //                              Vertex * toBeEstablishedCutEdgeVrtBefore = vrtcsCrossSegBefore.second;
    1341              :         //                              Vertex * toBeEstablishedCutEdgeVrtAfter = vrtcsCrossSegAfter.first;
    1342              : 
    1343              : 
    1344              : 
    1345              :         // gleich neue Faces erzeugen?
    1346              : //                              std::pair<Vertex*,Vertex*> vrtcsCrossSegBefore = expCFIBeforeFracEdg.getNormal();
    1347              : //                              std::pair<Vertex*,Vertex*> vrtcsCrossSegAfter = expCFIAfterFracEdg.getNormal();
    1348              : 
    1349              :         // insert the newly established vertex into the vertex info of the ExpandCrossFracInfo of the face
    1350              : ////                            vrtcsCrossSegBefore.second = newEdgVrtx;
    1351              : ////                            vrtcsCrossSegAfter.first = newEdgVrtx;
    1352              : ////
    1353              : //                              std::pair<Vertex*,Vertex*> vrtcsCrossSegBeforeNew( vrtcsCrossSegBefore.first, newEdgVrtx );
    1354              : //                              std::pair<Vertex*,Vertex*> vrtcsCrossSegAfterNew( newEdgVrtx, vrtcsCrossSegAfter.second );
    1355              : //
    1356              : //
    1357              : //                              expCFIBeforeFracEdg.setNewNormal( vrtcsCrossSegBeforeNew );
    1358              : //                              expCFIAfterFracEdg.setNewNormal( vrtcsCrossSegAfterNew );
    1359              : 
    1360              :         vrtcsCrossSegBefore.second = newEdgVrtx;
    1361              :         vrtcsCrossSegAfter.first = newEdgVrtx;
    1362              :         expCFIBeforeFracEdg.setNewNormal( vrtcsCrossSegBefore );
    1363              :         expCFIAfterFracEdg.setNewNormal( vrtcsCrossSegAfter );
    1364              : 
    1365              :         VecSubtract(distVecNewVrt2SCrossPt, posCrossPt, posNewVrtOnEdg );
    1366              : 
    1367              :         // only needed for TEnd case
    1368              : //      if( computeDistancesNewVrtsToOldShiVe )
    1369              : //      {
    1370              : //              VecSubtract(distVecNewVrt2ShiVeBefore, posShiftBefore, posNewVrtOnEdg );
    1371              : //              VecSubtract(distVecNewVrt2ShiVeAfter, posShiftAfter, posNewVrtOnEdg );
    1372              : //      }
    1373            0 : }
    1374              : 
    1375              : // This function creates the new faces outside the diamond, directly attached to the diamond,
    1376              : // as part of post processing
    1377              : 
    1378            0 : void createNewFacesForExtXCrossFracs( ExpandCrossFracInfo const & ecf,  std::vector<Face*> & newFracFaceVec,
    1379              :                                                                           bool & boundAtShiftVrtEdg, //bool & atStartSort,
    1380              :                                                                           SubsetHandler & sh, Grid & grid, Vertex * const & crossPt,
    1381              :                                                                           std::vector<IndexType> const & subdomList
    1382              :                                                                         )
    1383              : {
    1384              :         // get new vertex at the original fracture edge
    1385              : 
    1386              :         // extract this functionality to own function
    1387              : 
    1388              : 
    1389              :         std::pair<Edge*, Edge*> edgesCrossSeg = ecf.getEdge();
    1390              : 
    1391              :         Face * facSeg = ecf.getFace();
    1392              : 
    1393              :         std::pair<Vertex*, Vertex*> vertcsCrossSeg = ecf.getNormal();
    1394              : 
    1395              :         std::pair<Vertex*, Vertex*> vertcsCrossSegWithNewV = ecf.getNewNormal();
    1396              : 
    1397              : 
    1398              : //      if( atStartSort || boundAtShiftVrtEdg )
    1399            0 :         if( boundAtShiftVrtEdg )
    1400              :         {
    1401            0 :                 if( vertcsCrossSeg.first != nullptr || vertcsCrossSeg.second == nullptr )
    1402            0 :                         UG_THROW("Verwechslung " << vertcsCrossSeg.first << " " << vertcsCrossSeg.second << std::endl);
    1403              :         }
    1404              : 
    1405              : //      atStartSort = false;
    1406              : 
    1407            0 :         Edge * fracEdge = boundAtShiftVrtEdg ? edgesCrossSeg.first : edgesCrossSeg.second;
    1408              :         Edge * shiftVrtEdge = boundAtShiftVrtEdg ?  edgesCrossSeg.second : edgesCrossSeg.first;
    1409              : 
    1410            0 :         Vertex * fracVrtNew =  boundAtShiftVrtEdg ? vertcsCrossSegWithNewV.first : vertcsCrossSegWithNewV.second; // should be nullptr at first segment, to be assigned afterwards / shifted
    1411            0 :         Vertex * shiftVrt = boundAtShiftVrtEdg ? vertcsCrossSeg.second : vertcsCrossSeg.first;
    1412            0 :         Vertex * shiftVrtTest = boundAtShiftVrtEdg ? vertcsCrossSegWithNewV.second : vertcsCrossSegWithNewV.first;
    1413              : 
    1414            0 :         if( shiftVrtTest != shiftVrt )
    1415            0 :                 UG_THROW("Shift Vertex verloren gegangen " << std::endl);
    1416              : 
    1417            0 :         IndexType sudoFac = sh.get_subset_index(facSeg);
    1418              : 
    1419            0 :         IndexType sudoFracEdge = sh.get_subset_index(fracEdge);
    1420              : 
    1421            0 :         if( sudoFac != sudoFracEdge )
    1422              :         {
    1423            0 :                 UG_THROW("subdoms frac edge und face nicht gleich " << std::endl);
    1424              :         }
    1425              : 
    1426              :         // get all vertices of face, check if both known ones are contained, delete the face, create
    1427              :         // the additional needed edge, and create new face with new vertex
    1428              : 
    1429              : 
    1430              :         std::vector<Vertex*> vrtcsFace;
    1431              :         // assign first old vertices, then replace
    1432              : //                              std::vector<Vertex*> vrtcsNewFaceFrac = vrtcsFace;
    1433              : //                              std::vector<Vertex*> vrtcsNewFaceDiam = vrtcsFace;
    1434              : 
    1435              :         //      all new vertices have been assigned to newVrts.
    1436              :         //      Note that if newVrts[i] == NULL, then we have to take the
    1437              :         //      old vertex sf->vertex(i).
    1438              :         //      now expand the fracture edges of sf to faces.
    1439            0 :         for(size_t iVrt = 0; iVrt < facSeg->num_vertices(); iVrt++ )
    1440              :         {
    1441              : 
    1442            0 :                 Vertex * vrt = facSeg->vertex(iVrt);
    1443            0 :                 vrtcsFace.push_back( vrt );
    1444              : //                                      vrtcsNewFaceFrac.push_back( vrt );
    1445              : //                                      vrtcsNewFaceDiam.push_back( vrt );
    1446              :         }
    1447              : 
    1448            0 :         std::vector<Vertex*> vrtcsNewFaceFrac = vrtcsFace;
    1449              : //                              std::vector<Vertex*> vrtcsNewFaceDiam = vrtcsFace;
    1450              : 
    1451              : 
    1452              :         // check if known vertices are contained
    1453              : 
    1454              :         IndexType fraVeNuInd = -1;
    1455              :         IndexType shiftVeNuInd = -1;
    1456              : 
    1457              :         IndexType cntr = 0;
    1458              : 
    1459            0 :         for( auto const & vf : vrtcsFace )
    1460              :         {
    1461            0 :                 if( vf == fracVrtNew )
    1462              :                 {
    1463              :                         fraVeNuInd = cntr;
    1464            0 :                         UG_THROW("wie kann man hierher kommen?" << std::endl);
    1465              :                 }
    1466              : 
    1467            0 :                 if( vf == crossPt )
    1468              :                 {
    1469              :                         fraVeNuInd = cntr;
    1470              :                 }
    1471              : 
    1472              : //
    1473            0 :                 if( vf == shiftVrt )
    1474              :                         shiftVeNuInd = cntr;
    1475              : 
    1476            0 :                 cntr++;
    1477              :         }
    1478              : 
    1479              :         if( fraVeNuInd < 0 || shiftVeNuInd < 0 )
    1480              :                 UG_THROW("frac vertex oder shift vertex not contained " << std::endl);
    1481              : 
    1482              :         UG_LOG("neuer frac vertex " << fraVeNuInd << " " << shiftVeNuInd << std::endl );
    1483              : 
    1484              :         // replace vrtcs
    1485            0 :         vrtcsNewFaceFrac[fraVeNuInd] = fracVrtNew;
    1486              : 
    1487              :         // compute shift of center vertex along frac edge
    1488              : 
    1489              :         // check subdom of frac vertex and check if in subdom List of X cross
    1490              : 
    1491              :         IndexType sudoOther = -1;
    1492              : 
    1493              :         IndexType foundSudoOther = 0;
    1494              :         IndexType foundSudoFac = 0;
    1495              : 
    1496            0 :         for( auto const & sd : subdomList )
    1497              :         {
    1498            0 :                 if( sd != sudoFac )
    1499              :                 {
    1500              :                         sudoOther = sd;
    1501            0 :                         foundSudoOther++;
    1502              :                 }
    1503              :                 else if( sd == sudoFac )
    1504              :                 {
    1505            0 :                         foundSudoFac++;
    1506              :                 }
    1507              :                 else
    1508              :                 {
    1509              :                         UG_THROW("Sudo not from frac and not from other?" << std::endl);
    1510              :                 }
    1511              :         }
    1512              : 
    1513            0 :         if( foundSudoFac != 1 && foundSudoOther != 1 )
    1514            0 :                 UG_THROW("sudo zu oft oder zu selten gefunden " << std::endl);
    1515              : 
    1516              :         // establish new edges and new faces
    1517              : 
    1518            0 :         if( vrtcsNewFaceFrac.size() != 4 )
    1519              :                 UG_LOG("komische Groesse Gesicht " << std::endl);
    1520              : 
    1521            0 :         for( IndexType i = 0; i < vrtcsNewFaceFrac.size(); i++ )
    1522              :         {
    1523            0 :                 if( vrtcsNewFaceFrac[i] == nullptr )
    1524              :                 {
    1525            0 :                         UG_THROW("null auf " << i << std::endl);
    1526              :                 }
    1527              : //                                      else
    1528              : //                                      {
    1529              : //                                              UG_LOG("kein null auf " << i << std::endl );
    1530              : //                                      }
    1531              :         }
    1532              : 
    1533              : 
    1534              :         UG_LOG("neue Gesichter ausserhalb Diamant Ziel " << std::endl);
    1535              : 
    1536              : //                              int a = 1 + 2;
    1537              : //
    1538            0 :         Face * newFracFace = nullptr;
    1539              : 
    1540            0 :         if(vrtcsNewFaceFrac.size() == 3 )
    1541              :         {
    1542            0 :                 newFracFace =
    1543            0 :                         *grid.create<Triangle>( TriangleDescriptor( vrtcsNewFaceFrac[0], vrtcsNewFaceFrac[1],
    1544              :                                                                                                                                   vrtcsNewFaceFrac[2]
    1545              :                                                                                 ) );
    1546              : 
    1547              :         }
    1548            0 :         else if( vrtcsNewFaceFrac.size() == 4 )
    1549              :         {
    1550            0 :                 newFracFace =
    1551            0 :                         *grid.create<Quadrilateral>( QuadrilateralDescriptor( vrtcsNewFaceFrac[0], vrtcsNewFaceFrac[1],
    1552              :                                                                                                                                   vrtcsNewFaceFrac[2], vrtcsNewFaceFrac[3]
    1553              :                                                                                 ) );
    1554              : 
    1555              :         }
    1556              :         else
    1557              :         {
    1558            0 :                 UG_THROW("komisches Gesicht " << std::endl);
    1559              :         }
    1560              : 
    1561            0 :         if( newFracFace != nullptr )
    1562              :         {
    1563            0 :                 sh.assign_subset(newFracFace, sh.get_subset_index(facSeg) );
    1564              :                 //                              sh.assign_subset(newFracFace, diamantSubsNum ); testweise
    1565              : 
    1566            0 :                 newFracFaceVec.push_back(newFracFace);
    1567              :         }
    1568              :         else
    1569              :         {
    1570            0 :                 UG_THROW("Gesicht ist nicht enstanden " << std::endl);
    1571              :         }
    1572              : 
    1573              : 
    1574            0 :         boundAtShiftVrtEdg = ! boundAtShiftVrtEdg;
    1575              : 
    1576              : 
    1577            0 : }
    1578              : 
    1579              : // this function creates the new faces of the diamond center, for XCross, but also for free TEnd type crossing fractures
    1580              : 
    1581            0 : void createDiamondFacesXCrossType( ExpandCrossFracInfo & expCFIBeforeFracEdg, ExpandCrossFracInfo & expCFIAfterFracEdg,
    1582              :                 std::vector<Face*> & newDiamFaceVec,  SubsetHandler & sh, Grid & grid, IndexType diamantSubsNum, Vertex * & crossPt,
    1583              :                 bool isFreeTEnd = false )
    1584              : {
    1585              : 
    1586              :         Face * facBefore = expCFIBeforeFracEdg.getFace();
    1587              :         Face * facAfter = expCFIAfterFracEdg.getFace();
    1588              : 
    1589              :         std::vector<Vertex*> vrtcsFaceBefore;
    1590              :         std::vector<Vertex*> vrtcsFaceAfter;
    1591              : 
    1592            0 :         for(size_t iVrt = 0; iVrt < facBefore->num_vertices(); iVrt++ )
    1593              :         {
    1594            0 :                 Vertex * vrt = facBefore->vertex(iVrt);
    1595            0 :                 vrtcsFaceBefore.push_back( vrt );
    1596              :         }
    1597              : 
    1598            0 :         for(size_t iVrt = 0; iVrt < facAfter->num_vertices(); iVrt++ )
    1599              :         {
    1600            0 :                 Vertex * vrt = facAfter->vertex(iVrt);
    1601            0 :                 vrtcsFaceAfter.push_back( vrt );
    1602              :         }
    1603              : 
    1604            0 :         Vertex * newVrtBefore = expCFIBeforeFracEdg.getNewNormal().first;
    1605            0 :         Vertex * shiftVrt = expCFIBeforeFracEdg.getNewNormal().second;
    1606            0 :         Vertex * newVrtAfter = expCFIAfterFracEdg.getNewNormal().second;
    1607              : 
    1608              :         if(    expCFIBeforeFracEdg.getNewNormal().second != expCFIBeforeFracEdg.getNormal().second
    1609            0 :                 || expCFIBeforeFracEdg.getNewNormal().second == nullptr
    1610            0 :                 || expCFIBeforeFracEdg.getNewNormal().second != expCFIAfterFracEdg.getNewNormal().first
    1611              :                 || expCFIAfterFracEdg.getNewNormal().first == nullptr
    1612            0 :                 || expCFIAfterFracEdg.getNewNormal().first != expCFIAfterFracEdg.getNormal().first
    1613              :         )
    1614              :         {
    1615              :                 UG_LOG("Vektoren " << expCFIBeforeFracEdg.getNewNormal().second << " != " <<  expCFIBeforeFracEdg.getNormal().second << std::endl
    1616              :                 << expCFIBeforeFracEdg.getNewNormal().second << std::endl
    1617              :                 << expCFIBeforeFracEdg.getNewNormal().second << " != " << expCFIAfterFracEdg.getNewNormal().first << std::endl
    1618              :                 << expCFIAfterFracEdg.getNewNormal().first << std::endl
    1619              :                 << expCFIAfterFracEdg.getNewNormal().first << " != " << expCFIAfterFracEdg.getNormal().first << std::endl );
    1620              : 
    1621              : #if 0
    1622              :                 Vektoren 0x591e03ec9c90 != 0x591e03ec9c90
    1623              :                 0x591e03ec9c90
    1624              :                 0x591e03ec9c90 != 0x591e03d00fa0
    1625              :                 0x591e03d00fa0
    1626              :                 0x591e03d00fa0 != 0x591e03d00fa0
    1627              :                 Execution of tool Expand Layers 2d Arte failed with the following message:
    1628              : #endif
    1629              : 
    1630            0 :                 UG_THROW("Vektorchaos " << std::endl);
    1631              :         }
    1632              : 
    1633            0 :         if( ! isFreeTEnd ) // standard XCross case, also applicable for TEnd apart from the free end
    1634              :         {
    1635              :                 std::vector<Vertex *> vrtxSmallDiam;
    1636              : 
    1637            0 :                 vrtxSmallDiam.push_back( crossPt );
    1638            0 :                 vrtxSmallDiam.push_back( newVrtBefore );
    1639            0 :                 vrtxSmallDiam.push_back( shiftVrt );
    1640            0 :                 vrtxSmallDiam.push_back( newVrtAfter );
    1641              : 
    1642              :                 Face * newFracFace =
    1643            0 :                         *grid.create<Quadrilateral>( QuadrilateralDescriptor( vrtxSmallDiam[0], vrtxSmallDiam[1],
    1644              :                                                                                                                                   vrtxSmallDiam[2], vrtxSmallDiam[3]
    1645            0 :                                                                                 ) );
    1646              : 
    1647            0 :                 sh.assign_subset(newFracFace, diamantSubsNum );
    1648              : 
    1649            0 :                 newDiamFaceVec.push_back(newFracFace);
    1650              : 
    1651            0 :         }
    1652              :         else
    1653              :         {
    1654              :                 std::vector<Vertex *> vrtxSmallDiamBefore;
    1655              :                 std::vector<Vertex *> vrtxSmallDiamAfter;
    1656              : 
    1657            0 :                 vrtxSmallDiamBefore.push_back( crossPt );
    1658            0 :                 vrtxSmallDiamBefore.push_back( newVrtBefore );
    1659            0 :                 vrtxSmallDiamBefore.push_back( shiftVrt );
    1660              : 
    1661            0 :                 vrtxSmallDiamAfter.push_back( crossPt );
    1662            0 :                 vrtxSmallDiamAfter.push_back( shiftVrt );
    1663            0 :                 vrtxSmallDiamAfter.push_back( newVrtAfter );
    1664              : 
    1665              :                 Face * newFracFaceBefore =
    1666            0 :                         *grid.create<Triangle>( TriangleDescriptor( vrtxSmallDiamBefore[0], vrtxSmallDiamBefore[1], vrtxSmallDiamBefore[2] ) );
    1667              : 
    1668              :                 Face * newFracFaceAfter =
    1669            0 :                         *grid.create<Triangle>( TriangleDescriptor( vrtxSmallDiamAfter[0], vrtxSmallDiamAfter[1], vrtxSmallDiamAfter[2] ) );
    1670              : 
    1671              : 
    1672            0 :                 sh.assign_subset(newFracFaceBefore, diamantSubsNum );
    1673            0 :                 sh.assign_subset(newFracFaceAfter, diamantSubsNum );
    1674              : 
    1675            0 :                 newDiamFaceVec.push_back(newFracFaceBefore);
    1676            0 :                 newDiamFaceVec.push_back(newFracFaceAfter);
    1677              : 
    1678            0 :         }
    1679              : 
    1680              : 
    1681            0 : }
    1682              : 
    1683            0 : void assignFaceSubsetToClosedFace( std::vector<Face*> & faceVec, Grid & grid, SubsetHandler & sh )
    1684              : {
    1685              : 
    1686            0 :         for( auto const & nF : faceVec )
    1687              :         {
    1688            0 :                 for(size_t iEdge = 0; iEdge < nF->num_edges(); iEdge++ )
    1689              :                 {
    1690            0 :                         Edge* edg = grid.get_edge(nF, iEdge);
    1691              : 
    1692            0 :                         sh.assign_subset( edg, sh.get_subset_index(nF) );
    1693              : 
    1694              :                 }
    1695              : 
    1696            0 :                 for( size_t iVrt = 0; iVrt < nF->num_vertices(); iVrt++ )
    1697              :                 {
    1698            0 :                         Vertex * vrt = nF->vertex(iVrt);
    1699              : 
    1700            0 :                         sh.assign_subset( vrt, sh.get_subset_index(nF) );
    1701              :                 }
    1702              : 
    1703              :         }
    1704              : 
    1705            0 : }
    1706              : 
    1707              : 
    1708              : //using VecVertFracTrip = std::vector<VertFracTrip>;
    1709              : //
    1710              : //// needed for crossing points
    1711              : //using VertexOfFaceInfo = VertexFractureTriple< std::pair<Edge*, Edge*>, Face*, std::pair<vector3,vector3> >;
    1712              : //// all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges
    1713              : //// the size of the normal vector vector also must be two
    1714              : //// however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm
    1715              : //// for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple
    1716              : //
    1717              : //using VecVertexOfFaceInfo = std::vector<VertexOfFaceInfo>;
    1718              : //
    1719              : //using SegmentsFractExtrus = std::vector<VecVertexOfFaceInfo>;
    1720              : 
    1721              : 
    1722            0 : bool determineOrderOfFaces( //CrossVertInf & crossVrtInf,
    1723              :                                                         VecVertFracTrip const & vecVertFracTrip,
    1724              :                                                         VecFace const & assoFaces,  VecVertexOfFaceInfo & orderedFaces,
    1725              :                                                         SegmentsFractExtrus & segments,
    1726              :                                                         // single components always from one fracture edge to the next one
    1727              :                                                         //VecVertexOfFaceInfo & segmentPart,
    1728              :                                                         // note: we do not attach this info to the vertex, as we only need it local; in principle, in case of further need, it would
    1729              :                                                         // be usful to establish some sort of attachment,
    1730              :                                                         //VertFracTrip & startVertFracTrip,
    1731              :                                                         IndexType startIndex,
    1732              :                                                         std::vector<Edge*> const & allAssoEdges,
    1733              :                                                         SubsetHandler & sh,
    1734              :                                                         Grid::EdgeAttachmentAccessor<ABool> const & aaMarkEdgeB,
    1735              :                                                         std::vector<Edge* > const & adjBndEdgs = std::vector<Edge* >(), // to allow for boundary constrained regions
    1736              :                                                         Face * const & attFaceOf1stBndEdg = nullptr
    1737              :                                                 )
    1738              : {
    1739              :         IndexType countedCrossingFracEdgs = 0;
    1740              :         // copies of all faces and of fractured ones
    1741            0 :         auto aF = assoFaces; // caution: COPY, not reference!
    1742            0 :         auto vVFT = vecVertFracTrip; // caution: COPY, not reference!
    1743              : 
    1744              :         UG_LOG("Gesamtanzahl faces um Knoten " <<  aF.size() << std::endl );
    1745              : 
    1746              :         //  erstmal die ganzen anhaengenden Faces ordnen, dass wir wissen, in welcher Reihenfolge wir durchlaufen muessen
    1747              :         // jede Edge hat ein bool attachment schon, das weiss, ob sie Fracture edge ist oder nicht
    1748              :         // Reihenfolge der faces und die edges auch dazu, vielleicht neues Triple oder dergleiche, dabei zwei edges und zwei normals
    1749              :         // und wie gesagt, die edges wissen, ob sie fractures sind, dazu keine neuen Variablen notwendig
    1750              : 
    1751              :         //                              using VertexOfFaceInfo = VertexFractureTriple< std::pair<Edge*, Edge*>, Face*, std::pair<vector3,vector3> >;
    1752              : 
    1753              :         // all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges
    1754              :         // the size of the normal vector vector also must be two
    1755              :         // however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm
    1756              :         // for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple
    1757              : 
    1758              : 
    1759            0 :         if( vVFT.size() == 0 )
    1760            0 :                 UG_THROW("vertex frac triple zu klein an Kreuzung " << std::endl);
    1761              : 
    1762            0 :         IndexType numbIncorpBnds = adjBndEdgs.size();
    1763              : 
    1764            0 :         if( numbIncorpBnds != 0 && numbIncorpBnds != 2 )
    1765            0 :                 UG_THROW("komische Grenzstruktur" << numbIncorpBnds << std::endl);
    1766              : 
    1767              :         bool isNormalNoBndCase = ( numbIncorpBnds != 2 );
    1768              : 
    1769              :         bool atFirstTriple = true;
    1770              : 
    1771              :         vector3 nuVe(0,0,0);
    1772              : 
    1773              :         Face* fracFac = nullptr;
    1774              :         Edge* fracEdg = nullptr;
    1775              :         vector3 fracNorm = nuVe;
    1776              : 
    1777              :         Edge * originalStartEdge = nullptr;
    1778              :         Edge * targetedEndEdge = nullptr;
    1779              : 
    1780            0 :         if( isNormalNoBndCase )
    1781              :         {
    1782              :                         // we start with the first fracture face edge stuff, copy it,  and delete this immidiately
    1783            0 :                 VertFracTrip startVertFracTrip = vVFT[startIndex];
    1784              : 
    1785              :                 vVFT.erase( vVFT.begin() + startIndex );
    1786              : 
    1787              :                 atFirstTriple = true;
    1788              : 
    1789              :                 fracFac = startVertFracTrip.getFace();
    1790              :                 fracEdg = startVertFracTrip.getEdge();
    1791              :                 fracNorm = startVertFracTrip.getNormal();
    1792              : 
    1793              :                 originalStartEdge = startVertFracTrip.getEdge();
    1794              :                 targetedEndEdge = originalStartEdge;
    1795              :         }
    1796              :         else // boundary edge start
    1797              :         {
    1798              :                 atFirstTriple = false;
    1799              : 
    1800              :                 // misleading names fracFac and fracEdg, as on boundary edge no fracture assumed, but to keep code overviewable
    1801            0 :                 fracFac = attFaceOf1stBndEdg;
    1802            0 :                 fracEdg = adjBndEdgs[0];
    1803              : //              fracNorm = startVertFracTrip.getNormal(); - assumed to be nullvector
    1804              : 
    1805              :                 originalStartEdge = adjBndEdgs[0];
    1806            0 :                 targetedEndEdge = adjBndEdgs[1];
    1807              : 
    1808              : 
    1809              :         }
    1810              : 
    1811              : 
    1812              :         if( fracEdg != nullptr )
    1813              :         {
    1814              :                 countedCrossingFracEdgs++;
    1815              :         }
    1816              : 
    1817              :         // do not change this pointer
    1818              :         Edge* startEdg = fracEdg;
    1819              :         Face* startFace = fracFac;
    1820              : 
    1821              :         vector3 startNormal = fracNorm;
    1822              : 
    1823              :         Face* nextFace = NULL;
    1824              : 
    1825              :         UG_LOG("Gesamtanzahl faces um Knoten vor while " <<  aF.size() << std::endl );
    1826              : 
    1827              :         VecVertexOfFaceInfo segmentPart;
    1828              : 
    1829            0 :         while( aF.size() != 0 )
    1830              :         {
    1831              : 
    1832              :                 UG_LOG("Gesamtanzahl faces um Knoten Anfang while " <<  aF.size() << std::endl );
    1833              : 
    1834              : 
    1835              :                 Face* face2Append = startFace;
    1836              :                 Edge* startEdg2Append = startEdg;
    1837              : 
    1838              : 
    1839              :                 IndexType fndCommEdg = 0;
    1840              : //              vector3 nuVe(0,0,0);
    1841              : 
    1842              :                 Edge* nextEdge = NULL;
    1843              : 
    1844              :                 std::pair<Edge*, Edge *> edge2Append( startEdg2Append, nextEdge );
    1845              :                 std::pair<vector3, vector3 > normal2Append( startNormal, nuVe );
    1846              : 
    1847              : 
    1848              :                 // if start face and start edge from a triple, then has to be erased this triple, exept for the entire start, as already erased
    1849            0 :                 if( ! atFirstTriple )
    1850              :                 {
    1851            0 :                         for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT !=  vVFT.end(); itAttVFT++ )
    1852              :                         {
    1853              :                                 auto vft = *itAttVFT;
    1854              : 
    1855              :                                 Edge * edgIt = vft.getEdge();
    1856              : 
    1857              :                                 Face * facIt = vft.getFace();
    1858              : 
    1859            0 :                                 if( edgIt == startEdg && facIt == startFace )
    1860              :                                 {
    1861              :                                         // the first edge if from a fracture and the face is connected to it
    1862              : 
    1863              :                                         vVFT.erase(itAttVFT);
    1864              : 
    1865              :                                         normal2Append.first = vft.getNormal();
    1866              : 
    1867            0 :                                         if( ! FaceContains( facIt, startEdg ))
    1868              :                                         {
    1869            0 :                                                 UG_THROW("Face does not contain start edge of its edge" << std::endl);
    1870              :                                         }
    1871              : 
    1872              :                                         break;
    1873              :                                 }
    1874              :                         }
    1875              : 
    1876              :                 }
    1877              :                 else // we can save the investigation if we have a triple, and we do not need to erase, as already erased.....
    1878              :                 {
    1879              :                         atFirstTriple = false;
    1880              :                 }
    1881              : 
    1882              : 
    1883            0 :                 for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt
    1884              :                 {
    1885            0 :                         if( FaceContains(face2Append, iE) )
    1886              :                         {
    1887            0 :                                 fndCommEdg++;
    1888              : 
    1889            0 :                                 if( iE != startEdg )
    1890              :                                 {
    1891              :                                         nextEdge = iE;
    1892              : 
    1893              :                                         edge2Append.second = iE;
    1894              : 
    1895              :                                 }
    1896              :                         }
    1897              : 
    1898              : 
    1899              :                 }
    1900              : 
    1901            0 :                 if( fndCommEdg != 2 )
    1902              :                 {
    1903            0 :                         UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl);
    1904              :                 }
    1905              : 
    1906            0 :                 if( nextEdge == NULL )
    1907              :                 {
    1908            0 :                         UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl);
    1909              :                 }
    1910              : 
    1911            0 :                         if( edge2Append.first == NULL || edge2Append.second == NULL )
    1912              :                 {
    1913            0 :                         UG_THROW("null immer noch?" << std::endl);
    1914              :                 }
    1915              : 
    1916              :                 // erase the face from the list
    1917              : 
    1918              :                 IndexType faceFound = 0;
    1919              : 
    1920            0 :                 for( std::vector<Face*>::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ )
    1921              :                 {
    1922            0 :                         Face * iFa = *itFac;
    1923              : 
    1924            0 :                         if( iFa == startFace &&  FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg))
    1925              :                         {
    1926            0 :                                 faceFound++;
    1927              :                         }
    1928              :                 }
    1929              : 
    1930              :                 int totalSubsNum = sh.num_subsets();
    1931              : 
    1932              :                 int newSubsToAdd = totalSubsNum;
    1933              : 
    1934            0 :                 if( faceFound != 1 )
    1935              :                 {
    1936              : 
    1937              : 
    1938            0 :                         sh.assign_subset(startFace,newSubsToAdd++);
    1939            0 :                         sh.assign_subset(startEdg,newSubsToAdd++);
    1940            0 :                         sh.assign_subset(nextEdge,newSubsToAdd++);
    1941              : 
    1942            0 :                         int faNum = aF.size();
    1943              : 
    1944            0 :                         UG_LOG("Gesamtzahl faces vor Absturz " << faNum << std::endl);
    1945              : 
    1946              :                         UG_LOG("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl);
    1947              : 
    1948              :         //                                              return true;
    1949              : 
    1950            0 :                         UG_THROW("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl);
    1951              : 
    1952              :                         return false;
    1953              : 
    1954              :                 }
    1955              :                 else
    1956              :                 {
    1957              :         //                                              sh.assign_subset(startFace,newSubsToAdd++);
    1958              :         //                                              sh.assign_subset(startEdg,newSubsToAdd++);
    1959              :         //                                              sh.assign_subset(nextEdge,newSubsToAdd++);
    1960              : 
    1961            0 :                         int faNum = aF.size();
    1962              : 
    1963            0 :                         UG_LOG("Gesamtzahl faces ohne Absturz " << faNum << std::endl);
    1964              : 
    1965              :                 }
    1966              : 
    1967            0 :                 for( std::vector<Face*>::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ )
    1968              :                 {
    1969            0 :                         Face * iFa = *itFac;
    1970              : 
    1971            0 :                         if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg) )
    1972              :                         {
    1973              :                                 aF.erase(itFac);
    1974            0 :                                 break;
    1975              :                         }
    1976              :                 }
    1977              : 
    1978              : 
    1979              :                 bool sndEdgIsFracEdge = aaMarkEdgeB[nextEdge];
    1980              : 
    1981              :                 bool tripFound = false;
    1982              : 
    1983            0 :                 if( sndEdgIsFracEdge )
    1984              :                 {
    1985              : 
    1986              :                         if( nextEdge != originalStartEdge || ! isNormalNoBndCase )
    1987              :                                 countedCrossingFracEdgs++;
    1988              : 
    1989              :                         // we need to have a look for the next triple
    1990              : 
    1991              :                         // check if the next normal is a frac normal which contains the face as well
    1992              : 
    1993            0 :                         for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT !=  vVFT.end(); itAttVFT++ )
    1994              :                         {
    1995              :                                 auto vft = *itAttVFT;
    1996              : 
    1997              :                                 Edge * edgIt = vft.getEdge();
    1998              : 
    1999              :                                 Face * facIt = vft.getFace();
    2000              : 
    2001            0 :                                 if( edgIt == nextEdge && facIt == face2Append )
    2002              :                                 {
    2003              :                                         // the second edge if from a fracture and the face is connected to it
    2004              : 
    2005              :                                         tripFound = true;
    2006              : 
    2007              :                                         vVFT.erase(itAttVFT);
    2008              : 
    2009              :                                         normal2Append.second = vft.getNormal();
    2010              : 
    2011            0 :                                         if( ! FaceContains( facIt, nextEdge ))
    2012              :                                         {
    2013            0 :                                                 UG_THROW("Face does not contain edge of its edge" << std::endl);
    2014              :                                         }
    2015              : 
    2016              :                                         break;
    2017              :                                 }
    2018              :                         }
    2019              : 
    2020              :                 }
    2021              : 
    2022            0 :                 if( ! tripFound && sndEdgIsFracEdge )
    2023              :                 {
    2024            0 :                         UG_THROW("Triple nicht gefunden trotz markierter Edge" << std::endl);
    2025              :                 }
    2026              : 
    2027              : 
    2028              :                 // check if aF or vVFT still contain the former or the next face - must not be the case!
    2029              : 
    2030              :                 VertexOfFaceInfo vOFI( edge2Append, face2Append, normal2Append );
    2031              : 
    2032            0 :                 orderedFaces.push_back( vOFI );
    2033              : 
    2034            0 :                 segmentPart.push_back( vOFI );
    2035              : 
    2036            0 :                 if( sndEdgIsFracEdge )
    2037              :                 {
    2038            0 :                         segments.push_back( segmentPart );
    2039              : 
    2040              :                         segmentPart.clear();
    2041              :                 }
    2042              : 
    2043              : 
    2044              :                 // what is next face, what is next edge?
    2045              :                 // wie kriegen wir es hin, auch das nächste Triple zu erasen, wenn es jetzt kommt als nächstes?
    2046              : 
    2047              : 
    2048              :                 startNormal = nuVe;
    2049              :                 startEdg = nextEdge;
    2050              : 
    2051            0 :                 if( aF.size() == 0 )
    2052              :                 {
    2053              : //                      if( nextEdge != originalStartEdge )
    2054            0 :                         if( nextEdge != targetedEndEdge )
    2055              :                         {
    2056            0 :                                 UG_THROW("Gesichter leer, aber keine Anfangsecke gefunden" << std::endl);
    2057              :                         }
    2058              :                         else
    2059              :                         {
    2060              : 
    2061            0 :                                 if( ! isNormalNoBndCase )
    2062              :                                 {
    2063            0 :                                         segments.push_back( segmentPart );
    2064              : 
    2065              :                                         segmentPart.clear();
    2066              :                                 }
    2067              : 
    2068            0 :                                 break; // while loop zu Ende, raus aus dem while loop, den Rest nicht mehr machen, würde schief gehen zwingendermassen
    2069              :                         }
    2070              : 
    2071              :                 }
    2072              : 
    2073              : 
    2074              :                 // bleibt noch das nächste Gesicht heraus zu finden, dafür kommt eigentlich nur noch eines in Frage, da das zweite Gesicht vom edge
    2075              :                 // geloescht sein muss in aF, es muss das einzig übrige face sein, das die jetzt start edge enthält, davon darf es nur eines geben, wir löschen aber noch nicht
    2076              : 
    2077              :                 IndexType nextFaceFound = 0;
    2078              : 
    2079            0 :                 for( std::vector<Face*>::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ )
    2080              :                 {
    2081            0 :                         Face * iFa = *itFac;
    2082              : 
    2083            0 :                         if( FaceContains(iFa, startEdg ) )
    2084              :                         {
    2085            0 :                                 nextFaceFound++;
    2086              :                         }
    2087              :                 }
    2088              : 
    2089            0 :                 if( nextFaceFound != 1 )
    2090              :                 {
    2091            0 :                         UG_THROW("folgendes Gesicht in falscher Anztahl gefunden " << nextFaceFound << std::endl);
    2092              :                 }
    2093              : 
    2094            0 :                 for( std::vector<Face*>::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ )
    2095              :                 {
    2096            0 :                         Face * iFa = *itFac;
    2097              : 
    2098            0 :                         if( FaceContains(iFa, startEdg ) )
    2099              :                         {
    2100              :                                 startFace = iFa;
    2101              :                                 break;
    2102              :                         }
    2103              :                 }
    2104              : 
    2105              : 
    2106              :         }
    2107              : 
    2108            0 :         if( vVFT.size() != 0 )
    2109              :         {
    2110            0 :                 UG_THROW("not all triples found! " << std::endl);
    2111              :         }
    2112              : 
    2113            0 :         if( aF.size() != 0 )
    2114            0 :                 UG_THROW("not all faces found " << std::endl);
    2115              : 
    2116              : //      if( startEdg != originalStartEdge )
    2117            0 :         if( startEdg != targetedEndEdge )
    2118              :         {
    2119            0 :                 UG_THROW("wir sind nicht am Anfang wieder angekommen" << std::endl);
    2120              :         }
    2121              : 
    2122              : 
    2123            0 :         if( segmentPart.size() != 0 )
    2124              :         {
    2125            0 :                 UG_THROW("die Segmentteile muessen alle verarbeitet sein"  << std::endl);
    2126              :         }
    2127              : 
    2128              :         UG_LOG("Kreislauf geschlossen" << std::endl);
    2129              : 
    2130              : 
    2131              :         return true;
    2132            0 : }
    2133              : 
    2134              : 
    2135            0 : void teachAssoFacesNewVrtx( VecVertexOfFaceInfo const & segPart, Grid::FaceAttachmentAccessor<AttVrtVec> & aaVrtVecFace,
    2136              :                                                         Vertex * const & crossPt, Vertex * const & newShiftVrtx )
    2137              : {
    2138            0 :         for( VertexOfFaceInfo const & vertFracInfoSeg : segPart )
    2139              :         {
    2140              :                 Face * fac = vertFracInfoSeg.getFace();
    2141              : 
    2142              : //                                              sh.assign_subset(fa,newSubsToAdd);
    2143              : 
    2144              :                 // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu SR! nicht später falsche verwenden!
    2145              :                 vector<Vertex*>& newVrts4Fac = aaVrtVecFace[ fac ];
    2146              : 
    2147              :                 IndexType vrtxFnd = 0;
    2148              : 
    2149            0 :                 for(size_t indVrt = 0; indVrt < (fac)->num_vertices();  indVrt++ )
    2150              :                 {
    2151            0 :                         Vertex* facVrt = (fac)->vertex(indVrt);
    2152              : 
    2153            0 :                         if(  facVrt == crossPt )
    2154              :                         {
    2155            0 :                                 newVrts4Fac[ indVrt ] = newShiftVrtx;
    2156            0 :                                 vrtxFnd++;
    2157              : 
    2158              :                         }
    2159              :                 }
    2160              : 
    2161            0 :                 if( vrtxFnd <= 0 )
    2162              :                 {
    2163            0 :                         UG_THROW("vertex not found kreuzung!" << std::endl);
    2164              :                                                                                         }
    2165            0 :                 else if( vrtxFnd > 1 )
    2166              :                 {
    2167            0 :                         UG_THROW("vertex zu oft gefunden kreuzung " << vrtxFnd << std::endl );
    2168              :                 }
    2169              :                 else if ( vrtxFnd == 1 )
    2170              :                 {
    2171              :                 }
    2172              :                 else
    2173              :                 {
    2174              :                         UG_THROW("vertex finden komisch kreuzung " << std::endl);
    2175              :                 }
    2176              : 
    2177              :         }
    2178              : 
    2179            0 : }
    2180              : 
    2181              : 
    2182              : 
    2183              : #ifndef WORKAROUND_ARTE_SEGFAULT
    2184              : #define WORKAROUND_ARTE_SEGFAULT 1
    2185              : #endif
    2186              : 
    2187              : #ifndef ESTABLISH_DEBUG_SUDOS
    2188              : #define ESTABLISH_DEBUG_SUDOS 0
    2189              : #endif
    2190              : 
    2191              : #ifndef FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE
    2192              : #define FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE 0
    2193              : #endif
    2194              : 
    2195            0 : bool ExpandFractures2dArte( Grid& grid, SubsetHandler& sh, vector<FractureInfo> const & fracInfos,
    2196              : //                                              bool expandInnerFracBnds, bool expandOuterFracBnds
    2197              :                                                 bool useTrianglesInDiamonds, bool establishDiamonds
    2198              : )
    2199              : {
    2200              : 
    2201              :         constexpr bool expandInnerFracBnds = false;
    2202              :         constexpr bool expandOuterFracBnds = true;
    2203              : 
    2204              : //      for(EdgeIterator iter = sh.begin<Edge>(1); iter != sh.end<Edge>(1); ++iter)
    2205              : //      {
    2206              : //              size_t sm = sh.num_subsets();
    2207              : //
    2208              : //              sh.assign_subset(*iter,sm);
    2209              : //
    2210              : //              SplitEdge<RegularVertex>(grid,*iter,true);
    2211              : //
    2212              : //              UG_LOG("vertex gesplittet" << std::endl);
    2213              : //
    2214              : //              return true;
    2215              : //
    2216              : //      }
    2217              : 
    2218              : 
    2219              : //      static constexpr bool dehneInnereKluftGrenzpunkteAus = false;
    2220              : 
    2221              : //      expandInnerFracBnds = false;
    2222              : 
    2223              : //      expandOuterFracBnds = true;
    2224              : 
    2225              : //      access position attachment
    2226            0 :         if(!grid.has_vertex_attachment(aPosition)){
    2227              :                 UG_LOG("Error in ExpandFractures 2D Arte: Missing position attachment");
    2228            0 :                 return false;
    2229              :         }
    2230              :         Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPosition);
    2231              : 
    2232            0 :         if(!grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES)){
    2233              :                 UG_LOG("WARNING in Arte 2D CalculateCreaseNormal: grid option FACEOPT_AUTOGENERATE_EDGES autoenabled.\n");
    2234            0 :                 grid.enable_options(FACEOPT_AUTOGENERATE_EDGES);
    2235              :         }
    2236              : 
    2237              : 
    2238              : 
    2239              : //      objects for temporary results
    2240            0 :         FaceDescriptor fd;
    2241              :         vector<Edge*> edges; // used for temporary results.
    2242              :         vector<Face*> faces; // used for temporary results.
    2243              : 
    2244              : //      vectors that allow to access fracture properties by subset index
    2245            0 :         vector<FractureInfo> fracInfosBySubset(sh.num_subsets(), FractureInfo(-1, -1, 0));
    2246            0 :         for(size_t i = 0; i < fracInfos.size(); ++i){
    2247            0 :                 if(fracInfos[i].subsetIndex >= sh.num_subsets()){
    2248            0 :                         throw(UGError("Bad subsetIndex in given fracInfos."));
    2249              :                 }
    2250              : 
    2251            0 :                 fracInfosBySubset[fracInfos[i].subsetIndex] = fracInfos[i];
    2252              :         }
    2253              : 
    2254              : ////////////////////////////////
    2255              : //      Collect surrounding faces of all fractures in a selector
    2256              : //      and select edges and vertices too.
    2257            0 :         Selector sel(grid);
    2258            0 :         sel.enable_autoselection(false);
    2259            0 :         sel.enable_selection_inheritance(false);
    2260              : 
    2261              : #if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE
    2262              :         AInt aAdjMarker;        // used to mark how many adjacent fractures a vertex has.
    2263              :                                                 // 0: no frac, 1: frac-boundary, >1: inner frac vertex
    2264              :         // TODO FIXME das sieht komisch aus, ist das immer so, wenn z.B. an einer Grenze sich zwei fracs treffen?
    2265              :         grid.attach_to_vertices_dv(aAdjMarker, 0);
    2266              :         Grid::VertexAttachmentAccessor<AInt> aaMarkVRT(grid, aAdjMarker);
    2267              :         grid.attach_to_edges_dv(aAdjMarker, 0);
    2268              :         Grid::EdgeAttachmentAccessor<AInt> aaMarkEDGE(grid, aAdjMarker);
    2269              : #endif
    2270              : 
    2271              : //      using IndexType = unsigned short;
    2272              :         using AttVerFracProp = Attachment<VertexFractureProperties<IndexType> >;
    2273              :         // attachment pair boundary is fracture, number fractures crossing
    2274              : 
    2275              :         AttVerFracProp aAdjMarkerVFP;
    2276              : 
    2277              :         VertexFractureProperties<IndexType> vfp0( false, 0 );
    2278              :         // default value: no boundary fracture, no fractures crossing
    2279              : 
    2280              :         grid.attach_to_vertices_dv(aAdjMarkerVFP, vfp0 );
    2281              :         Grid::VertexAttachmentAccessor<AttVerFracProp> aaMarkVrtVFP(grid, aAdjMarkerVFP);
    2282              : 
    2283              :         ABool aAdjMarkerB; // used to know if an edge is frac edge
    2284            0 :         grid.attach_to_edges_dv(aAdjMarkerB, false);
    2285              :         Grid::EdgeAttachmentAccessor<ABool> aaMarkEdgeB(grid, aAdjMarkerB);
    2286              : 
    2287              : 
    2288              :         // die Vertizes, Faces und Edges, die mit einer Kluft zu tun haben
    2289              : 
    2290              : //      using VertFracTrip = VertexFractureTriple<Edge*, Face*, vector3>;
    2291              : //
    2292              : //      using VecVertFracTrip = std::vector<VertFracTrip>;
    2293              : 
    2294              :         VecVertFracTrip vertexNoInfo;
    2295              : 
    2296              :         using AttVecVertFracTrip = Attachment<VecVertFracTrip>;
    2297              : 
    2298              :         AttVecVertFracTrip aAdjInfoAVVFT;
    2299              : 
    2300              :         grid.attach_to_vertices_dv( aAdjInfoAVVFT, vertexNoInfo );
    2301              :         Grid::VertexAttachmentAccessor<AttVecVertFracTrip> aaVrtInfoFraTri(grid,  aAdjInfoAVVFT );
    2302              : 
    2303              : 
    2304              : //      using VecEdge = std::vector<Edge*>;
    2305              : //      using VecFace = std::vector<Face*>;
    2306              : 
    2307              :         using AttVecEdge = Attachment<VecEdge>;
    2308              :         using AttVecFace = Attachment<VecFace>;
    2309              : 
    2310              :         VecEdge noEdge;
    2311              :         VecFace noFace;
    2312              :         AttVecEdge aAdjInfoEdges;
    2313              :         AttVecFace aAdjInfoFaces;
    2314              : 
    2315              :         grid.attach_to_vertices_dv( aAdjInfoEdges, noEdge );
    2316              :         Grid::VertexAttachmentAccessor<AttVecEdge> aaVrtInfoAssoEdges( grid, aAdjInfoEdges );
    2317              : 
    2318              :         grid.attach_to_vertices_dv( aAdjInfoFaces, noFace );
    2319              :         Grid::VertexAttachmentAccessor<AttVecFace> aaVrtInfoAssoFaces( grid, aAdjInfoFaces );
    2320              : 
    2321              : 
    2322              :         // das ist Käse, ich brauche für jeden Vertex ein Attachment der Form
    2323              :         // class VertexTriple, bzw std vektoren von solchen vertex triplen
    2324              :         // da weiss dann jeder Vertex das triple
    2325              :         // Kante (damit subdom) - Face - normal (von Kante in Face rein)
    2326              :         // dann kann man nämlich anhand des Winkels von zwei Normalen
    2327              :         // von solchen Vertizes bestimmtn, ob sie auf die gleiche Seite der Kante zeigen
    2328              :         // und dann kann man sie mitteln, sofern die Vertizes keine Kreuzungs Vertizes sind
    2329              :         // oder keine äusseren Vertizes - ob sie dsa sind, dafür haben wir schon attachments!
    2330              : 
    2331              :         // TODO FIXME diese komischen accessoren sollen jetzt so zugewiesen
    2332              :         // werden, dass
    2333              :         /*
    2334              :          * jeder Kluftvertex soll wissen, welche Kluftedges ihm anliegen, und welche faces
    2335              :          * jede Kluftedge soll wissen, welche Vertizes ihr anliegen, und welche faces
    2336              :          * jedes Face, das an eine Kluft anliegt, soll wissen, welche Vertizes und Edges
    2337              :          * ihm anliegen
    2338              :          * letzteres muss man vielleicht noch ausdehnen, indem man subdomain indizes
    2339              :          * dazu bringt
    2340              :          * das kann auch notwendig sein fuer alle anderen - wirklich?
    2341              :          * die edges und faces kennen ihre subdomain
    2342              :          * nur beim Vertex kann in Kreuzungspunkten ein Problem sein
    2343              :          * zudem ist die subdomain der faces EGAL, im Zweifel entscheidet die subdomain
    2344              :          * der edges, die anliegen bzw der edge, die anliegt!
    2345              :          *
    2346              :          */
    2347              : 
    2348              : //      iterate over the given fracture infos and select all fracture edges
    2349              : //      and fracture vertices.
    2350            0 :         for(size_t i_fi = 0; i_fi < fracInfos.size(); ++i_fi)
    2351              :         {
    2352            0 :                 int fracInd = fracInfos[i_fi].subsetIndex;
    2353              : 
    2354            0 :                 for(EdgeIterator iter = sh.begin<Edge>(fracInd); iter != sh.end<Edge>(fracInd); ++iter)
    2355              :                 {
    2356              :                 //      mark edge and vertices
    2357              :                         sel.select(*iter);
    2358              : 
    2359              : #if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE
    2360              :                         aaMarkEDGE[*iter] = 1;
    2361              : #endif
    2362              : 
    2363              :                         aaMarkEdgeB[*iter] = true;
    2364              : 
    2365              :                 //      select associated vertices
    2366            0 :                         for(size_t i = 0; i < 2; ++i)
    2367              :                         {
    2368            0 :                                 Vertex* v = (*iter)->vertex(i);
    2369              :                                 sel.select(v);
    2370              : 
    2371              :                                 // wird in jedem Fall inkrimiert, da der Vertex auf jeden Fall mit einer Kante einer frac verbunden sein muss, sonst darf der loop gar nicht darüber gehen
    2372              :                                 aaMarkVrtVFP[v]++;
    2373              : 
    2374            0 :                                 if( IsBoundaryVertex2D(grid, v) )
    2375              :                                         aaMarkVrtVFP[v].setIsBndFracVertex();
    2376              : 
    2377              : 
    2378              : #if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE
    2379              :                                 // das ist Sebastians loop, den nicht mehr lassen lassen
    2380              :                                 //      if fracture boundaries are expanded, we'll regard all fracture vertices
    2381              :                                 //      as inner vertices
    2382              :                                 if(expandInnerFracBnds)
    2383              :                                 {
    2384              :                                         if(!expandOuterFracBnds)
    2385              :                                         {
    2386              :                                                 if(IsBoundaryVertex2D(grid, v))
    2387              :                                                         aaMarkVRT[v]++;
    2388              :                                                 else
    2389              :                                                         aaMarkVRT[v] = 2;
    2390              :                                         }
    2391              :                                         else
    2392              :                                                 aaMarkVRT[v] = 2;
    2393              :                                 }
    2394              :                                 else
    2395              :                                         aaMarkVRT[v]++;
    2396              : #endif
    2397              : 
    2398              :                         }
    2399              :                 }
    2400              :         }
    2401              : 
    2402              : 
    2403              : #if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE
    2404              : //      Make sure that selected vertices that lie on the boundary of the geometry
    2405              : //      are treated as inner fracture vertices.
    2406              : //      This is only required if frac-boundaries are not expanded anyways.
    2407              :         if(expandOuterFracBnds && !expandInnerFracBnds){
    2408              :                 for(VertexIterator iter = sel.vertices_begin();
    2409              :                         iter != sel.vertices_end(); ++iter)
    2410              :                 {
    2411              :                         Vertex* v = *iter;
    2412              :                         if(aaMarkVRT[v] == 1){
    2413              :                                 if(IsBoundaryVertex2D(grid, v))
    2414              :                                         aaMarkVRT[v] = 2;
    2415              :                         }
    2416              :                 }
    2417              :         }
    2418              :         // TODO FIXME was soll das fuer ein Kaese sein?
    2419              : #endif
    2420              : 
    2421              :         int dbg_flachen_passiert = 0;
    2422              : 
    2423            0 :         for(VertexIterator iter = sel.begin<Vertex>(); iter != sel.end<Vertex>(); ++iter)
    2424              :         {
    2425              : 
    2426              :                 bool wahl = true;
    2427              : 
    2428              : 
    2429              :                 // so stimmt es vielleicht, aber ist auch ein komischer Fall, innen expandieren und aussen nicht...... die Frage ist, ob es oonst Sinn macht.....
    2430              :                 if( expandInnerFracBnds && !expandOuterFracBnds && aaMarkVrtVFP[*iter].getIsBndFracVertex() )
    2431              :                         wahl = false;
    2432              : 
    2433              :                 // DEBUG ASSERT TEST static_assert( std::is_same< decltype(*iter), Vertex * >::value );
    2434              : 
    2435              :                 bool isBnd = aaMarkVrtVFP[ *iter ].getIsBndFracVertex();
    2436              :                 auto numCrosFrac = aaMarkVrtVFP[ *iter ].getNumberFracEdgesInVertex();
    2437              : 
    2438            0 :                 if( ! isBnd && numCrosFrac == 1 )
    2439              :                 {
    2440              :                         wahl = false;
    2441              :                 }
    2442              : 
    2443              : //              if( ! dehneInnereKluftGrenzpunkteAus )
    2444              : //              {
    2445              : //                      if( numCrosFrac == 1 ) // inner frac boundary vertex
    2446              : //                      {
    2447              : //                              wahl = false;
    2448              : //                      }
    2449              : //              }
    2450              : 
    2451              : 
    2452              :                 if( wahl )
    2453              :                 {
    2454            0 :                         sel.select(grid.associated_edges_begin(*iter),
    2455              :                                                 grid.associated_edges_end(*iter));
    2456            0 :                         sel.select(grid.associated_faces_begin(*iter),
    2457              :                                                 grid.associated_faces_end(*iter));
    2458              : 
    2459              :                         // TODO FIXME hier ein attachment der associated faces und vertizes, am besten als Klasse, die std vertizes davon frisst, an jeden Vertex anhängen
    2460              :                         // so muss man später nicht nochmal über alle Faces und Edges laufen, sondern hat die angehängten schon zur Hand
    2461              :                         // im Fall, dass eine Kreuzung vorliegt, das Ganze irgendwann ordnen, dass nebeneinander liegende Faces und edges in eine verkettete Liste kommen
    2462              :                         // vielleicht das aber nur bei den Schnittvertizes später
    2463              :                         // und vielleicht sollen die Faces Zeiger auf ihre Edges bekommen, und die edges auf die faces, aber wird irgendwann zu wild verzeigert.....
    2464              :                         // vielleicht einfach attachment von faces und edges unabhängig an jeden Fracture Vertex......
    2465              : 
    2466              :                         // testen, ob ein Schnittvertex vor liegt, indem die Anzahl der touches getestet wird, anhand einfacher Geometrien testen, was die Anzahl ist
    2467              : 
    2468              :                         // mit UG_LOG ausgeben, was die Koordinaten sind, und die Anzahl der hits
    2469              : 
    2470              :                         VecFace assFac;
    2471              :                         VecEdge assEdg;
    2472              : 
    2473              : //                      UG_LOG("----------" << std::endl);
    2474              : 
    2475            0 :                         for( std::vector<Face *>::iterator iterFac = grid.associated_faces_begin(*iter); iterFac != grid.associated_faces_end(*iter); iterFac++ )
    2476              :                         {
    2477            0 :                                 assFac.push_back(*iterFac);
    2478              : //                              vector3 facCenter = CalculateCenter( *iterFac, aaPos );
    2479              : //                              UG_LOG("fac center " << facCenter << std::endl);
    2480              : 
    2481              : //                              sh.assign_subset(*iterFac, 10);
    2482              :                         }
    2483              : 
    2484              : //                      UG_LOG("----------" << std::endl);
    2485              : 
    2486            0 :                         for( std::vector<Edge *>::iterator iterEdg = grid.associated_edges_begin(*iter); iterEdg != grid.associated_edges_end(*iter); iterEdg++ )
    2487              :                         {
    2488            0 :                                 assEdg.push_back(*iterEdg);
    2489              : //                              sh.assign_subset(*iterEdg,10);
    2490              :                         }
    2491              : 
    2492            0 :                         aaVrtInfoAssoFaces[*iter] = assFac;
    2493            0 :                         aaVrtInfoAssoEdges[*iter] = assEdg;
    2494              : 
    2495            0 :                         UG_LOG("marked vertex wahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl );
    2496              : 
    2497              :                         // fuer Nicht Boundary Vertizes muessen wir durch 2 teilen, damit wir richtige Anzahl der
    2498              :                         // Fracs haben, die durch den spezifischen Vertex durch geht
    2499              :                         // FALSCH war mal so, ist schon abgestellt, es wird angezeigt, wieviele Ecken von Kanten rein kommen
    2500              : 
    2501            0 :                 }
    2502              :                 else
    2503              :                 {
    2504            0 :                         UG_LOG("marked vertex unwahl: " << aaPos[*iter] << " is bnd " << isBnd << " number cross frac " << numCrosFrac << std::endl );
    2505              :                 }
    2506              : 
    2507              :         }
    2508              : 
    2509              : //      return true;
    2510              : 
    2511              :         using pairIndDbl = std::pair<IndexType,double>;
    2512              : 
    2513              :         std::vector< pairIndDbl > fracSubdom_facePerpendMinVal;
    2514              : 
    2515            0 :         for( auto const & pf: fracInfos )
    2516              :         {
    2517            0 :                 fracSubdom_facePerpendMinVal.push_back( pairIndDbl( pf.subsetIndex, std::numeric_limits<double>::max() ) );
    2518              :         }
    2519              : 
    2520              :         T_min<double> minDistPerpOverall( std::numeric_limits<double>::max() );
    2521              : 
    2522              : //      for( auto fI : fracInfos )
    2523              : //      for( size_t fraInfInd = 0; fraInfInd < fracInfos.size(); fraInfInd++ )
    2524            0 :         for( auto & fsfpmv : fracSubdom_facePerpendMinVal )
    2525              :         {
    2526              : //              int fracInd = fracInfos[fraInfInd].subsetIndex;
    2527              : //              int fracInd = fI.subsetIndex;
    2528              : 
    2529            0 :                 auto fracInd = fsfpmv.first;
    2530              : 
    2531            0 :                 T_min<double> minDistPerpThisFrac( fsfpmv.second );
    2532              : 
    2533            0 :                 for(EdgeIterator iterEdg = sh.begin<Edge>(fracInd); iterEdg != sh.end<Edge>(fracInd); iterEdg++ )
    2534              :                 {
    2535              : 
    2536              :                         // get subdomain of edge
    2537              : 
    2538            0 :                         auto sudoEdg = sh.get_subset_index(*iterEdg);
    2539              : 
    2540              :                         // sieht quasi doppelt gemoppelt aus
    2541            0 :                         if( sudoEdg != fracInd )
    2542            0 :                                 UG_THROW("Subdomain Index Fehler " << std::endl);
    2543              : 
    2544              :                         // DEBUG ASSERT TEST static_assert( std::is_same< decltype(sudoEdg), int >::value );
    2545              : 
    2546              :                         // get vertices of edge, always 2
    2547              : 
    2548              :                         std::vector<Vertex* > verticesEdg;
    2549              : 
    2550              :                         // DEBUG ASSERT TEST static_assert( std::is_same< Vertex*, decltype( (*iterEdg)->vertex(0) ) >::value );
    2551              : 
    2552            0 :                         for( size_t i = 0; i < 2; ++i )
    2553            0 :                                 verticesEdg.push_back( (*iterEdg)->vertex(i) );
    2554              : 
    2555              :                         // get attached faces
    2556              : 
    2557              : #if 0
    2558              :                         std::vector<Face* > assFace;
    2559              : 
    2560              :                         // TODO FIXME dieser loop kann vielleicht vereinfacht werden, wenn dieser ganze loop umgebaut wird
    2561              :                         // denn die Vertizes kennen dann die assosciated faces schon
    2562              :                         // der Name AssociatedFaceIterator ist sowieso verwirrend, hat mit assosciated nix zu tun, bezieht sich auf alle std Vektoren von Face *
    2563              :                         UG_LOG("XXXXXXXXXXXX" << std::endl);
    2564              :                         for(Grid::AssociatedFaceIterator iterAFI = grid.associated_faces_begin( verticesEdg[0] );
    2565              :                                 iterAFI != grid.associated_faces_end( verticesEdg[0] );
    2566              :                                 iterAFI++ )
    2567              :                         {
    2568              : 
    2569              :                                 if(FaceContains( *iterAFI, *iterEdg ))
    2570              :                                 {
    2571              :                                         assFace.push_back( *iterAFI );
    2572              : 
    2573              : 
    2574              :                                         vector3 facCenter = CalculateCenter( *iterAFI, aaPos );
    2575              :                                         UG_LOG("fac center " << facCenter << std::endl);
    2576              : 
    2577              : 
    2578              : 
    2579              : //                                      sh.assign_subset( *iterAFI, sh.get_subset_index(*iterEdg));
    2580              :                                 }
    2581              : 
    2582              :                         }
    2583              :                         UG_LOG("XXXXXXXXX" << std::endl);
    2584              : #else
    2585              : 
    2586            0 :                         std::vector<Face* > & assFaceVrt0 = aaVrtInfoAssoFaces[verticesEdg[0]];
    2587              : 
    2588              :                         std::vector<Face* > assFace;
    2589              : 
    2590              : //                      // DEBUG ASSERT TEST static_assert( std::is_same< decltype( aaVrtInfoAssoFaces[verticesEdg[0]] )[0], std::vector<Face *> >::value );
    2591              :                         //// DEBUG ASSERT TEST static_assert( std::is_same< decltype( *(aaVrtInfoAssoFaces[verticesEdg[0]]) ), Face * >::value );
    2592              : 
    2593              : //                      UG_LOG("XXXXXXXXXXXX" << std::endl);
    2594              : 
    2595            0 :                         for( auto const & ifa : assFaceVrt0 )
    2596              :                         {
    2597            0 :                                 if(FaceContains( ifa, *iterEdg ))
    2598              :                                 {
    2599            0 :                                         assFace.push_back( ifa );
    2600              : 
    2601              : //                                      vector3 facCenter = CalculateCenter( ifa, aaPos );
    2602              : //                                      UG_LOG("fac center " << facCenter << std::endl);
    2603              :                                 }
    2604              :                         }
    2605              : 
    2606            0 :                         std::vector<Face* > & assFaceVrt1 = aaVrtInfoAssoFaces[verticesEdg[1]];
    2607              : 
    2608            0 :                         for( auto const & ifa : assFaceVrt1 )
    2609              :                         {
    2610            0 :                                 if(FaceContains( ifa, *iterEdg ))
    2611              :                                 {
    2612              :                                         bool faceContained = false;
    2613              : 
    2614            0 :                                         for( auto const & afa : assFace )
    2615              :                                         {
    2616            0 :                                                 if( afa == ifa )
    2617              :                                                         faceContained = true;
    2618              :                                         }
    2619              : 
    2620            0 :                                         if( !faceContained )
    2621              :                                         {
    2622              :                                                 bool faceAlreadyIncluded = false;
    2623              : 
    2624            0 :                                                 for( auto const & af : assFace )
    2625              :                                                 {
    2626            0 :                                                         if( ifa == af )
    2627              :                                                                 faceAlreadyIncluded = true;
    2628              :                                                 }
    2629              : 
    2630            0 :                                                 if( ! faceAlreadyIncluded )
    2631            0 :                                                         assFace.push_back( ifa );
    2632              :                                         }
    2633              :                                 }
    2634              :                         }
    2635              : 
    2636              : 
    2637              : //                      UG_LOG("XXXXXXXXX" << std::endl);
    2638              : 
    2639              : #endif
    2640              :                         // von hier lernen:
    2641              :                         //      VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV ist verticesEdg[0] ];
    2642              :                         //              for( auto const & ifac : assoFaces )
    2643              :                         //              {
    2644              :                         //                      // DEBUG ASSERT TEST static_assert( std::is_same< decltype( ifac ), Face * const & >::value );
    2645              :                         //              }
    2646              : 
    2647              : 
    2648              : 
    2649              :                         // compute normal of edge
    2650              : 
    2651              :                         std::vector< vector3 > edgeNormals;
    2652              : 
    2653              :                         std::vector<double> perpendDistances;
    2654              : 
    2655            0 :                         for( auto const & fac : assFace )
    2656              :                         {
    2657            0 :                                 vector3 facCenter = CalculateCenter( fac, aaPos );
    2658              : 
    2659              :                                 vector3 perpendicu;
    2660              : 
    2661            0 :                                 DropAPerpendicular(perpendicu, facCenter, aaPos[verticesEdg[0]], aaPos[verticesEdg[1]]);
    2662              : 
    2663            0 :                                 double perpendDist = VecLength( perpendicu ); // betrag perpendicu
    2664              : 
    2665            0 :                                 perpendDistances.push_back( perpendDist );
    2666              : 
    2667              :                                 minDistPerpThisFrac( perpendDist );
    2668              : 
    2669              : 
    2670              :                         //      vector from projection to center is the unnormalized normal
    2671              :                                 vector3 tmpN;
    2672              : 
    2673              :                                 VecSubtract(tmpN, facCenter, perpendicu );
    2674              : 
    2675            0 :                                 VecNormalize(tmpN, tmpN);
    2676              : 
    2677            0 :                                 edgeNormals.push_back( tmpN );
    2678              : 
    2679              :                                 // DEBUG ASSERT TEST static_assert( std::is_same< Edge*, decltype(*iterEdg) >::value );
    2680              : 
    2681              :                                 // DEBUG ASSERT TEST static_assert( std::is_same< Face * const &, decltype(fac) >::value );
    2682              :                                 // DEBUG ASSERT TEST static_assert( std::is_same< Face *, decltype( const_cast<Face*>(fac) ) >::value );
    2683              :                                 // DEBUG ASSERT TEST static_assert( std::is_same< vector3, decltype( tmpN ) >::value );
    2684              : 
    2685              :                                 VertFracTrip infoVertizesThisEdge( *iterEdg, fac, tmpN );
    2686              : 
    2687              : //                              UG_LOG("TypE Fac " << typeid(const_cast<Face*>(fac) ).name() << std::endl);
    2688              : //                              UG_LOG("TypE Edg " << typeid( *iterEdg ).name() << std::endl);
    2689              : //                              UG_LOG("TypE Vec " << typeid( tmpN ).name() << std::endl);
    2690              : 
    2691              : 
    2692            0 :                                 for( auto const & v : verticesEdg )
    2693              :                                 {
    2694              :                                         // DEBUG ASSERT TEST static_assert( std::is_same< decltype(v), Vertex * const & >::value );
    2695              :                                         // DEBUG ASSERT TEST static_assert( std::is_same< decltype(const_cast<Vertex*>(v)), Vertex *  >::value );
    2696            0 :                                         aaVrtInfoFraTri[v].push_back( infoVertizesThisEdge );
    2697              : 
    2698              : //                                      VecVertFracTrip allInfosVrtxThisEdg = aaVrtInfoFraTri[v];
    2699              : 
    2700              : //                                      // DEBUG ASSERT TEST static_assert( std::is_same< decltype(  aaVrtInfoFraTri[v] ),  VecVertFracTrip >::value );
    2701              : 
    2702              : //                                      UG_LOG("type Fac " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ).name() << std::endl);
    2703              : //                                      UG_LOG("type Edg " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ).name() << std::endl);
    2704              : //                                      UG_LOG("type Vec " << typeid( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ).name() << std::endl);
    2705              : 
    2706              :                                         // DEBUG ASSERT TEST static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getFace() ), Face * >::value );
    2707              :                                         // DEBUG ASSERT TEST static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getEdge() ), Edge * >::value );
    2708              :                                         // DEBUG ASSERT TEST static_assert( std::is_same< decltype( aaVrtInfoFraTri[v][ aaVrtInfoFraTri[v].size() - 1 ].getNormal() ), vector3 const >::value );
    2709              :                                 }
    2710              : 
    2711              :                         }
    2712              : 
    2713              :                         // damit speichern wir die plus und minus Normale, und das ist alles, und auch
    2714              :                         // gleich wieder weg
    2715              :                         // TODO FIXME besser, wir speichern die gemittelte Normale an den Vertizes
    2716              :                         // vielleihct als attachment pair, das die subdom kennt der frac und die Normale dazu?
    2717              :                         // ziemlich nutzlos, die Normale wie hier gemacht in einen kurzen Vektor zu speichern, der schnell
    2718              :                         // wieder weg ist......
    2719              :                         // wir brauchen alle Normalen zu jeder fracture an jedem fracture Vertex, also die Mittelung vermutlich
    2720              :                         // diese Mittelung kann aber erst stattfinden, wenn wir nachher über die vertizes loopen,
    2721              :                         // hier kennen wir nur die Vertizes, die an derselben Edge anliegen
    2722              : 
    2723            0 :                         UG_LOG("EDGE NORMALS: " << sh.get_subset_index(*iterEdg) << " -> ");
    2724              : 
    2725              :                         int j = 0;
    2726              : 
    2727            0 :                         for( auto const & en: edgeNormals )
    2728              :                         {
    2729              : 
    2730            0 :                                 for( size_t i = 0; i < 3; i++ )
    2731            0 :                                         UG_LOG( en[i] << ", "  );
    2732              : 
    2733              : 
    2734            0 :                                 UG_LOG(" --- " << perpendDistances[j] << " ///////// " );
    2735              : 
    2736            0 :                                 j++;
    2737              :                         }
    2738              : 
    2739              :                         UG_LOG(std::endl);
    2740              : 
    2741            0 :                 }
    2742              : 
    2743            0 :                 fsfpmv.second = minDistPerpThisFrac();
    2744              : 
    2745              :                 minDistPerpOverall( fsfpmv.second );
    2746              : 
    2747            0 :                 UG_LOG("first " << fsfpmv.first << " second " << fsfpmv.second << std::endl);
    2748              :         }
    2749              : 
    2750            0 :         for( auto const & fsfpmv : fracSubdom_facePerpendMinVal )
    2751              :         {
    2752            0 :                 UG_LOG("min dist sd " << fsfpmv.first << " -> " << fsfpmv.second << std::endl  );
    2753              :         }
    2754              : 
    2755              :         UG_LOG("overall min dist " << minDistPerpOverall() << std::endl);
    2756              : 
    2757              : 
    2758              : 
    2759              :         // von Sebastian teilweise das Prinzip übernommen, dass die Faces wissen können, was ihre neuen Vertizes sein sollen
    2760              :         //      create new vertices
    2761              : 
    2762              :         //      we have to associate a vector of vertices with each node in the fracture.
    2763              :         //      since an empty vector is quite small, we can associate one with each vertex in
    2764              :         //      the whole grid. This could be optimized if required, by using subset attachments.
    2765              : 
    2766              :         // es reicht vielleicht, hier statt einem Vektor einfach nur einen Vertex * zu storen
    2767              : //      using AttVrtVec = Attachment<vector<Vertex*> >;
    2768              :         AttVrtVec attVrtVec;
    2769              : 
    2770              :         //      we  associate a vector of vertices for each face adjacent to the frac.
    2771              :         //      it will store a set of vertices. An entry contains the new vertex, if the
    2772              :         //      corresponding vertex is an inner fracture vertex, and NULL if not.
    2773              :         grid.attach_to_faces(attVrtVec);
    2774              :         Grid::FaceAttachmentAccessor<AttVrtVec> aaVrtVecFace(grid, attVrtVec);
    2775              : 
    2776              : 
    2777              :         //      iterate over all surrounding faces to enable face changes, this loop taken from SR but shortened
    2778            0 :         for(FaceIterator iterSurrFac = sel.faces_begin(); iterSurrFac != sel.faces_end(); ++iterSurrFac )
    2779              :         {
    2780              :                 Face* sf = *iterSurrFac;
    2781              : 
    2782              :                 std::vector<Vertex*>& newVrts = aaVrtVecFace[sf];
    2783            0 :                 newVrts.resize(sf->num_vertices());
    2784              : 
    2785            0 :                 for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt)
    2786              :                 {
    2787            0 :                         newVrts[i_vrt] = nullptr;
    2788              :                 }
    2789              :                         // erstmal so tun, als ob keine neuen Vertizes erzeugt werden an den alten Vertizes
    2790              :         }
    2791              : 
    2792              : 
    2793              :         // attachment to allow fracture vertizes to know the newly created vertizes
    2794              :         // due to extrusion which are related to them, in connection with
    2795              :         // the normals which are an average of the related edges and the faces
    2796              :         // defining the original normal
    2797              : 
    2798              :         // usage: store edges and associated faces in SAME order in std vectors!
    2799              :         using ExpandVertexMultiplett = VertexFractureTriple< std::vector<Edge*>, std::vector<Face*>, vector3 >;
    2800              :         // holds the averaged normal of the related edges and their corresponding faces which give direction
    2801              : 
    2802              :         using VecExpandVertexMultiplett = std::vector<ExpandVertexMultiplett>;
    2803              : 
    2804              : 
    2805              :         VecExpandVertexMultiplett vertexMultiplettEmpty;
    2806              : 
    2807              :         using AttVecExpandVertexMultiplett = Attachment<VecExpandVertexMultiplett>;
    2808              : 
    2809              :         AttVecExpandVertexMultiplett aAdjInfoVVEVM;
    2810              : 
    2811              :         grid.attach_to_vertices_dv( aAdjInfoVVEVM, vertexMultiplettEmpty );
    2812              :         Grid::VertexAttachmentAccessor<AttVecExpandVertexMultiplett> aaVrtExpMP(grid, aAdjInfoVVEVM );
    2813              : 
    2814              : 
    2815              :         // am Ende dieser Prozedur sollten alle Vertizes wissen, welche Tripel vom Typ Edge - Face - Normal zum Face hin an ihnen angelagert sind
    2816              : 
    2817              :         // damit weiss, wenn es stimmt, jeder Vertex, der an einer Fracture ist, wieviele Schnittpunkte von Fractures er hat,
    2818              :         // ob er ein boundary vertex ist, und was für einen Vektor von Tripeln an ihm angehängt sind
    2819              :         // die subdomain der Fracture muss anhand der subdomain der edge bestimmt werden immer
    2820              : 
    2821              :         UG_LOG("loop over all marked vertizes " << std::endl);
    2822              : 
    2823              :         int dbg_vertizesPassiert = 0;
    2824              : 
    2825              : //      std::vector<Vertex *> crossVrts;
    2826              : //      std::vector<Vertex *> teeVrts;
    2827              : 
    2828              : //      using CrossVertInf = CrossingVertexInfo<Vertex*, IndexType, Edge*, Face* >;
    2829              : 
    2830              : //      std::vector<CrossingVertexInfo<Vertex*, IndexType> > vecCrossVrtInf;
    2831              :         std::vector<CrossVertInf > vecCrossVrtInf;
    2832              : 
    2833              : //      // needed for crossing points
    2834              : //      using VertexOfFaceInfo = VertexFractureTriple< std::pair<Edge*, Edge*>, Face*, std::pair<vector3,vector3> >;
    2835              : //      // all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges
    2836              : //      // the size of the normal vector vector also must be two
    2837              : //      // however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm
    2838              : //      // for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple
    2839              : //
    2840              : //      using VecVertexOfFaceInfo = std::vector<VertexOfFaceInfo>;
    2841              : //
    2842              : //      using SegmentsFractExtrus = std::vector<VecVertexOfFaceInfo>;
    2843              : 
    2844              : 
    2845              :         // jetzt können wir alle Vertizes ablaufen und an ihnen neue Vertizes erzeugen, die anhand der gemittelten Normalen von den Vertizes weg gehen
    2846              :         // ob zwei anhängende Faces auf der gleichen Seite liegen, wenn es kein Schnittvertex von zwei oder mehr Klüften ist
    2847              :         // das kann man anhand des Winkels zwischen zwei face Normalen unterscheiden vermutlich
    2848              :         // dabei müssen die edges sowieso disjunkt sein, sonst ist man sowieso sicher auf verschiedenen Seiten
    2849              :         // wenn wir es mit einem boundary Vertex zu tun haben, müssen wir weiter überlegen, wie wir die Verschiebung auf die äussere Kante projizieren
    2850              :         // muss auch mit dem Winkel zu tun haben
    2851            0 :         for(VertexIterator iterV = sel.begin<Vertex>(); iterV != sel.end<Vertex>(); ++iterV)
    2852              :         {
    2853              : 
    2854              :                 // POsition dieses Vertex
    2855              :                 vector3 posOldVrt = aaPos[*iterV];
    2856              : 
    2857              :                 // vielleicht muss man, wenn die neuen Vertizes da sind, diese auch gleich mit den umliegenden Knoten per neuer Kanten verbinden
    2858              :                 // und die neuen faces erzeugen nach Löschen der alten?
    2859              :                 // oder alle neuen Vertizes wie bei Prof Reiter in einen std Vektor, der als attachment den bisherigen Face Vertizes angehängt wird
    2860              :                 // und Edge Vernichtung und Erzeugung neuer edges und faces wie bei Prof Reiter in Folgeschritten?
    2861              : 
    2862              :                 VecVertFracTrip & vecVertFracTrip = aaVrtInfoFraTri[*iterV];
    2863              : 
    2864              :                 std::vector<Edge*> & allAssoEdges = aaVrtInfoAssoEdges[*iterV];
    2865              : 
    2866              :                 // DEBUG ASSERT TEST static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getFace() ), Face * >::value );
    2867              :                 // DEBUG ASSERT TEST static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getEdge() ), Edge * >::value );
    2868              :                 // DEBUG ASSERT TEST static_assert( std::is_same< decltype( vecVertFracTrip[ vecVertFracTrip.size() - 1 ].getNormal() ), vector3 const >::value );
    2869              : 
    2870            0 :                 for( auto const & vft : vecVertFracTrip )
    2871              :                 {
    2872              :                         // DEBUG ASSERT TEST static_assert( std::is_same< decltype( vft.getFace() ), Face * >::value );
    2873              :                         // DEBUG ASSERT TEST static_assert( std::is_same< decltype( vft.getEdge() ), Edge * >::value );
    2874              :                         // DEBUG ASSERT TEST static_assert( std::is_same< decltype( vft.getNormal() ), vector3 const >::value );
    2875              : 
    2876              :                         Face * f = vft.getFace();
    2877              :                         Edge * e = vft.getEdge();
    2878              :                         vector3 n = vft.getNormal();
    2879              : 
    2880              :                 }
    2881              : 
    2882              :                 using VvftIterator = VecVertFracTrip::iterator;
    2883              : 
    2884              :                 VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV];
    2885              :                 // TODO FIXME hier braucht man das nicht zu ordnen
    2886              :                 // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt
    2887              :                 // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind
    2888              : 
    2889              : //              for( auto const & ifac : assoFaces )
    2890              : //              {
    2891              : //                      // DEBUG ASSERT TEST static_assert( std::is_same< decltype( ifac ), Face * const & >::value );
    2892              : //              }
    2893              : 
    2894              : 
    2895              : 
    2896              :                 // Anzahl der Kreuzungspunkte auslesen und danach unterscheiden, erstmal keine Kreuzung! TODO FIXME
    2897              : 
    2898              :                 // irgendwie muessen wir diese Infos jetzt verwerten, um als erstes neue Vertizes zu erzeugen, anfangs für eine Kluft nur
    2899              :                 // und danach die alten Edges und faces löschen und an neuer Stelle neu erzeugen, plus die sowieso neuen,
    2900              :                 // oder Edges verschieben, wenn es möglich ist, die Vertizes zu verschieben, und die Edges und in Folge faces passen sich an,
    2901              :                 // dann müssen nur die neuen edges und faces neu erzeugt werden
    2902              :                 // verschieben der Position des Vertex löst Kaskade aus, dass Edge und Face auch verschoben werden, kann also angewendet werden
    2903              :                 // allerdings Problem, dass die Vertizes dafür verdoppelt werden müssen und die Kanten, sonst kann man sie nicht nach aussen verschieben
    2904              :                 // also doch komplette Neuerzeugung vermutlich..... oder doppeltes Klonen, und das alte bleibt in der Mitte.....
    2905              : 
    2906              :                 vector3 posThisVrt =  aaPos[*iterV];
    2907              : 
    2908            0 :                 UG_LOG("vertex at " << posThisVrt << std::endl );
    2909              : 
    2910              :                 bool vrtxIsBndVrt = aaMarkVrtVFP[*iterV].getIsBndFracVertex();
    2911              :                 // alternativ wäre möglich: IsBoundaryVertex2D(grid, *iterV)
    2912              : 
    2913              :                 UG_LOG("is bndry " << vrtxIsBndVrt << std::endl);
    2914              : 
    2915              :                 IndexType numFracsCrossAtVrt = aaMarkVrtVFP[*iterV].getNumberFracEdgesInVertex();
    2916              : 
    2917              :                 UG_LOG("number crossing fracs " << numFracsCrossAtVrt << std::endl);
    2918              : 
    2919              :                 size_t numbAttTripl = vecVertFracTrip.size();
    2920              : 
    2921              :                 UG_LOG("sizes of vft " << numbAttTripl << std::endl );
    2922              : 
    2923            0 :                 if( ! vrtxIsBndVrt )
    2924              :                 {
    2925              : 
    2926              : #if 0
    2927              :                         CrossVertInf crossVrtInf( *iterV, numFracsCrossAtVrt );
    2928              : 
    2929              :                         //                              using VecVertexOfFaceInfo = std::vector<VertexOfFaceInfo>;
    2930              :                         VecVertexOfFaceInfo orderedFaces;
    2931              : 
    2932              : //                              using SegmentsFractExtrus = std::vector<VecVertexOfFaceInfo>;
    2933              : 
    2934              :                         SegmentsFractExtrus segments;
    2935              :                         // single components always from one fracture edge to the next one
    2936              : 
    2937              :                         VecVertexOfFaceInfo segmentPart;
    2938              : 
    2939              :                         // note: we do not attach this info to the vertex, as we only need it local; in principle, in case of further need, it would
    2940              :                         // be usful to establish some sort of attachment
    2941              : 
    2942              :                         // fixed: diesen Sortierungsalgorithmus bei allen inneren Knoten anwenden,
    2943              :                         // um zweifelsfrei alle anhängenden Faces der richtigen Seite zuordnen zu können!!!!
    2944              : 
    2945              :                         // VecVertFracTrip & vecVertFracTrip = aaVrtInfoFraTri[*iterV];
    2946              :                         // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV];
    2947              : 
    2948              :                         IndexType startIndex = 0;
    2949              : 
    2950              :                         if( numFracsCrossAtVrt > 1 )
    2951              :                         {
    2952              :                                 determineOrderOfFaces( // crossVrtInf,
    2953              :                                                                                 vecVertFracTrip, assoFaces,  orderedFaces,
    2954              :                                                                                 segments, segmentPart, startIndex, allAssoEdges,
    2955              :                                                                                 sh, aaMarkEdgeB
    2956              :                                                                         );
    2957              :                         }
    2958              : #endif
    2959            0 :                         if( numFracsCrossAtVrt < 1 )
    2960              :                         {
    2961            0 :                                 UG_THROW("no fracs crossing but marked vertex? << std::endl");
    2962              :                         }
    2963            0 :                         else if( numFracsCrossAtVrt == 1 )
    2964              :                         {
    2965              : 
    2966              :                                 // do nothing
    2967              : 
    2968              : //                              if( numbAttTripl != 0 )
    2969              : //                              {
    2970              : //                                      UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand, Kluftende " << std::endl);
    2971              : //                              }
    2972              : 
    2973              : 
    2974              : 
    2975              :                                 UG_LOG("END THIS VERTEX NORMAL INNER ENDING CLEFT" << std::endl);
    2976              : 
    2977              : 
    2978              : //                              if( ! dehneInnereKluftGrenzpunkteAus )
    2979              : //                              {
    2980              : //                                      break;
    2981              : //                              }
    2982              :                                 // inner vertex where fracture ends
    2983              :                                 // TODO FIXME
    2984              : 
    2985              :                                 // in this case, we have two attached edges, and each of these edges has two attached faces
    2986              :                                 // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges
    2987              : 
    2988              : #if 0
    2989              : 
    2990              :                                 if( numbAttTripl != 2 )
    2991              :                                 {
    2992              :                                         UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand, Kluftende " << std::endl);
    2993              :                                 }
    2994              : 
    2995              :                                 // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind
    2996              : 
    2997              :                                 // und gleich auch Erzeugung der neuen Knoten, die dann
    2998              :                                 // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes
    2999              :                                 // angehängt werden; der Winkel zur Normalen hilft später, die Seite
    3000              :                                 // heraus zu finden, Seite von den Edges
    3001              : 
    3002              :                                 int dbg_iteratorAblaufen = 0;
    3003              : 
    3004              : 
    3005              : #if WORKAROUND_ARTE_SEGFAULT
    3006              : 
    3007              :                                 int dbg_laenge = 0;
    3008              : 
    3009              :                                 for( auto const & vft : vecVertFracTrip )
    3010              :                                 {
    3011              :                                         dbg_laenge++;
    3012              : 
    3013              :                                         UG_LOG("VERTEXFRACTRIP" << std::endl);
    3014              : 
    3015              :                                         vector3 ve = vft.getNormal();
    3016              : 
    3017              :                                         UG_LOG("NORMAL " << ve << std::endl);
    3018              : 
    3019              :                                         UG_LOG("laenge " << dbg_laenge << std::endl );
    3020              :                                 }
    3021              : 
    3022              :                                 int dbg_laenge_eins = 0;
    3023              : 
    3024              : #endif
    3025              : 
    3026              : 
    3027              : 
    3028              :                                 for( VvftIterator vvftV = vecVertFracTrip.begin();
    3029              :                                                 vvftV != vecVertFracTrip.end();
    3030              :                                                 vvftV++
    3031              :                                 )
    3032              :                                 {
    3033              : 
    3034              : #if WORKAROUND_ARTE_SEGFAULT
    3035              :                                         dbg_laenge_eins++;
    3036              : 
    3037              :                                         if( dbg_laenge_eins > dbg_laenge )
    3038              :                                         {
    3039              :                                                 break;
    3040              :                                         }
    3041              : 
    3042              : #endif
    3043              : 
    3044              :                                         vector3 nV = vvftV->getNormal();
    3045              : 
    3046              :                                         Edge * edgeV = vvftV->getEdge();
    3047              : 
    3048              : 
    3049              : 
    3050              : #if WORKAROUND_ARTE_SEGFAULT
    3051              : 
    3052              :                                         UG_LOG("NORMAL " << vvftV->getNormal() << std::endl);
    3053              :                                         UG_LOG("LAENGE EINZ " << dbg_laenge_eins << std::endl );
    3054              : #endif
    3055              : 
    3056              :                                         Vertex * nextFracVrt;
    3057              : 
    3058              :                                         IndexType foundThisVrt = 0;
    3059              : 
    3060              :                                         for( size_t i = 0; i < 2; ++i )
    3061              :                                         {
    3062              :                                                 Vertex * vrtEdgEnd = edgeV->vertex(i);
    3063              : 
    3064              :                                                 if( vrtEdgEnd == *iterV )
    3065              :                                                 {
    3066              :                                                         foundThisVrt++;
    3067              :                                                 }
    3068              :                                                 else
    3069              :                                                 {
    3070              :                                                         nextFracVrt = vrtEdgEnd ;
    3071              :                                                 }
    3072              : 
    3073              :                                         }
    3074              : 
    3075              :                                         if( foundThisVrt != 1 )
    3076              :                                         {
    3077              :                                                 UG_THROW("zu viel zu wenig vertizex one " << std::endl);
    3078              :                                         }
    3079              : 
    3080              : 
    3081              : 
    3082              :                                         // Klasse schreiben, die als attachment an einen Fracture-Vertex
    3083              :                                         // die neuen Vertizes samt ihrer gemittelten Normalen speichert
    3084              :                                         // also std::vector von dieser neuen Klasse als Vertex attachment
    3085              : 
    3086              :                                         std::vector<Edge * > attEdg;
    3087              :                                         std::vector<Face * > attFac;
    3088              : 
    3089              :                                         attEdg.push_back( edgeV );
    3090              : 
    3091              :                                         Face * facV = vvftV->getFace();
    3092              : 
    3093              :                                         attFac.push_back( facV );
    3094              : 
    3095              :                                         // jetzt neuen Vertex erzeugen in Richtung der Normalen
    3096              :                                         // sonst ist das attachment Schwachsinn!
    3097              : 
    3098              :                                         vector3 posNewVrt;
    3099              : 
    3100              :                                         vector3 moveVrt;
    3101              : 
    3102              :                                         auto subsIndEdgV = sh.get_subset_index(edgeV);
    3103              : 
    3104              :                                         number width = fracInfosBySubset.at(subsIndEdgV).width;
    3105              : 
    3106              : //                                      if( expandInnerFracBnds )
    3107              : //                                      {
    3108              : //                                              // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden
    3109              : //                                              VecScale(moveVrt, nV, width/2. );
    3110              : //                                      }
    3111              : //                                      else
    3112              : //                                      {
    3113              : //                                              // auf Annes Wunsch hin werden die Normalen innendrin an einer endenen Kluft zu Null gesetzt
    3114              : //
    3115              : //                                              VecScale(moveVrt, nV, 0. );
    3116              : //
    3117              : //                                      }
    3118              : 
    3119              :                                         VecScale(moveVrt, nV, width/2. );
    3120              : 
    3121              :                                         VecAdd(posNewVrt, posOldVrt, moveVrt );
    3122              : 
    3123              :                                         UG_LOG("neuer Vertex " << posNewVrt << std::endl );
    3124              : 
    3125              :                                         // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex
    3126              : 
    3127              : 
    3128              : 
    3129              :                                         Vertex * newShiftVrtx = *grid.create<RegularVertex>();
    3130              :                                         aaPos[newShiftVrtx] = posNewVrt;
    3131              : 
    3132              :                                         sh.assign_subset(newShiftVrtx, subsIndEdgV );
    3133              : 
    3134              : 
    3135              : 
    3136              :                                         // fuer was braucheh wir das eigentlich? selber schon vergessen.....
    3137              : 
    3138              :                                         ExpandVertexMultiplett vrtMtpl( attEdg, attFac, nV );
    3139              : 
    3140              :                                         aaVrtExpMP[ *iterV ].push_back( vrtMtpl );
    3141              : 
    3142              : 
    3143              : 
    3144              :                                         // alle anhängenden faces müssen noch zu wissen bekommen
    3145              :                                         // dass es diesen neuen Vertex gibt, nicht nur die
    3146              :                                         // an den edges anhängenden
    3147              :                                         // vielleicht gibt es einen Loop über attached faces des
    3148              :                                         // Vertex, für die schon bekannten direkt angehängten klar
    3149              :                                         // wenn auch dort vermerkt werden muss im Attachment von Seb
    3150              :                                         // bei den anderen, die keine Edge haben von der Kluft
    3151              :                                         // da muss man die Normale ins Zentrum bestimmen
    3152              :                                         // um heraus zu finden, ob sie auf dieser seite sind
    3153              :                                         // am besten dann das Attachment der faces für vertizes
    3154              :                                         // von Seb recyclen
    3155              : 
    3156              :                                         // loop über assosciated faces des vertex am besten
    3157              :                                         // vermutlich auch noch assosciated edges, um
    3158              :                                         // zu markieren, welche weg fallen sollen, wenn
    3159              :                                         // nicht von Kluft selber, sondern quasi verschoben
    3160              :                                         // und neu erzeugt
    3161              : 
    3162              :                                         int dbg_FaceIterator = 0;
    3163              : 
    3164              : 
    3165              : 
    3166              :                                         for( auto const & ifac : assoFaces )
    3167              :                                         {
    3168              :                                                 bool isFromFrac = false;
    3169              : 
    3170              :                                                 for( auto const & facFrac : attFac )
    3171              :                                                 {
    3172              : 
    3173              : //                                                                                      // DEBUG ASSERT TEST static_assert( std::is_same<  decltype( const_cast<Face* & >(facFrac) ), decltype ( ifac ) >::value );
    3174              :                                                         // DEBUG ASSERT TEST static_assert( std::is_same<  decltype( (facFrac) ), decltype ( ifac ) >::value );
    3175              : 
    3176              :                                                         if( ifac == facFrac )
    3177              :                                                         {
    3178              :                                                                 isFromFrac = true;
    3179              : 
    3180              : //                                                                                                      // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast<Face* & >(facFrac) ), Face * & >::value  );
    3181              :                                                                 // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value  );
    3182              : //                                                                                              // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast<Face* & >(facFrac) ), decltype( ifac ) >::value  );
    3183              :                                                                 // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value  );
    3184              : 
    3185              :                                                         }
    3186              :                                                 }
    3187              : 
    3188              : 
    3189              :                                                 bool atRightSide = false;
    3190              : 
    3191              :                                                 if( isFromFrac )
    3192              :                                                         atRightSide = true;
    3193              : 
    3194              :                                                 if( !isFromFrac )
    3195              :                                                 {
    3196              :                                                         // check if on same side of edge where the normal points to: compute cosinus between vector of face center
    3197              :                                                         //  perpendicular to the edge
    3198              : 
    3199              : 
    3200              : 
    3201              : 
    3202              :                                                         vector3 facCenter = CalculateCenter( ifac, aaPos );
    3203              : 
    3204              :                                                         vector3 perpendicu;
    3205              : 
    3206              : 
    3207              : //                                                      UG_LOG("pos 0 " << aaPos[nextFracVrt[0]] << std::endl);
    3208              : //                                                      UG_LOG("pos 1 " << aaPos[*iterV] << std::endl);
    3209              : //                                                      UG_LOG("fac ce " << facCenter << std::endl);
    3210              : 
    3211              :                                                         DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt], aaPos[*iterV]);
    3212              : 
    3213              : //                                                      if( dbg_FaceIterator == 1 )
    3214              : //                                                      {
    3215              : //                                                              UG_LOG("huhu a0" << std::endl);
    3216              : //                                                              return true;
    3217              : //                                                      }
    3218              : 
    3219              : 
    3220              :                                                         vector3 tmpN;
    3221              : 
    3222              :                                                         VecSubtract(tmpN, facCenter, perpendicu );
    3223              : 
    3224              :                                                         VecNormalize(tmpN, tmpN);
    3225              : 
    3226              :                                                         UG_LOG("Normale zum Face ist " << tmpN << std::endl);
    3227              : 
    3228              :                                                         number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nV );
    3229              : 
    3230              :                                                         UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl);
    3231              : 
    3232              : //                                                      if( dbg_FaceIterator == 1 )
    3233              : //                                                      {
    3234              : //                                                              UG_LOG("huhu a" << std::endl);
    3235              : ////                                                            return true;
    3236              : //                                                      }
    3237              : 
    3238              : 
    3239              :                                                         if( cosBetwFracEdgAndDirection2Face > 0 )
    3240              :                                                         {
    3241              :                                                                 UG_LOG("assuming face to be on richt side" << std::endl);
    3242              : 
    3243              :                                                                 atRightSide = true;
    3244              : 
    3245              : #if ESTABLISH_DEBUG_SUDOS
    3246              : 
    3247              :                                                                 Vertex * otherFacCent = *grid.create<RegularVertex>();
    3248              :                                                                 aaPos[otherFacCent] = facCenter;
    3249              :                                                                 sh.assign_subset(otherFacCent, 6 );
    3250              : 
    3251              :                                                                 Vertex * pp = *grid.create<RegularVertex>();
    3252              :                                                                 aaPos[pp] = perpendicu;
    3253              :                                                                 sh.assign_subset(pp, 7 );
    3254              : 
    3255              :                                                                 sh.assign_subset(ifac,8);
    3256              : 
    3257              : #endif
    3258              : 
    3259              :                                                         }
    3260              :                                                         else
    3261              :                                                         {
    3262              :                                                                 UG_LOG("assuming face to be on wrong side" << std::endl);
    3263              :                                                         }
    3264              : 
    3265              : 
    3266              :                                                         dbg_flachen_passiert++;
    3267              :                                                 }
    3268              : 
    3269              : 
    3270              : //                                              if( dbg_FaceIterator == 1 )
    3271              : //                                              {
    3272              : //                                                      UG_LOG("huhu b" << std::endl);
    3273              : ////                                                    return true;
    3274              : //                                              }
    3275              : 
    3276              : 
    3277              : 
    3278              :                                                 if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein
    3279              :                                                 {
    3280              : 
    3281              :                                                         // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden!
    3282              :                                                         vector<Vertex*>& newVrts4Fac = aaVrtVecFace[ ifac ];
    3283              : 
    3284              :                                                         IndexType vrtxFnd = 0;
    3285              : 
    3286              :                                                         for(size_t indVrt = 0; indVrt < (ifac)->num_vertices();  indVrt++ )
    3287              :                                                         {
    3288              :                                                                 Vertex* facVrt = (ifac)->vertex(indVrt);
    3289              : 
    3290              :                                                                 if(  facVrt == *iterV )
    3291              :                                                                 {
    3292              :                                                                         newVrts4Fac[ indVrt ] = newShiftVrtx;
    3293              :                                                                         vrtxFnd++;
    3294              :                                                                 }
    3295              :                                                         }
    3296              : 
    3297              : 
    3298              :                                                         if( vrtxFnd <= 0 )
    3299              :                                                         {
    3300              :                                                                 UG_THROW("vertex not found!" << std::endl);
    3301              :                                                         }
    3302              :                                                         else if( vrtxFnd > 1 )
    3303              :                                                         {
    3304              :                                                                 UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl );
    3305              :                                                         }
    3306              :                                                         else if ( vrtxFnd == 1 )
    3307              :                                                         {
    3308              :                                                         }
    3309              :                                                         else
    3310              :                                                         {
    3311              :                                                                 UG_THROW("vertex finden komisch " << std::endl);
    3312              :                                                         }
    3313              : 
    3314              : 
    3315              :                                                 }
    3316              : 
    3317              :                                                 dbg_FaceIterator++;
    3318              : 
    3319              :                                         }
    3320              : 
    3321              : 
    3322              : 
    3323              : 
    3324              : 
    3325              : 
    3326              : 
    3327              : 
    3328              :                                 }
    3329              : 
    3330              : 
    3331              : 
    3332              :                                 dbg_iteratorAblaufen++;
    3333              : 
    3334              : 
    3335              : 
    3336              : //                              // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen
    3337              : //                              // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat
    3338              : //                              // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden
    3339              : //                              // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren?
    3340              : //
    3341              : //
    3342              : //
    3343              :                                 UG_LOG("END THIS VERTEX NORMAL INNER ENDING CLEFT" << std::endl);
    3344              : 
    3345              : #endif
    3346              : 
    3347              : 
    3348              : //                              return true;
    3349              : 
    3350              : 
    3351              :                         }
    3352              : //                      else if( numFracsCrossAtVrt == 2 ) // free line of fracture, no crossing point, not at boundary
    3353              :                         else if( false ) // free line of fracture, no crossing point, not at boundary
    3354              :                         {
    3355              :                                 // in this case, we have two attached edges, and each of these edges has two attached faces
    3356              :                                 // the faces have a naormal, and based on the normal, we can decide which faces belong to the same side of the edges
    3357              : 
    3358              : 
    3359              :                                 if( numbAttTripl != 4 )
    3360              :                                 {
    3361              : 
    3362              :                                         UG_LOG("NUMBER OF TRIPLETTS " << numbAttTripl << std::endl);
    3363              : 
    3364              : //                                      return true;
    3365              : 
    3366              :                                         UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte, nicht am Rand " << std::endl);
    3367              :                                 }
    3368              : 
    3369              :                                 // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind
    3370              : 
    3371              :                                 // und gleich auch Erzeugung der neuen Knoten, die dann
    3372              :                                 // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes
    3373              :                                 // angehängt werden; der Winkel zur Normalen hilft später, die Seite
    3374              :                                 // heraus zu finden, Seite von den Edges
    3375              : 
    3376              : 
    3377              : 
    3378              :                                 int dbg_iteratorAblaufen = 0;
    3379              : 
    3380              : #if WORKAROUND_ARTE_SEGFAULT
    3381              : 
    3382              :                                 int dbg_laenge = 0;
    3383              : 
    3384              :                                 for( auto const & vft : vecVertFracTrip )
    3385              :                                 {
    3386              :                                         dbg_laenge++;
    3387              : 
    3388              :                                         UG_LOG("VERTEXFRACTRIP" << std::endl);
    3389              : 
    3390              :                                         vector3 ve = vft.getNormal();
    3391              : 
    3392              :                                         UG_LOG("NORMAL " << ve << std::endl);
    3393              : 
    3394              :                                         UG_LOG("laenge " << dbg_laenge << std::endl );
    3395              :                                 }
    3396              : 
    3397              : 
    3398              :                                 UG_LOG("SINGLE" << std::endl);
    3399              : 
    3400              : 
    3401              :                                 for( VvftIterator vvftOne = vecVertFracTrip.begin();
    3402              :                                                 vvftOne != vecVertFracTrip.end() - 1;
    3403              :                                                 vvftOne++
    3404              :                                 )
    3405              :                                 {
    3406              : 
    3407              : 
    3408              :                                         Edge * edgeOne = vvftOne->getEdge();
    3409              :                                         vector3 nOne = vvftOne->getNormal();
    3410              : 
    3411              : 
    3412              :                                         for( VvftIterator vvftTwo = vvftOne + 1;
    3413              :                                                         vvftTwo != vecVertFracTrip.end();
    3414              :                                                         vvftTwo++
    3415              :                                         )
    3416              :                                         {
    3417              :                                                 Edge * edgeTwo = vvftTwo->getEdge();
    3418              :                                                 vector3 nTwo = vvftTwo->getNormal();
    3419              : 
    3420              :                                                 number cosinus = VecDot( nOne, nTwo );
    3421              : 
    3422              :                                                 if( edgeOne != edgeTwo )
    3423              :                                                 {
    3424              :                                                         UG_LOG("COSI  between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl );
    3425              :                                                 }
    3426              : 
    3427              :                                         }
    3428              :                                 }
    3429              : 
    3430              :                                 UG_LOG("SINGLE END" << std::endl);
    3431              : 
    3432              :                                 int dbg_laenge_eins = 0;
    3433              : 
    3434              : #endif
    3435              : 
    3436              : 
    3437              :                                 for( VvftIterator vvftOne = vecVertFracTrip.begin();
    3438              :                                                 vvftOne != vecVertFracTrip.end() - 1;
    3439              :                                                 vvftOne++
    3440              :                                 )
    3441              :                                 {
    3442              : 
    3443              : #if WORKAROUND_ARTE_SEGFAULT
    3444              :                                         dbg_laenge_eins++;
    3445              : 
    3446              :                                         if( dbg_laenge_eins > dbg_laenge )
    3447              :                                         {
    3448              :                                                 break;
    3449              :                                         }
    3450              : 
    3451              :                                         int dbg_laenge_zwei = dbg_laenge_eins;
    3452              : #endif
    3453              :                                         int dbg_zweiterIteratorAblaufen = 0;
    3454              : 
    3455              :                                         vector3 nOne = vvftOne->getNormal();
    3456              : 
    3457              :                                         Edge * edgeOne = vvftOne->getEdge();
    3458              : 
    3459              : 
    3460              : 
    3461              :                                         for( VvftIterator vvftTwo = vvftOne + 1;
    3462              :                                                         vvftTwo != vecVertFracTrip.end();
    3463              :                                                         vvftTwo++
    3464              :                                         )
    3465              :                                         {
    3466              : 
    3467              : #if WORKAROUND_ARTE_SEGFAULT
    3468              :                                                 dbg_laenge_zwei++;
    3469              : 
    3470              :                                                 if( dbg_laenge_zwei > dbg_laenge )
    3471              :                                                 {
    3472              :                                                         break;
    3473              :                                                 }
    3474              : 
    3475              :                                                 UG_LOG("NORMAL ONE " << vvftOne->getNormal() << std::endl);
    3476              :                                                 UG_LOG("NORMAL TWO " << vvftTwo->getNormal() << std::endl);
    3477              :                                                 UG_LOG("LAENGE EINZ ZWO " << dbg_laenge_eins << " " << dbg_laenge_zwei << std::endl );
    3478              : #endif
    3479              : 
    3480              :                                                 // dieselben brauchen wir nicht vergleichen
    3481              :                                                 if( vvftOne == vvftTwo )
    3482              :                                                 {
    3483              :                                                         // sollte nie vorkommen!
    3484              :                                                         UG_THROW("Unsinn " << std::endl);
    3485              :                                                 }
    3486              :                                                 else
    3487              :                                                 {
    3488              : 
    3489              :                                                         Edge * edgeTwo = vvftTwo->getEdge();
    3490              : 
    3491              :                                                         // noch testen, ob nicht die Kante dieselbe ist, geht das?
    3492              :                                                         // bei der gleichen Ecke ist es unnötig, da es gegensätzlich sein muss
    3493              : 
    3494              : 
    3495              : 
    3496              :                                                         if( edgeOne != edgeTwo )
    3497              :                                                         {
    3498              : 
    3499              :                                                                 std::vector<Vertex *> nextFracVrt;
    3500              : 
    3501              :                                                                 IndexType foundThisVrtOne = 0;
    3502              : 
    3503              :                                                                 for( size_t i = 0; i < 2; ++i )
    3504              :                                                                 {
    3505              :                                                                         Vertex * vrtEdgEnd = edgeOne->vertex(i);
    3506              : 
    3507              :                                                                         if( vrtEdgEnd == *iterV )
    3508              :                                                                         {
    3509              :                                                                                 foundThisVrtOne++;
    3510              :                                                                         }
    3511              :                                                                         else
    3512              :                                                                         {
    3513              :                                                                                 nextFracVrt.push_back( vrtEdgEnd );
    3514              :                                                                         }
    3515              : 
    3516              :                                                                 }
    3517              : 
    3518              :                                                                 if( foundThisVrtOne != 1 )
    3519              :                                                                 {
    3520              :                                                                         UG_THROW("zu viel zu wenig vertizex one " << std::endl);
    3521              :                                                                 }
    3522              : 
    3523              : 
    3524              :                                                                 IndexType foundThisVrtTwo = 0;
    3525              : 
    3526              :                                                                 for( size_t i = 0; i < 2; ++i )
    3527              :                                                                 {
    3528              :                                                                         Vertex * vrtEdgEnd = edgeTwo->vertex(i);
    3529              : 
    3530              :                                                                         if( vrtEdgEnd == *iterV )
    3531              :                                                                         {
    3532              :                                                                                 foundThisVrtTwo++;
    3533              :                                                                         }
    3534              :                                                                         else
    3535              :                                                                         {
    3536              :                                                                                 nextFracVrt.push_back( vrtEdgEnd );
    3537              :                                                                         }
    3538              : 
    3539              :                                                                 }
    3540              : 
    3541              :                                                                 if( foundThisVrtTwo != 1 )
    3542              :                                                                 {
    3543              :                                                                         UG_THROW("zu viel zu wenig vertizex two " << std::endl);
    3544              :                                                                 }
    3545              : 
    3546              : 
    3547              : 
    3548              :                                                                 vector3 nTwo = vvftTwo->getNormal();
    3549              : 
    3550              :                                                                 number cosinus = VecDot( nOne, nTwo );
    3551              : 
    3552              : //                                                              bool vz = ! std::signbit(cosinus);
    3553              : 
    3554              :                                                                 UG_LOG("cosinus " << dbg_vertizesPassiert << " between " << nOne << " and " << nTwo << " -> " << cosinus << std::endl );
    3555              :                                                                 //UG_LOG("sign between " << nOne << " and " << nTwo << " -> " << vz << std::endl );
    3556              : 
    3557              : 
    3558              :                                                                 if( cosinus > 0 )
    3559              :                                                                 {
    3560              :                                                                         // gleiche Seite vermutet
    3561              : 
    3562              :                                                                         // sind die edges dieselben? pruefen! gleiche unnoetig - wird oben schon abgefragt
    3563              : 
    3564              :                                                                         // Klasse schreiben, die als attachment an einen Fracture-Vertex
    3565              :                                                                         // die neuen Vertizes samt ihrer gemittelten Normalen speichert
    3566              :                                                                         // also std::vector von dieser neuen Klasse als Vertex attachment
    3567              : 
    3568              : #if 1
    3569              : 
    3570              :                                                                         Face * facOne = vvftOne->getFace();
    3571              :                                                                         Face * facTwo = vvftTwo->getFace();
    3572              : 
    3573              :                                                                         expandSingleFractureAtGivenSide( nOne, nTwo,
    3574              :                                                                                                                                          edgeOne, edgeTwo,
    3575              :                                                                                                                                          facOne, facTwo,
    3576              :                                                                                                                                          fracInfosBySubset,
    3577              :                                                                                                                                          posOldVrt,
    3578              :                                                                                                                                          aaPos,
    3579              :                                                                                                                                          grid, sh,
    3580              :                                                                                                                                          assoFaces,
    3581              :                                                                                                                                          nextFracVrt,
    3582              :                                                                                                                                          aaVrtVecFace,
    3583              :                                                                                                                                          dbg_flachen_passiert,
    3584              :                                                                                                                                          *iterV
    3585              :                                                                                                                                         );
    3586              : 
    3587              : #else
    3588              : 
    3589              :                                                                         // average the normals
    3590              : 
    3591              :                                                                         vector3 normSum;
    3592              : 
    3593              :                                                                         VecAdd( normSum, nOne, nTwo );
    3594              : 
    3595              :                                                                         vector3 normSumNormed;
    3596              : 
    3597              :                                                                         VecNormalize(normSumNormed, normSum);
    3598              : 
    3599              :                                                                         UG_LOG("averaged normal " << normSumNormed << std::endl);
    3600              : 
    3601              :                                                                         std::vector<Edge * > attEdg;
    3602              :                                                                         std::vector<Face * > attFac;
    3603              : 
    3604              :                                                                         attEdg.push_back( edgeOne );
    3605              :                                                                         attEdg.push_back( edgeTwo );
    3606              : 
    3607              : //                                                                      Face * facOne = vvftOne->getFace();
    3608              : //                                                                      Face * facTwo = vvftTwo->getFace();
    3609              : 
    3610              :                                                                         attFac.push_back( facOne );
    3611              :                                                                         attFac.push_back( facTwo );
    3612              : 
    3613              :                                                                         // jetzt neuen Vertex erzeugen in Richtung der Normalen
    3614              :                                                                         // sonst ist das attachment Schwachsinn!
    3615              : 
    3616              :                                                                         vector3 posNewVrt;
    3617              : 
    3618              :                                                                         vector3 moveVrt;
    3619              : 
    3620              :                                                                         auto subsIndEdgOne = sh.get_subset_index(edgeOne);
    3621              : 
    3622              :                                                                         auto subsIndEdgTwo = sh.get_subset_index(edgeTwo);
    3623              : 
    3624              : 
    3625              :                                                                         if( subsIndEdgOne != subsIndEdgTwo )
    3626              :                                                                         {
    3627              :                                                                                 UG_THROW("subsets passen nicht" << std::endl );
    3628              :                                                                         }
    3629              : 
    3630              : 
    3631              : 
    3632              : 
    3633              :                                                                         number width = fracInfosBySubset.at(subsIndEdgOne).width;
    3634              : 
    3635              :                                                                         // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden
    3636              :                                                                         VecScale(moveVrt, normSumNormed, width/2. );
    3637              : 
    3638              :                                                                         VecAdd(posNewVrt, posOldVrt, moveVrt );
    3639              : 
    3640              :                                                                         UG_LOG("neuer Vertex " << posNewVrt << std::endl );
    3641              : 
    3642              :                                                                         // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex
    3643              : 
    3644              :                                                                         Vertex * newShiftVrtx = *grid.create<RegularVertex>();
    3645              :                                                                         aaPos[newShiftVrtx] = posNewVrt;
    3646              : 
    3647              :                                                                         sh.assign_subset(newShiftVrtx, subsIndEdgOne );
    3648              : 
    3649              : 
    3650              : 
    3651              :                                                                         // fuer was braucheh wir das eigentlich? selber schon vergessen.....
    3652              : 
    3653              :                                                                         ExpandVertexMultiplett vrtMtpl( attEdg, attFac, normSumNormed );
    3654              : 
    3655              :                                                                         aaVrtExpMP[ *iterV ].push_back( vrtMtpl );
    3656              : 
    3657              : 
    3658              : 
    3659              :                                                                         // alle anhängenden faces müssen noch zu wissen bekommen
    3660              :                                                                         // dass es diesen neuen Vertex gibt, nicht nur die
    3661              :                                                                         // an den edges anhängenden
    3662              :                                                                         // vielleicht gibt es einen Loop über attached faces des
    3663              :                                                                         // Vertex, für die schon bekannten direkt angehängten klar
    3664              :                                                                         // wenn auch dort vermerkt werden muss im Attachment von Seb
    3665              :                                                                         // bei den anderen, die keine Edge haben von der Kluft
    3666              :                                                                         // da muss man die Normale ins Zentrum bestimmen
    3667              :                                                                         // um heraus zu finden, ob sie auf dieser seite sind
    3668              :                                                                         // am besten dann das Attachment der faces für vertizes
    3669              :                                                                         // von Seb recyclen
    3670              : 
    3671              :                                                                         // loop über assosciated faces des vertex am besten
    3672              :                                                                         // vermutlich auch noch assosciated edges, um
    3673              :                                                                         // zu markieren, welche weg fallen sollen, wenn
    3674              :                                                                         // nicht von Kluft selber, sondern quasi verschoben
    3675              :                                                                         // und neu erzeugt
    3676              : 
    3677              :                                                                         int dbg_FaceIterator = 0;
    3678              : 
    3679              : #if 0
    3680              : //                                                                      for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ )
    3681              :                                                                         for( std::vector<Face *>::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ )
    3682              :                                                                         {
    3683              :                                                                                 bool isFromFrac = false;
    3684              : 
    3685              : //                                                                              for( std::vector<Face *>::iterator iterF2 = attFac.begin(); iterF2 != attFac.end(); iterF2++ )
    3686              : //                                                                              {
    3687              : //                                                                                      // DEBUG ASSERT TEST static_assert( std::is_same< decltype( *iterF2 ), decltype ( *iterFac ) >::value );
    3688              : //
    3689              : //                                                                              }
    3690              : 
    3691              :                                                                                 int dbg_innterFacFracIt = 0;
    3692              : 
    3693              :                                                                                 for( auto const & facFrac : attFac )
    3694              :                                                                                 {
    3695              : 
    3696              : 
    3697              : //                                                                                      UG_LOG("type iter facFrac " << typeid( facFrac ).name() << std::endl);
    3698              : //
    3699              : //                                                                                      UG_LOG("type iter Fac " << typeid( *iterFac ).name() << std::endl);
    3700              : 
    3701              :                                                                                         // DEBUG ASSERT TEST static_assert( std::is_same<  decltype( const_cast<Face* & >(facFrac) ), decltype ( *iterFac ) >::value );
    3702              : 
    3703              : 
    3704              : 
    3705              : 
    3706              :                                                                                         if( *iterFac == facFrac )
    3707              :                                                                                         {
    3708              :                                                                                                 isFromFrac = true;
    3709              : 
    3710              :                                                                                                 // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast<Face* & >(facFrac) ), Face * & >::value  );
    3711              :                                                                                                 // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast<Face* & >(facFrac) ), decltype( * iterFac ) >::value  );
    3712              : 
    3713              :                                                                                         }
    3714              :                                                                                 }
    3715              : 
    3716              :                                                                                 bool atRightSide = false;
    3717              : 
    3718              :                                                                                 if( isFromFrac )
    3719              :                                                                                         atRightSide = true;
    3720              : 
    3721              :                                                                                 if( !isFromFrac )
    3722              :                                                                                 {
    3723              :                                                                                         // check if on same side of edge where the normal points to: compute cosinus between vector of face center
    3724              :                                                                                         //  perpendicular to the edge
    3725              :                                                                                         // TODO FIXME
    3726              :                                                                                         // KAESE!!!
    3727              : 
    3728              :                                                                                         vector3 facCenter = CalculateCenter( *iterFac, aaPos );
    3729              : 
    3730              :                                                                                         vector3 perpendicu;
    3731              : 
    3732              :                                                                                         if( nextFracVrt.size() != 2 )
    3733              :                                                                                         {
    3734              :                                                                                                 UG_THROW("komische Groesse" << std::endl);
    3735              :                                                                                         }
    3736              : 
    3737              :                                                                                         DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]);
    3738              : 
    3739              :                                                                                         vector3 tmpN;
    3740              : 
    3741              :                                                                                         VecSubtract(tmpN, facCenter, perpendicu );
    3742              : 
    3743              :                                                                                         VecNormalize(tmpN, tmpN);
    3744              : 
    3745              :                                                                                         UG_LOG("Normale zum Face ist " << tmpN << std::endl);
    3746              : 
    3747              :                                                                                         number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed );
    3748              : 
    3749              :                                                                                         UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl);
    3750              : 
    3751              :                                                                                         if( cosBetwFracEdgAndDirection2Face > 0 )
    3752              :                                                                                         {
    3753              :                                                                                                 UG_LOG("assuming face to be on richt side" << std::endl);
    3754              : 
    3755              :                                                                                                 atRightSide = true;
    3756              : 
    3757              : #if ESTABLISH_DEBUG_SUDOS
    3758              : 
    3759              :                                                                                                 Vertex * otherFacCent = *grid.create<RegularVertex>();
    3760              :                                                                                                 aaPos[otherFacCent] = facCenter;
    3761              :                                                                                                 sh.assign_subset(otherFacCent, 5 );
    3762              : 
    3763              :                                                                                                 Vertex * pp = *grid.create<RegularVertex>();
    3764              :                                                                                                 aaPos[pp] = perpendicu;
    3765              :                                                                                                 sh.assign_subset(pp, 6 );
    3766              : 
    3767              :                                                                                                 sh.assign_subset(*iterFac,7);
    3768              : #endif
    3769              : 
    3770              :                                                                                         }
    3771              :                                                                                         else
    3772              :                                                                                         {
    3773              :                                                                                                 UG_LOG("assuming face to be on wrong side" << std::endl);
    3774              :                                                                                         }
    3775              : 
    3776              : //                                                                                      if( dbg_flachen_passiert == 0 )
    3777              : //                                                                                      {
    3778              : //                                                                                              UG_LOG("passiert " << dbg_flachen_passiert << std::endl);
    3779              : //
    3780              : //                                                                                              Vertex * otherFacCent = *grid.create<RegularVertex>();
    3781              : //                                                                                              aaPos[otherFacCent] = facCenter;
    3782              : //                                                                                              sh.assign_subset(otherFacCent, 5 );
    3783              : //
    3784              : //                                                                                              Vertex * pp = *grid.create<RegularVertex>();
    3785              : //                                                                                              aaPos[pp] = perpendicu;
    3786              : //                                                                                              sh.assign_subset(pp, 6 );
    3787              : //
    3788              : //                                                                                              sh.assign_subset(*iterFac,7);
    3789              : //
    3790              : //
    3791              : //                                                                                              sh.assign_subset(*iterFac,3);
    3792              : //
    3793              : //                                                                                              UG_LOG("is from frac " << isFromFrac << std::endl);
    3794              : //
    3795              : //                                                                                              return true;
    3796              : //                                                                                      }
    3797              : 
    3798              : 
    3799              :                                                                                         dbg_flachen_passiert++;
    3800              :                                                                                 }
    3801              : 
    3802              : 
    3803              :                                                                                 if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein
    3804              :                                                                                 {
    3805              : 
    3806              : 
    3807              :                                                                                         // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden!
    3808              :                                                                                         vector<Vertex*>& newVrts4Fac = aaVrtVecFace[ * iterFac ];
    3809              : 
    3810              :                                                                                         IndexType vrtxFnd = 0;
    3811              : 
    3812              :                                                                                         for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices();  indVrt++ )
    3813              :                                                                                         {
    3814              :                                                                                                 Vertex* facVrt = (*iterFac)->vertex(indVrt);
    3815              : 
    3816              :                                                                                                 if(  facVrt == *iterV )
    3817              :                                                                                                 {
    3818              :                                                                                                         newVrts4Fac[ indVrt ] = newShiftVrtx;
    3819              :         //                                                                                                      UG_LOG("vertex found " <<  indVrt << std::endl );
    3820              :                                                                                                         vrtxFnd++;
    3821              :                                                                                                 }
    3822              :                                                                                         }
    3823              : 
    3824              : 
    3825              :                                                                                         if( vrtxFnd <= 0 )
    3826              :                                                                                         {
    3827              :                                                                                                 UG_THROW("vertex not found!" << std::endl);
    3828              :                                                                                         }
    3829              :                                                                                         else if( vrtxFnd > 1 )
    3830              :                                                                                         {
    3831              :                                                                                                 UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl );
    3832              :                                                                                         }
    3833              :                                                                                         else if ( vrtxFnd == 1 )
    3834              :                                                                                         {
    3835              :         //                                                                                              UG_LOG("vertex found abgeschlossen" << std::endl);
    3836              :                                                                                         }
    3837              :                                                                                         else
    3838              :                                                                                         {
    3839              :                                                                                                 UG_THROW("vertex finden komisch " << std::endl);
    3840              :                                                                                         }
    3841              : 
    3842              : 
    3843              :                                                                                 }
    3844              : 
    3845              :                                                                                 dbg_innterFacFracIt++;
    3846              : 
    3847              : 
    3848              : 
    3849              : //
    3850              : //
    3851              : //                                                                              if( ! isFromFrac )
    3852              : //                                                                              {
    3853              : //                                                                                      // Vektor zum Zentrum von KNoten aus berechnen und Winkel zur Normalen bestimmen zur Unterscheidung der Seite
    3854              : //                                                                                      // wenn auf richtiger Seite, zuweisen
    3855              : //                                                                              }
    3856              : 
    3857              :                                                                                 dbg_FaceIterator++;
    3858              : 
    3859              :                                                                         }
    3860              : #else
    3861              : //                                                                      std::vector<Face* > & assFaceVrt = aaVrtInfoAssoFaces[*iterV];
    3862              : 
    3863              :                                                                         //                                                                      VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV];
    3864              :                                                                                                                                                 // TODO FIXME hier braucht man das nicht zu ordnen
    3865              :                                                                                                                                                 // aber bei Kreuzpunkten von Klueften muss es so geordnet werden, wie es nebeneinander liegt
    3866              :                                                                                                                                                 // bei den Edges gibt es auch die benachbarten, und die edges haben das attachment, ob sie Kluftedges sind
    3867              : 
    3868              :                                                                         //                                                                      for( auto const & ifac : assoFaces )
    3869              :                                                                         //                                                                      {
    3870              :                                                                         //                                                                              // DEBUG ASSERT TEST static_assert( std::is_same< decltype( ifac ), Face * const & >::value );
    3871              :                                                                         //
    3872              :                                                                         //                                                                              // TODO FIXME folgenden loop durch diesen ersetzen
    3873              :                                                                         //                                                                              // Achtung: Zeigerproblematik, Referenzen, etc.....
    3874              :                                                                         //                                                                              // *iterFac ersetzen durch ifac vermutlich, aber wer weiss
    3875              :                                                                         //                                                                      }
    3876              : 
    3877              : 
    3878              :                                                                         //                                                                      for( auto iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ )
    3879              :                                                                         //for( std::vector<Face *>::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ )
    3880              :                                                                         for( auto const & ifac : assoFaces )
    3881              :                                                                         {
    3882              :                                                                                 bool isFromFrac = false;
    3883              : 
    3884              : 
    3885              :                                                                                 int dbg_innterFacFracIt = 0;
    3886              : 
    3887              :                                                                                 for( auto const & facFrac : attFac )
    3888              :                                                                                 {
    3889              : 
    3890              : //                                                                                      // DEBUG ASSERT TEST static_assert( std::is_same<  decltype( const_cast<Face* & >(facFrac) ), decltype ( ifac ) >::value );
    3891              :                                                                                         // DEBUG ASSERT TEST static_assert( std::is_same<  decltype( (facFrac) ), decltype ( ifac ) >::value );
    3892              : 
    3893              :                                                                                         if( ifac == facFrac )
    3894              :                                                                                         {
    3895              :                                                                                                 isFromFrac = true;
    3896              : 
    3897              : //                                                                                              // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast<Face* & >(facFrac) ), Face * & >::value  );
    3898              :                                                                                                 // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), Face * const & >::value  );
    3899              : //                                                                                              // DEBUG ASSERT TEST static_assert( std::is_same< decltype( const_cast<Face* & >(facFrac) ), decltype( ifac ) >::value  );
    3900              :                                                                                                 // DEBUG ASSERT TEST static_assert( std::is_same< decltype( (facFrac) ), decltype( ifac ) >::value  );
    3901              : 
    3902              :                                                                                         }
    3903              :                                                                                 }
    3904              : 
    3905              :                                                                                 bool atRightSide = false;
    3906              : 
    3907              :                                                                                 if( isFromFrac )
    3908              :                                                                                         atRightSide = true;
    3909              : 
    3910              :                                                                                 if( !isFromFrac )
    3911              :                                                                                 {
    3912              :                                                                                         // check if on same side of edge where the normal points to: compute cosinus between vector of face center
    3913              :                                                                                         //  perpendicular to the edge
    3914              : 
    3915              :                                                                                         vector3 facCenter = CalculateCenter( ifac, aaPos );
    3916              : 
    3917              :                                                                                         vector3 perpendicu;
    3918              : 
    3919              :                                                                                         if( nextFracVrt.size() != 2 )
    3920              :                                                                                         {
    3921              :                                                                                                 UG_THROW("komische Groesse" << std::endl);
    3922              :                                                                                         }
    3923              : 
    3924              :                                                                                         DropAPerpendicular(perpendicu, facCenter, aaPos[nextFracVrt[0]], aaPos[nextFracVrt[1]]);
    3925              : 
    3926              :                                                                                         vector3 tmpN;
    3927              : 
    3928              :                                                                                         VecSubtract(tmpN, facCenter, perpendicu );
    3929              : 
    3930              :                                                                                         VecNormalize(tmpN, tmpN);
    3931              : 
    3932              :                                                                                         UG_LOG("Normale zum Face ist " << tmpN << std::endl);
    3933              : 
    3934              :                                                                                         number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, normSumNormed );
    3935              : 
    3936              :                                                                                         UG_LOG("Cosinus zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl);
    3937              : 
    3938              :                                                                                         if( cosBetwFracEdgAndDirection2Face > 0 )
    3939              :                                                                                         {
    3940              :                                                                                                 UG_LOG("assuming face to be on richt side" << std::endl);
    3941              : 
    3942              :                                                                                                 atRightSide = true;
    3943              : 
    3944              : #if ESTABLISH_DEBUG_SUDOS
    3945              : 
    3946              :                                                                                                 Vertex * otherFacCent = *grid.create<RegularVertex>();
    3947              :                                                                                                 aaPos[otherFacCent] = facCenter;
    3948              :                                                                                                 sh.assign_subset(otherFacCent, 5 );
    3949              : 
    3950              :                                                                                                 Vertex * pp = *grid.create<RegularVertex>();
    3951              :                                                                                                 aaPos[pp] = perpendicu;
    3952              :                                                                                                 sh.assign_subset(pp, 6 );
    3953              : 
    3954              :                                                                                                 sh.assign_subset(*iterFac,7);
    3955              : #endif
    3956              : 
    3957              :                                                                                         }
    3958              :                                                                                         else
    3959              :                                                                                         {
    3960              :                                                                                                 UG_LOG("assuming face to be on wrong side" << std::endl);
    3961              :                                                                                         }
    3962              : 
    3963              : 
    3964              :                                                                                         dbg_flachen_passiert++;
    3965              :                                                                                 }
    3966              : 
    3967              : 
    3968              :                                                                                 if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein
    3969              :                                                                                 {
    3970              : 
    3971              :                                                                                         // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden!
    3972              :                                                                                         vector<Vertex*>& newVrts4Fac = aaVrtVecFace[ ifac ];
    3973              : 
    3974              :                                                                                         IndexType vrtxFnd = 0;
    3975              : 
    3976              :                                                                                         for(size_t indVrt = 0; indVrt < (ifac)->num_vertices();  indVrt++ )
    3977              :                                                                                         {
    3978              :                                                                                                 Vertex* facVrt = (ifac)->vertex(indVrt);
    3979              : 
    3980              :                                                                                                 if(  facVrt == *iterV )
    3981              :                                                                                                 {
    3982              :                                                                                                         newVrts4Fac[ indVrt ] = newShiftVrtx;
    3983              :                                                                                                         vrtxFnd++;
    3984              :                                                                                                 }
    3985              :                                                                                         }
    3986              : 
    3987              : 
    3988              :                                                                                         if( vrtxFnd <= 0 )
    3989              :                                                                                         {
    3990              :                                                                                                 UG_THROW("vertex not found!" << std::endl);
    3991              :                                                                                                                                                                 }
    3992              :                                                                                         else if( vrtxFnd > 1 )
    3993              :                                                                                         {
    3994              :                                                                                                 UG_THROW("vertex zu oft gefunden " << vrtxFnd << std::endl );
    3995              :                                                                                         }
    3996              :                                                                                         else if ( vrtxFnd == 1 )
    3997              :                                                                                         {
    3998              :                                                                                         }
    3999              :                                                                                         else
    4000              :                                                                                         {
    4001              :                                                                                                 UG_THROW("vertex finden komisch " << std::endl);
    4002              :                                                                                         }
    4003              : 
    4004              : 
    4005              :                                                                                 }
    4006              : 
    4007              :                                                                                 dbg_innterFacFracIt++;
    4008              : 
    4009              : 
    4010              : 
    4011              :                                                                                 dbg_FaceIterator++;
    4012              : 
    4013              :                                                                         }
    4014              : 
    4015              : #endif
    4016              : 
    4017              : #endif
    4018              : 
    4019              :                                                                 }
    4020              :                                                                 else
    4021              :                                                                 {
    4022              :                                                                         // andere Seite vermutet, nichts tun!
    4023              :                                                                 }
    4024              : 
    4025              : 
    4026              :                                                         }
    4027              : 
    4028              : 
    4029              :                                                 }
    4030              : 
    4031              :                                                 dbg_zweiterIteratorAblaufen++;
    4032              : 
    4033              :                                         }
    4034              : 
    4035              :                                         dbg_iteratorAblaufen++;
    4036              : 
    4037              :                                 }
    4038              : 
    4039              : 
    4040              : //                              // Ziel: die beiden parallelen Normalen mitteln, und in die jeweiligen beiden Richtungen je einen neuen Vertex erzeugen
    4041              : //                              // irgendwie muss der Vertex oder die Edge besser sogar wissen, dass sie einen neuen Verschiebevertex bekommen hat
    4042              : //                              // denn später müssen neue Edges und neue Faces basierend auf den neuen Vertizes erzeugt werden
    4043              : //                              // vielleicht braucht die edge und das face ein Attachment, das ihnen das sagt, ähnlihc wie VertexTrible std Vektoren?
    4044              : //
    4045              : //
    4046              : //
    4047              : 
    4048              : 
    4049              :                                 UG_LOG("END THIS VERTEX NORMAL COSINE" << std::endl);
    4050              : 
    4051              : 
    4052              : 
    4053              :                         }
    4054              : //                      else // two fractures completely crossing, numFracsCrossAtVrt >= 3, i.e. T crossing and two fractures completely crossing
    4055              :                         else // two fractures completely crossing, numFracsCrossAtVrt >= 2, i.e. durchgehend, T crossing and two fractures completely crossing
    4056              :                         {
    4057              : 
    4058              : 
    4059            0 :                                 CrossVertInf crossVrtInf( *iterV, numFracsCrossAtVrt );
    4060              :                                 VecVertexOfFaceInfo orderedFaces;
    4061              :                                 SegmentsFractExtrus segments;
    4062              : //                              VecVertexOfFaceInfo segmentPart;
    4063              : 
    4064              :                                 // note: we do not attach this info to the vertex, as we only need it local; in principle, in case of further need, it would
    4065              :                                 // be usful to establish some sort of attachment
    4066              : 
    4067              :                                 IndexType startIndex = 0;
    4068              : 
    4069            0 :                                 determineOrderOfFaces(
    4070              :                                                 vecVertFracTrip, assoFaces,  orderedFaces,
    4071              :                                                 segments, //segmentPart,
    4072              :                                                 startIndex, allAssoEdges,
    4073              :                                                 sh, aaMarkEdgeB
    4074              :                                 );
    4075              : 
    4076              : //                              CrossingVertexInfo<Vertex*, IndexType> crossVrtInf( *iterV, numFracsCrossAtVrt );
    4077              : 
    4078              :                                 UG_LOG("number fracs " << numFracsCrossAtVrt << std::endl);
    4079              : 
    4080              : 
    4081              :                                 UG_LOG("Nummer vorbei " << std::endl);
    4082              : 
    4083              : //                              for( auto const & aae : allAssoEdges )
    4084              : //                              {
    4085              : //                                      crossVrtInf.addOriginalFracEdge( aae );
    4086              : //                              }
    4087              : 
    4088              : //                              crossVrtInf.setOriginalFracEdge(allAssoEdges);
    4089              : 
    4090              :                                 //  in case of three fractures, we have to use the method for eine durchgehende fracture
    4091              :                                 // auf der Seite, wo die zweite fracture NICHT rein geht
    4092              : 
    4093              :                                 //  kreuzende Fractures im Innenraum -> Arte in Reinform implementieren
    4094              : 
    4095              :                                 // verkettete Liste der anhängenden fractures in Reihenfolge
    4096              :                                 // der Anhängung mit INfo, ob eine Kluft vorliegt
    4097              : 
    4098              : //                              for( auto const & attVFT : vecVertFracTrip )
    4099              : //                              {
    4100              : //                                      Edge * edg = attVFT.getEdge();
    4101              : //                                      Face * fac = attVFT.getFace();
    4102              : //                                      vector3 nv = attVFT.getNormal();
    4103              : //                              }
    4104              : 
    4105              : //                              // hier werden  ALLE attached Faces benötigt, auch die, die zwischen den direkt an den fractures liegenden Faces sind
    4106              : //
    4107              :                                 // copies of all faces and of fractured ones
    4108              : //                              auto vVFT = vecVertFracTrip; // caution: COPY, not reference!
    4109              : //                              auto aF = assoFaces; // caution: COPY, not reference!
    4110              : 
    4111              : //                              UG_LOG("Gesamtanzahl faces um Knoten " <<  aF.size() << std::endl );
    4112              : 
    4113              :                                 //  erstmal die ganzen anhaengenden Faces ordnen, dass wir wissen, in welcher Reihenfolge wir durchlaufen muessen
    4114              :                                 // jede Edge hat ein bool attachment schon, das weiss, ob sie Fracture edge ist oder nicht
    4115              :                                 // Reihenfolge der faces und die edges auch dazu, vielleicht neues Triple oder dergleiche, dabei zwei edges und zwei normals
    4116              :                                 // und wie gesagt, die edges wissen, ob sie fractures sind, dazu keine neuen Variablen notwendig
    4117              : 
    4118              : //                              using VertexOfFaceInfo = VertexFractureTriple< std::pair<Edge*, Edge*>, Face*, std::pair<vector3,vector3> >;
    4119              : //                              // all edges of the attached face - must always be two, the face itself, and the normal vectors of the face in direction of the two edges
    4120              : //                              // the size of the normal vector vector also must be two
    4121              : //                              // however, if an edge of the face is not a fracture edge, we do not compute the normal, but assign zero as norm
    4122              : //                              // for those edges and faces which are Kluft edges, we assign the normal known from the info computed before, vertex fracture triple
    4123              : //
    4124              : #if 0
    4125              :                                 CrossVertInf crossVrtInf( *iterV, numFracsCrossAtVrt );
    4126              : 
    4127              :                                 //                              using VecVertexOfFaceInfo = std::vector<VertexOfFaceInfo>;
    4128              : 
    4129              :                                 VecVertexOfFaceInfo orderedFaces;
    4130              : 
    4131              : //                              using SegmentsFractExtrus = std::vector<VecVertexOfFaceInfo>;
    4132              : 
    4133              :                                 SegmentsFractExtrus segments;
    4134              :                                 // single components always from one fracture edge to the next one
    4135              : 
    4136              :                                 VecVertexOfFaceInfo segmentPart;
    4137              : 
    4138              :                                 // note: we do not attach this info to the vertex, as we only need it local; in principle, in case of further need, it would
    4139              :                                 // be usful to establish some sort of attachment
    4140              : 
    4141              :                                 // fixed diesen Sortierungsalgorithmus bei allen inneren Knoten anwenden,
    4142              :                                 // um zweifelsfrei alle anhängenden Faces der richtigen Seite zuordnen zu können!!!!
    4143              : 
    4144              :                                 // VecVertFracTrip & vecVertFracTrip = aaVrtInfoFraTri[*iterV];
    4145              :                                 // VecFace & assoFaces = aaVrtInfoAssoFaces[*iterV];
    4146              : 
    4147              :                                 IndexType startIndex = 0;
    4148              : 
    4149              :                                 determineOrderOfFaces( crossVrtInf, vecVertFracTrip, assoFaces,  orderedFaces,
    4150              :                                                                                         segments, segmentPart, startIndex, allAssoEdges,
    4151              :                                                                                         sh, aaMarkEdgeB
    4152              :                                                                                 );
    4153              : #endif
    4154              : 
    4155              : #if 0
    4156              : 
    4157              :                                 IndexType countedCrossingFracEdgs = 0;
    4158              : 
    4159              :                                 if( vVFT.size() == 0 )
    4160              :                                         UG_THROW("vertex frac triple zu klein an Kreuzung " << std::endl);
    4161              : 
    4162              :                                 // we start with the first fracture face edge stuff, copy it,  and delete this immidiately
    4163              :                                 VertFracTrip startVertFracTrip = vVFT[0];
    4164              : 
    4165              :                                 vVFT.erase(vVFT.begin());
    4166              : 
    4167              :                                 bool atFirstTriple = true;
    4168              : 
    4169              :                                 Face* fracFac = startVertFracTrip.getFace();
    4170              :                                 Edge* fracEdg = startVertFracTrip.getEdge();
    4171              :                                 vector3 fracNorm = startVertFracTrip.getNormal();
    4172              : 
    4173              :                                 Edge* originalStartEdge = startVertFracTrip.getEdge();
    4174              : 
    4175              :                                 if( fracEdg != 0 )
    4176              :                                 {
    4177              :                                         countedCrossingFracEdgs++;
    4178              :                                 }
    4179              : 
    4180              :                                 // do not change this pointer
    4181              :                                 Edge* startEdg = fracEdg;
    4182              :                                 Face* startFace = fracFac;
    4183              : 
    4184              :                                 vector3 startNormal = fracNorm;
    4185              : 
    4186              :                                 Face* nextFace = NULL;
    4187              : 
    4188              :                                 UG_LOG("Gesamtanzahl faces um Knoten vor while " <<  aF.size() << std::endl );
    4189              : 
    4190              :                                 while( aF.size() != 0 )
    4191              :                                 {
    4192              : 
    4193              :                                         UG_LOG("Gesamtanzahl faces um Knoten Anfang while " <<  aF.size() << std::endl );
    4194              : 
    4195              : 
    4196              :                                         Face* face2Append = startFace;
    4197              :                                         Edge* startEdg2Append = startEdg;
    4198              : 
    4199              : 
    4200              :                                         IndexType fndCommEdg = 0;
    4201              :                                         vector3 nuVe(0,0,0);
    4202              : 
    4203              :                                         Edge* nextEdge = NULL;
    4204              : 
    4205              :                                         std::pair<Edge*, Edge *> edge2Append( startEdg2Append, nextEdge );
    4206              :                                         std::pair<vector3, vector3 > normal2Append( startNormal, nuVe );
    4207              : 
    4208              : 
    4209              :                                         // if start face and start edge from a triple, then has to be erased this triple, exept for the entire start, as already erased
    4210              :                                         if( ! atFirstTriple )
    4211              :                                         {
    4212              :                                                 for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT !=  vVFT.end(); itAttVFT++ )
    4213              :                                                 {
    4214              :                                                         auto vft = *itAttVFT;
    4215              : 
    4216              :                                                         Edge * edgIt = vft.getEdge();
    4217              : 
    4218              :                                                         Face * facIt = vft.getFace();
    4219              : 
    4220              :                                                         if( edgIt == startEdg && facIt == startFace )
    4221              :                                                         {
    4222              :                                                                 // the first edge if from a fracture and the face is connected to it
    4223              : 
    4224              :                                                                 vVFT.erase(itAttVFT);
    4225              : 
    4226              :                                                                 normal2Append.first = vft.getNormal();
    4227              : 
    4228              :                                                                 if( ! FaceContains( facIt, startEdg ))
    4229              :                                                                 {
    4230              :                                                                         UG_THROW("Face does not contain start edge of its edge" << std::endl);
    4231              :                                                                 }
    4232              : 
    4233              :                                                                 break;
    4234              :                                                         }
    4235              :                                                 }
    4236              : 
    4237              :                                         }
    4238              :                                         else // we can save the investigation if we have a triple, and we do not need to erase, as already erased.....
    4239              :                                         {
    4240              :                                                 atFirstTriple = false;
    4241              :                                         }
    4242              : 
    4243              : 
    4244              :                                         for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt
    4245              :                                         {
    4246              :                                                 if( FaceContains(face2Append, iE) )
    4247              :                                                 {
    4248              :                                                         fndCommEdg++;
    4249              : 
    4250              :                                                         if( iE != startEdg )
    4251              :                                                         {
    4252              :                                                                 nextEdge = iE;
    4253              : 
    4254              :                                                                 edge2Append.second = iE;
    4255              : 
    4256              :                                                         }
    4257              :                                                 }
    4258              : 
    4259              : 
    4260              :                                         }
    4261              : 
    4262              :                                         if( fndCommEdg != 2 )
    4263              :                                         {
    4264              :                                                 UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl);
    4265              :                                         }
    4266              : 
    4267              :                                         if( nextEdge == NULL )
    4268              :                                         {
    4269              :                                                 UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl);
    4270              :                                         }
    4271              : 
    4272              :                                                 if( edge2Append.first == NULL || edge2Append.second == NULL )
    4273              :                                         {
    4274              :                                                 UG_THROW("null immer noch?" << std::endl);
    4275              :                                         }
    4276              : 
    4277              :                                         // erase the face from the list
    4278              : 
    4279              :                                         IndexType faceFound = 0;
    4280              : 
    4281              :                                         for( std::vector<Face*>::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ )
    4282              :                                         {
    4283              :                                                 Face * iFa = *itFac;
    4284              : 
    4285              :                                                 if( iFa == startFace &&  FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg))
    4286              :                                                 {
    4287              :                                                         faceFound++;
    4288              :                                                 }
    4289              :                                         }
    4290              : 
    4291              :                                         int totalSubsNum = sh.num_subsets();
    4292              : 
    4293              :                                         int newSubsToAdd = totalSubsNum;
    4294              : 
    4295              :                                         if( faceFound != 1 )
    4296              :                                         {
    4297              : 
    4298              : 
    4299              :                                                 sh.assign_subset(startFace,newSubsToAdd++);
    4300              :                                                 sh.assign_subset(startEdg,newSubsToAdd++);
    4301              :                                                 sh.assign_subset(nextEdge,newSubsToAdd++);
    4302              : 
    4303              :                                                 int faNum = aF.size();
    4304              : 
    4305              :                                                 UG_LOG("Gesamtzahl faces vor Absturz " << faNum << std::endl);
    4306              : 
    4307              :                                                 UG_LOG("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl);
    4308              : 
    4309              : //                                              return true;
    4310              : 
    4311              : 
    4312              : 
    4313              :                                                 UG_THROW("Gesicht in falscher Anztahl gefunden " << faceFound << std::endl);
    4314              :                                         }
    4315              :                                         else
    4316              :                                         {
    4317              : //                                              sh.assign_subset(startFace,newSubsToAdd++);
    4318              : //                                              sh.assign_subset(startEdg,newSubsToAdd++);
    4319              : //                                              sh.assign_subset(nextEdge,newSubsToAdd++);
    4320              : 
    4321              :                                                 int faNum = aF.size();
    4322              : 
    4323              :                                                 UG_LOG("Gesamtzahl faces ohne Absturz " << faNum << std::endl);
    4324              : 
    4325              :                                         }
    4326              : 
    4327              :                                         for( std::vector<Face*>::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ )
    4328              :                                         {
    4329              :                                                 Face * iFa = *itFac;
    4330              : 
    4331              :                                                 if( iFa == startFace && FaceContains( iFa, nextEdge ) && FaceContains(iFa, startEdg) )
    4332              :                                                 {
    4333              :                                                         aF.erase(itFac);
    4334              :                                                         break;
    4335              :                                                 }
    4336              :                                         }
    4337              : 
    4338              : 
    4339              : 
    4340              : 
    4341              :                                         bool sndEdgIsFracEdgeAlso = aaMarkEdgeB[nextEdge];
    4342              : 
    4343              :                                         bool tripFound = false;
    4344              : 
    4345              :                                         if( sndEdgIsFracEdgeAlso )
    4346              :                                         {
    4347              : 
    4348              :                                                 if( nextEdge != originalStartEdge )
    4349              :                                                         countedCrossingFracEdgs++;
    4350              : 
    4351              :                                                 // we need to have a look for the next triple
    4352              : 
    4353              :                                                 // check if the next normal is a frac normal which contains the face as well
    4354              : 
    4355              :                                                 for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT !=  vVFT.end(); itAttVFT++ )
    4356              :                                                 {
    4357              :                                                         auto vft = *itAttVFT;
    4358              : 
    4359              :                                                         Edge * edgIt = vft.getEdge();
    4360              : 
    4361              :                                                         Face * facIt = vft.getFace();
    4362              : 
    4363              :                                                         if( edgIt == nextEdge && facIt == face2Append )
    4364              :                                                         {
    4365              :                                                                 // the second edge if from a fracture and the face is connected to it
    4366              : 
    4367              :                                                                 tripFound = true;
    4368              : 
    4369              :                                                                 vVFT.erase(itAttVFT);
    4370              : 
    4371              :                                                                 normal2Append.second = vft.getNormal();
    4372              : 
    4373              :                                                                 if( ! FaceContains( facIt, nextEdge ))
    4374              :                                                                 {
    4375              :                                                                         UG_THROW("Face does not contain edge of its edge" << std::endl);
    4376              :                                                                 }
    4377              : 
    4378              :                                                                 break;
    4379              :                                                         }
    4380              :                                                 }
    4381              : 
    4382              :                                         }
    4383              : 
    4384              :                                         if( ! tripFound && sndEdgIsFracEdgeAlso )
    4385              :                                         {
    4386              :                                                 UG_THROW("Triple nicht gefunden trotz markierter Edge" << std::endl);
    4387              :                                         }
    4388              : 
    4389              : 
    4390              :                                         // check if aF or vVFT still contain the former or the next face - must not be the case!
    4391              : 
    4392              :                                         VertexOfFaceInfo vOFI( edge2Append, face2Append, normal2Append );
    4393              : 
    4394              :                                         orderedFaces.push_back( vOFI );
    4395              : 
    4396              :                                         segmentPart.push_back( vOFI );
    4397              : 
    4398              :                                         if( sndEdgIsFracEdgeAlso )
    4399              :                                         {
    4400              :                                                 segments.push_back( segmentPart );
    4401              : 
    4402              :                                                 segmentPart.clear();
    4403              :                                         }
    4404              : 
    4405              : 
    4406              :                                         // what is next face, what is next edge?
    4407              :                                         // wie kriegen wir es hin, auch das nächste Triple zu erasen, wenn es jetzt kommt als nächstes?
    4408              : 
    4409              : 
    4410              :                                         startNormal = nuVe;
    4411              :                                         startEdg = nextEdge;
    4412              : 
    4413              :                                         if( aF.size() == 0 )
    4414              :                                         {
    4415              :                                                 if( nextEdge != originalStartEdge )
    4416              :                                                 {
    4417              :                                                         UG_THROW("Gesichter leer, aber keine Anfangsecke gefunden" << std::endl);
    4418              :                                                 }
    4419              :                                                 else
    4420              :                                                 {
    4421              :                                                         break; // while loop zu Ende, raus aus dem while loop, den Rest nicht mehr machen, würde schief gehen zwingendermassen
    4422              :                                                 }
    4423              : 
    4424              :                                         }
    4425              : 
    4426              : 
    4427              :                                         // bleibt noch das nächste Gesicht heraus zu finden, dafür kommt eigentlich nur noch eines in Frage, da das zweite Gesicht vom edge
    4428              :                                         // geloescht sein muss in aF, es muss das einzig übrige face sein, das die jetzt start edge enthält, davon darf es nur eines geben, wir löschen aber noch nicht
    4429              : 
    4430              :                                         IndexType nextFaceFound = 0;
    4431              : 
    4432              :                                         for( std::vector<Face*>::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ )
    4433              :                                         {
    4434              :                                                 Face * iFa = *itFac;
    4435              : 
    4436              :                                                 if( FaceContains(iFa, startEdg ) )
    4437              :                                                 {
    4438              :                                                         nextFaceFound++;
    4439              :                                                 }
    4440              :                                         }
    4441              : 
    4442              :                                         if( nextFaceFound != 1 )
    4443              :                                         {
    4444              :                                                 UG_THROW("folgendes Gesicht in falscher Anztahl gefunden " << nextFaceFound << std::endl);
    4445              :                                         }
    4446              : 
    4447              :                                         for( std::vector<Face*>::iterator itFac = aF.begin(); itFac != aF.end(); itFac++ )
    4448              :                                         {
    4449              :                                                 Face * iFa = *itFac;
    4450              : 
    4451              :                                                 if( FaceContains(iFa, startEdg ) )
    4452              :                                                 {
    4453              :                                                         startFace = iFa;
    4454              :                                                         break;
    4455              :                                                 }
    4456              :                                         }
    4457              : 
    4458              : 
    4459              :                                 }
    4460              : 
    4461              :                                 if( vVFT.size() != 0 )
    4462              :                                 {
    4463              :                                         UG_THROW("not all triples found! " << std::endl);
    4464              :                                 }
    4465              : 
    4466              :                                 if( aF.size() != 0 )
    4467              :                                         UG_THROW("not all faces found " << std::endl);
    4468              : 
    4469              :                                 if( startEdg != originalStartEdge )
    4470              :                                 {
    4471              :                                         UG_THROW("wir sind nicht am Anfang wieder angekommen" << std::endl);
    4472              :                                 }
    4473              : 
    4474              : 
    4475              :                                 if( segmentPart.size() != 0 )
    4476              :                                 {
    4477              :                                         UG_THROW("die Segmentteile muessen alle verarbeitet sein"  << std::endl);
    4478              :                                 }
    4479              : 
    4480              :                                 UG_LOG("Kreislauf geschlossen" << std::endl);
    4481              : 
    4482              : #endif
    4483              : 
    4484              :                                 // test if the segments and their partition produce sumething useful, for debug purposes
    4485              : 
    4486              :                                 // als nächstes muss man die Klassen von durch Klüften abgetrennten ordered Faces durchgehen, und die Verschiebevertizes erzeugen
    4487              :                                 // als nächstes die verschiedenen Sektionen durch gehen, eventuell nochmal extra Objekte dafür erzeugen
    4488              :                                 // oder gleich beim Durchgehen die neuen Vertizes erzeugen, Startsignal durch ein Face mit erster Edge KLuft, und dann die nächste
    4489              :                                 // Kluftedge finden, egal ob vom gleihen face oder von einem späteren face im kreis
    4490              : 
    4491              :                                 // now figure out to which face this next edge belongs, and if this is a fracture edge, then we have the triple and the normal info
    4492              :                                 // else we let the normal zero
    4493              : 
    4494              :                                 // figure out if second edge is also frac edge, i.e. if it belongs to an edge  of the remaining vVFT elements
    4495              :                                 // first easily asking if it is marked as frac edge, simplifies research
    4496              : 
    4497              :                                 // in principle from here on need to loop through all triples and through all faces, find out some way to construct next edge and to
    4498              :                                 // build one element after the other of the ordered faces vector, still even the first element is not completed
    4499              : 
    4500              :                                 // TODO FIXME kreuzende Fractures im Innenraum -> Arte in Reinform implementieren
    4501              :                                 // later assign somehow next edge to start edge, or use new variable, when we have figured out next face
    4502              :                                 // at end, chech if we have arrived again at original first edge
    4503              : 
    4504              : 
    4505              :                                 int totalSubsNum = sh.num_subsets();
    4506              : 
    4507              : //                              int newSubsToAdd = totalSubsNum;
    4508              : 
    4509              : //                              for( VertexOfFaceInfo const & vertFracInfo : orderedFaces )
    4510              : //                              {
    4511              : ////                                    Face * fa = vertFracInfo.getFace();
    4512              : ////
    4513              : ////                                    sh.assign_subset(fa,newSubsToAdd++);
    4514              : //                              }
    4515              : 
    4516              :                                 number totAnglsEdg = 0;
    4517              :                                 number totAnglsNrm = 0;
    4518              : 
    4519            0 :                                 for( VecVertexOfFaceInfo const & segPart : segments )
    4520              :                                 {
    4521              : //                                      newSubsToAdd++;
    4522              : 
    4523            0 :                                         IndexType numbTriangs = segPart.size();
    4524              : 
    4525            0 :                                         if( numbAttTripl == 0 )
    4526              :                                         {
    4527            0 :                                                 UG_THROW("zu wenig Dreiecke " << std::endl);
    4528              :                                         }
    4529              : 
    4530              :                                         VertexOfFaceInfo const & vFISBegin = segPart[0];
    4531            0 :                                         VertexOfFaceInfo const & vFISEnd = segPart[numbTriangs-1];
    4532              : 
    4533              :                                         std::pair<Edge*, Edge* >  edgesBegin = vFISBegin.getEdge();
    4534              :                                         std::pair<Edge*, Edge* >  edgesEnd = vFISEnd.getEdge();
    4535              : 
    4536              :                                         std::pair<vector3, vector3> normalBegin = vFISBegin.getNormal();
    4537              :                                         std::pair<vector3, vector3> normalEnd = vFISEnd.getNormal();
    4538              : 
    4539            0 :                                         Edge* edgeFracOne = edgesBegin.first;
    4540            0 :                                         Edge* edgeFracTwo = edgesEnd.second;
    4541              : 
    4542            0 :                                         auto subsIndFracOne = sh.get_subset_index(edgeFracOne);
    4543              :                                         auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo);
    4544              : 
    4545              :                                         vector3 normalFracOne = normalBegin.first;
    4546              :                                         vector3 normalFracTwo = normalEnd.second;
    4547              : 
    4548              : //                                      sh.assign_subset(edgeFracOne, newSubsToAdd);
    4549              : //
    4550              : //                                      if( edgeFracTwo != originalStartEdge )
    4551              : //                                              sh.assign_subset(edgeFracTwo, newSubsToAdd);
    4552              : 
    4553              :                                         // neue Punkte erzeugen
    4554              : 
    4555              :                                         number cosBetweenNormals = VecDot( normalFracOne, normalFracTwo );
    4556              : 
    4557              :                                         constexpr bool useOldMethodeNotAngleDep = false;
    4558              : 
    4559              :                                         if( useOldMethodeNotAngleDep )
    4560              :                                         {
    4561              : 
    4562              :                                                 if( subsIndFracOne == subsIndFracTwo )
    4563              :                                                 {
    4564              :         //                                              if( numFracsCrossAtVrt != 3 )
    4565              :                                                         if( numFracsCrossAtVrt != 2 && numFracsCrossAtVrt != 3 )
    4566              :                                                         {
    4567              :         //                                                      UG_THROW("Fracture Segment an beiden Seiten gleiche sudo, aber keine T Kreuzung?" << std::endl);
    4568              :                                                                 UG_THROW("Fracture Segment an beiden Seiten gleiche sudo, aber keine durchgehende Kluft?" << std::endl);
    4569              :                                                         }
    4570              : 
    4571              :                                                         // dieselben Methoden wie im Fall von einer durchgehenden Kluft an einem Vertex, dort kopieren
    4572              :                                                         // bzw Funktion schreiben, die beides macht
    4573              : 
    4574              :                                                         // hier wird der Fall abgezweigt, dass wir auf der durchgehenden Seite einer Kluft sind
    4575              :                                                         // wenn wir eine T-Kreuzung haben
    4576              : 
    4577              :                                                         std::vector<Vertex *> nextFracVrt;
    4578              : 
    4579              :                                                         IndexType foundThisVrtOne = 0;
    4580              : 
    4581              :                                                         for( size_t i = 0; i < 2; ++i )
    4582              :                                                         {
    4583              :                                                                 Vertex * vrtEdgEnd = edgeFracOne->vertex(i);
    4584              : 
    4585              :                                                                 if( vrtEdgEnd == *iterV )
    4586              :                                                                 {
    4587              :                                                                         foundThisVrtOne++;
    4588              :                                                                 }
    4589              :                                                                 else
    4590              :                                                                 {
    4591              :                                                                         nextFracVrt.push_back( vrtEdgEnd );
    4592              :                                                                 }
    4593              : 
    4594              :                                                         }
    4595              : 
    4596              :                                                         if( foundThisVrtOne != 1 )
    4597              :                                                         {
    4598              :                                                                 UG_THROW("zu viel zu wenig vertizex one " << std::endl);
    4599              :                                                         }
    4600              : 
    4601              : 
    4602              :                                                         IndexType foundThisVrtTwo = 0;
    4603              : 
    4604              :                                                         for( size_t i = 0; i < 2; ++i )
    4605              :                                                         {
    4606              :                                                                 Vertex * vrtEdgEnd = edgeFracTwo->vertex(i);
    4607              : 
    4608              :                                                                 if( vrtEdgEnd == *iterV )
    4609              :                                                                 {
    4610              :                                                                         foundThisVrtTwo++;
    4611              :                                                                 }
    4612              :                                                                 else
    4613              :                                                                 {
    4614              :                                                                         nextFracVrt.push_back( vrtEdgEnd );
    4615              :                                                                 }
    4616              : 
    4617              :                                                         }
    4618              : 
    4619              :                                                         if( foundThisVrtTwo != 1 )
    4620              :                                                         {
    4621              :                                                                 UG_THROW("zu viel zu wenig vertizex two " << std::endl);
    4622              :                                                         }
    4623              : 
    4624              :                                                         Face *  faceBegin = vFISBegin.getFace();
    4625              :                                                         Face *  faceEnd = vFISEnd.getFace();
    4626              : 
    4627              : 
    4628              :                                                         // TODO FIXME hier die Segmentinformation übergeben, da die Faces bekannt sind, die dran hängen!!!!!
    4629              :         //                                              expandSingleFractureAtGivenSide( normalFracTwo, normalFracTwo,
    4630              :         //                                                                                                               edgeFracOne, edgeFracTwo,
    4631              :         //                                                                                                               faceBegin, faceEnd,
    4632              :         //                                                                                                               fracInfosBySubset,
    4633              :         //                                                                                                               posOldVrt,
    4634              :         //                                                                                                               aaPos,
    4635              :         //                                                                                                               grid, sh,
    4636              :         //                                                                                                               assoFaces,
    4637              :         //                                                                                                               nextFracVrt,
    4638              :         //                                                                                                               aaVrtVecFace,
    4639              :         //                                                                                                               dbg_flachen_passiert,
    4640              :         //                                                                                                               *iterV,
    4641              :         //                                                                                                               crossVrtInf,
    4642              :         //                                                                                                               ( numFracsCrossAtVrt == 3 )
    4643              :         //                                                                                                              );
    4644              :                                                         expandSingleFractureAtGivenSide( normalFracOne, normalFracTwo,
    4645              :                                                                                                                          edgeFracOne, edgeFracTwo,
    4646              :                                                                                                                          faceBegin, faceEnd,
    4647              :                                                                                                                          fracInfosBySubset,
    4648              :                                                                                                                          posOldVrt,
    4649              :                                                                                                                          aaPos,
    4650              :                                                                                                                          grid, sh,
    4651              :                                                                                                                          segPart,
    4652              :                                                                                                                          nextFracVrt,
    4653              :                                                                                                                          aaVrtVecFace,
    4654              :                                                                                                                          dbg_flachen_passiert,
    4655              :                                                                                                                          *iterV,
    4656              :                                                                                                                          crossVrtInf,
    4657              :                                                                                                                          ( numFracsCrossAtVrt == 3 )
    4658              :                                                                                                                         );
    4659              : 
    4660              : 
    4661              : 
    4662              :                                                 }
    4663              :                                                 else
    4664              :                                                 {
    4665              : 
    4666              : //                                                      UG_THROW("in dieser Funktion alt" << std::endl);
    4667              : 
    4668              :                                                         // create normal vectors into direction of relevant edges
    4669              : 
    4670              :                                                         vector3 alongEdgeOne;
    4671              :                                                         vector3 alongEdgeTwo;
    4672              : 
    4673              :                                                         Vertex * vrtEdgeOneBegin = nullptr;
    4674              :                                                         Vertex * vrtEdgeTwoBegin = nullptr;
    4675              :                                                         Vertex * vrtEdgeOneEnd = nullptr;
    4676              :                                                         Vertex * vrtEdgeTwoEnd = nullptr;
    4677              : 
    4678              : 
    4679              :                                                         for( size_t i = 0; i < 2; ++i )
    4680              :                                                         {
    4681              :                                                                 Vertex * vrtFromEdgeOne = edgeFracOne->vertex(i);
    4682              :                                                                 Vertex * vrtFromEdgeTwo = edgeFracTwo->vertex(i);
    4683              : 
    4684              :                                                                 if( vrtFromEdgeOne == *iterV )
    4685              :                                                                 {
    4686              :                                                                         vrtEdgeOneBegin = vrtFromEdgeOne;
    4687              :                                                                 }
    4688              :                                                                 else
    4689              :                                                                 {
    4690              :                                                                         vrtEdgeOneEnd = vrtFromEdgeOne;
    4691              :                                                                 }
    4692              : 
    4693              :                                                                 if( vrtFromEdgeTwo == *iterV )
    4694              :                                                                 {
    4695              :                                                                         vrtEdgeTwoBegin = vrtFromEdgeTwo;
    4696              :                                                                 }
    4697              :                                                                 else
    4698              :                                                                 {
    4699              :                                                                         vrtEdgeTwoEnd = vrtFromEdgeTwo;
    4700              :                                                                 }
    4701              : 
    4702              :                                                         }
    4703              : 
    4704              :                                                         if( vrtEdgeOneBegin == nullptr || vrtEdgeTwoBegin == nullptr || vrtEdgeOneEnd == nullptr || vrtEdgeTwoEnd == nullptr )
    4705              :                                                         {
    4706              :                                                                 UG_THROW("lauter Nullen vertizes" << std::endl);
    4707              :                                                         }
    4708              : 
    4709              :                                                         vector3 fracVrtPos = aaPos[*iterV];
    4710              : 
    4711              :                                                         vector3 fracEdgOneEndPos = aaPos[ vrtEdgeOneEnd ];
    4712              :                                                         vector3 fracEdgTwoEndPos = aaPos[ vrtEdgeTwoEnd ];
    4713              : 
    4714              :                                                         vector3 directionEdgOne;
    4715              :                                                         VecSubtract(directionEdgOne, fracEdgOneEndPos, fracVrtPos);
    4716              : 
    4717              :                                                         vector3 directionEdgTwo;
    4718              :                                                         VecSubtract(directionEdgTwo, fracEdgTwoEndPos, fracVrtPos);
    4719              : 
    4720              :                                                         vector3 nrmdVecEdgOne;
    4721              :                                                         VecNormalize(nrmdVecEdgOne, directionEdgOne);
    4722              : 
    4723              :                                                         vector3 nrmdVecEdgTwo;
    4724              :                                                         VecNormalize(nrmdVecEdgTwo, directionEdgTwo);
    4725              : 
    4726              :                                                         number cosBetweenEdges = VecDot(nrmdVecEdgOne,nrmdVecEdgTwo);
    4727              : 
    4728              :                                                         // TODO FIXME wenn Winkel zu klein, dann die Methode verwenden der Mittelung der beiden Normalen!!!!
    4729              : 
    4730              :                                                         number angleEdges = std::acos( cosBetweenEdges );
    4731              :                                                         number angleNormls = std::acos( cosBetweenNormals );
    4732              : 
    4733              :                                                         totAnglsEdg += angleEdges;
    4734              :                                                         totAnglsNrm += angleNormls;
    4735              : 
    4736              :                                                         UG_LOG("cosinus Edges Normals " << cosBetweenEdges << "  " << cosBetweenNormals << std::endl);
    4737              :                                                         UG_LOG("angles edges normals " << angleEdges << "  " << angleNormls << std::endl);
    4738              : 
    4739              :                                                         // prject normal 1 onto edge 2 and normal 2 on edge 1, scale with width one half resp with width two half
    4740              : 
    4741              : 
    4742              :                                                         number cosBetweenNrmFraOneEdgTwo = VecDot(normalFracOne,nrmdVecEdgTwo);
    4743              :                                                         number cosBetweenNrmFraTwoEdgOne = VecDot(normalFracTwo,nrmdVecEdgOne);
    4744              : 
    4745              :                                                         vector3 projectNrmFraOneToEdgTwoDirection;
    4746              :                                                         VecScale(projectNrmFraOneToEdgTwoDirection, nrmdVecEdgTwo, 1./cosBetweenNrmFraOneEdgTwo);
    4747              : 
    4748              :                                                         vector3 projectNrmFraTwoToEdgOneDirection;
    4749              :                                                         VecScale(projectNrmFraTwoToEdgOneDirection, nrmdVecEdgOne, 1./cosBetweenNrmFraTwoEdgOne);
    4750              : 
    4751              :                 //                                      auto subsIndFracOne = sh.get_subset_index(edgeFracOne);
    4752              :                 //                                      auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo);
    4753              : 
    4754              :                                                         number shiftOne = fracInfosBySubset.at( subsIndFracOne ).width / 2. ;
    4755              :                                                         number shiftTwo = fracInfosBySubset.at( subsIndFracTwo ).width / 2. ;
    4756              : 
    4757              :                                                         vector3 shiftAlongEdgeTwo;
    4758              :                                                         VecScale(shiftAlongEdgeTwo, projectNrmFraOneToEdgTwoDirection, shiftOne);
    4759              : 
    4760              :                                                         vector3 shiftAlongEdgeOne;
    4761              :                                                         VecScale(shiftAlongEdgeOne, projectNrmFraTwoToEdgOneDirection, shiftTwo);
    4762              : 
    4763              :                                                         vector3 shiftPart;
    4764              :                                                         VecAdd(shiftPart, fracVrtPos, shiftAlongEdgeTwo);
    4765              : 
    4766              :                                                         vector3 posNewVrt;
    4767              :                                                         VecAdd( posNewVrt, shiftPart, shiftAlongEdgeOne);
    4768              : 
    4769              :                                                         UG_LOG("neuer Vertex Kreuzung " << posNewVrt << std::endl );
    4770              : 
    4771              :                                                         Vertex * newShiftVrtx = *grid.create<RegularVertex>();
    4772              :                                                         aaPos[newShiftVrtx] = posNewVrt;
    4773              : 
    4774              :                                                         //                                      sh.assign_subset(newShiftVrtx,  newSubsToAdd );
    4775              :                                                         sh.assign_subset(newShiftVrtx, subsIndFracOne );
    4776              :                                                         // could also be two, but have to select one, no Kompromiss possible......
    4777              : 
    4778              :                                                         crossVrtInf.addShiftVrtx(newShiftVrtx);
    4779              : 
    4780              :         //                                              UG_LOG("ADDED SHIFT VECTOR " << aaPos[newShiftVrtx] << std::endl);
    4781              : 
    4782              :                                                         // TODO FIXME eigene Funktion, da bei 2 und 3 Klüften exakt dieselbe Routine, mit copy und paste übernommen worden
    4783              : 
    4784              :                                                         for( VertexOfFaceInfo const & vertFracInfoSeg : segPart )
    4785              :                                                         {
    4786              :                                                                 Face * fac = vertFracInfoSeg.getFace();
    4787              : 
    4788              :                 //                                              sh.assign_subset(fa,newSubsToAdd);
    4789              : 
    4790              : 
    4791              :                                                                 // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu Prof. Reiter! nicht später falsche verwenden!
    4792              :                                                                 vector<Vertex*>& newVrts4Fac = aaVrtVecFace[ fac ];
    4793              : 
    4794              :                                                                 IndexType vrtxFnd = 0;
    4795              : 
    4796              :                                                                 for(size_t indVrt = 0; indVrt < (fac)->num_vertices();  indVrt++ )
    4797              :                                                                 {
    4798              :                                                                         Vertex* facVrt = (fac)->vertex(indVrt);
    4799              : 
    4800              :                                                                         if(  facVrt == *iterV )
    4801              :                                                                         {
    4802              :                                                                                 newVrts4Fac[ indVrt ] = newShiftVrtx;
    4803              :                                                                                 vrtxFnd++;
    4804              : 
    4805              :         //                                                                      crossVrtInf.addShiftVrtx(newShiftVrtx);
    4806              :         //
    4807              :         //                                                                      UG_LOG("ADDED SHIFT VECTOR " << aaPos[newShiftVrtx] << std::endl);
    4808              : 
    4809              :                                                                         }
    4810              :                                                                 }
    4811              : 
    4812              :         //                                                      crossVrtInf.setShiftVrtx(newVrts4Fac);
    4813              : 
    4814              :                                                                 if( vrtxFnd <= 0 )
    4815              :                                                                 {
    4816              :                                                                         UG_THROW("vertex not found kreuzung!" << std::endl);
    4817              :                                                                                                                                         }
    4818              :                                                                 else if( vrtxFnd > 1 )
    4819              :                                                                 {
    4820              :                                                                         UG_THROW("vertex zu oft gefunden kreuzung " << vrtxFnd << std::endl );
    4821              :                                                                 }
    4822              :                                                                 else if ( vrtxFnd == 1 )
    4823              :                                                                 {
    4824              :                                                                 }
    4825              :                                                                 else
    4826              :                                                                 {
    4827              :                                                                         UG_THROW("vertex finden komisch kreuzung " << std::endl);
    4828              :                                                                 }
    4829              : 
    4830              :                                                         }
    4831              :                                                 }
    4832              :                                         }
    4833              :                                         else // angle dependent, new method
    4834              :                                         {
    4835            0 :                                                 if( subsIndFracOne == subsIndFracTwo )
    4836              :                                                 {
    4837              :         //                                              if( numFracsCrossAtVrt != 3 )
    4838            0 :                                                         if( numFracsCrossAtVrt != 2 && numFracsCrossAtVrt != 3 )
    4839              :                                                         {
    4840              :         //                                                      UG_THROW("Fracture Segment an beiden Seiten gleiche sudo, aber keine T Kreuzung?" << std::endl);
    4841            0 :                                                                 UG_THROW("Fracture Segment an beiden Seiten gleiche sudo, aber keine durchgehende Kluft?" << std::endl);
    4842              :                                                         }
    4843              :                                                 }
    4844              : 
    4845            0 :                                                 if( subsIndFracOne != subsIndFracTwo && numFracsCrossAtVrt == 2 )
    4846              :                                                 {
    4847            0 :                                                         UG_THROW("subsets passen nicht Vereinheitlichung" << std::endl );
    4848              :                                                 }
    4849              : 
    4850              :                                                 vector3 moveVrt;
    4851              : 
    4852              :                                                 number pi = 3.1415926535897932385;
    4853              : 
    4854              :                                                 number cosinusLim = std::cos( pi/8. );
    4855              : 
    4856              :                                                 vector3 posNewVrt;
    4857              : 
    4858              : //                                              if( cosBetweenNormals > cosinusLim )
    4859            0 :                                                 if( cosBetweenNormals > cosinusLim && numFracsCrossAtVrt < 4 )
    4860              : //                                              if( cosBetweenNormals > cosinusLim && subsIndFracOne == subsIndFracTwo )
    4861              : //                                              if( false )
    4862              :                                                 {
    4863              : 
    4864              : //                                                      UG_THROW("in dieser Funktion neu cos" << std::endl);
    4865              : 
    4866              : 
    4867              :                                                         // dieselben Methoden wie im Fall von einer durchgehenden Kluft an einem Vertex, dort kopieren
    4868              :                                                         // bzw Funktion schreiben, die beides macht
    4869              : 
    4870              :                                                         // hier wird der Fall abgezweigt, dass wir auf der durchgehenden Seite einer Kluft sind
    4871              :                                                         // wenn wir eine T-Kreuzung haben
    4872              : 
    4873              :                                                         std::vector<Vertex *> nextFracVrt;
    4874              : 
    4875              :                                                         IndexType foundThisVrtOne = 0;
    4876              : 
    4877            0 :                                                         for( size_t i = 0; i < 2; ++i )
    4878              :                                                         {
    4879            0 :                                                                 Vertex * vrtEdgEnd = edgeFracOne->vertex(i);
    4880              : 
    4881            0 :                                                                 if( vrtEdgEnd == *iterV )
    4882              :                                                                 {
    4883            0 :                                                                         foundThisVrtOne++;
    4884              :                                                                 }
    4885              :                                                                 else
    4886              :                                                                 {
    4887            0 :                                                                         nextFracVrt.push_back( vrtEdgEnd );
    4888              :                                                                 }
    4889              : 
    4890              :                                                         }
    4891              : 
    4892            0 :                                                         if( foundThisVrtOne != 1 )
    4893              :                                                         {
    4894            0 :                                                                 UG_THROW("zu viel zu wenig vertizex one " << std::endl);
    4895              :                                                         }
    4896              : 
    4897              : 
    4898              :                                                         IndexType foundThisVrtTwo = 0;
    4899              : 
    4900            0 :                                                         for( size_t i = 0; i < 2; ++i )
    4901              :                                                         {
    4902            0 :                                                                 Vertex * vrtEdgEnd = edgeFracTwo->vertex(i);
    4903              : 
    4904            0 :                                                                 if( vrtEdgEnd == *iterV )
    4905              :                                                                 {
    4906            0 :                                                                         foundThisVrtTwo++;
    4907              :                                                                 }
    4908              :                                                                 else
    4909              :                                                                 {
    4910            0 :                                                                         nextFracVrt.push_back( vrtEdgEnd );
    4911              :                                                                 }
    4912              : 
    4913              :                                                         }
    4914              : 
    4915            0 :                                                         if( foundThisVrtTwo != 1 )
    4916              :                                                         {
    4917            0 :                                                                 UG_THROW("zu viel zu wenig vertizex two " << std::endl);
    4918              :                                                         }
    4919              : 
    4920            0 :                                                         Face *  faceBegin = vFISBegin.getFace();
    4921            0 :                                                         Face *  faceEnd = vFISEnd.getFace();
    4922              : 
    4923              : 
    4924              :                                                         vector3 normSum;
    4925              : 
    4926              :                                                         VecAdd( normSum, normalFracOne, normalFracTwo );
    4927              : 
    4928              :                                                         vector3 normSumNormed;
    4929              : 
    4930            0 :                                                         VecNormalize(normSumNormed, normSum);
    4931              : 
    4932            0 :                                                         UG_LOG("averaged normal " << normSumNormed << std::endl);
    4933              : 
    4934              :                                                         std::vector<Edge * > attEdg;
    4935              :                                                         std::vector<Face * > attFac;
    4936              : 
    4937            0 :                                                         attEdg.push_back( edgeFracOne );
    4938            0 :                                                         attEdg.push_back( edgeFracTwo );
    4939              : 
    4940            0 :                                                         attFac.push_back( faceBegin );
    4941            0 :                                                         attFac.push_back( faceEnd );
    4942              : 
    4943              :                                                         // jetzt neuen Vertex erzeugen in Richtung der Normalen
    4944              :                                                         // sonst ist das attachment Schwachsinn!
    4945              : 
    4946            0 :                                                         number widthOne = fracInfosBySubset.at(subsIndFracOne).width;
    4947            0 :                                                         number widthTwo = fracInfosBySubset.at(subsIndFracTwo).width;
    4948              : 
    4949            0 :                                                         number width = ( widthOne + widthTwo ) /2.;
    4950              : 
    4951              :                                                         // FALSCH
    4952              :                                                         // der Faktor ist Käse und muss noch aus den Eingaben übernommen werden
    4953            0 :                                                         VecScale(moveVrt, normSumNormed, width/2. );
    4954              : 
    4955              : //                                                      vector3 posNewVrt;
    4956              : 
    4957              :                                                         VecAdd(posNewVrt, posOldVrt, moveVrt );
    4958              : 
    4959            0 :                                                         UG_LOG("neuer Vertex " << posNewVrt << std::endl );
    4960              : 
    4961              :                                                         // TODO FIXME hier ist das PROBLEM, SEGFAULT durch create regular vertex
    4962              : 
    4963            0 :                                                 }
    4964              :                                                 else
    4965              :                                                 {
    4966              : 
    4967              : //                                                      UG_THROW("in dieser Funktion neu" << std::endl);
    4968              : 
    4969              :                                                         // create normal vectors into direction of relevant edges
    4970              : 
    4971              :                                                         vector3 alongEdgeOne;
    4972              :                                                         vector3 alongEdgeTwo;
    4973              : 
    4974              :                                                         Vertex * vrtEdgeOneBegin = nullptr;
    4975              :                                                         Vertex * vrtEdgeTwoBegin = nullptr;
    4976              :                                                         Vertex * vrtEdgeOneEnd = nullptr;
    4977              :                                                         Vertex * vrtEdgeTwoEnd = nullptr;
    4978              : 
    4979              : 
    4980            0 :                                                         for( size_t i = 0; i < 2; ++i )
    4981              :                                                         {
    4982            0 :                                                                 Vertex * vrtFromEdgeOne = edgeFracOne->vertex(i);
    4983            0 :                                                                 Vertex * vrtFromEdgeTwo = edgeFracTwo->vertex(i);
    4984              : 
    4985            0 :                                                                 if( vrtFromEdgeOne == *iterV )
    4986              :                                                                 {
    4987              :                                                                         vrtEdgeOneBegin = vrtFromEdgeOne;
    4988              :                                                                 }
    4989              :                                                                 else
    4990              :                                                                 {
    4991              :                                                                         vrtEdgeOneEnd = vrtFromEdgeOne;
    4992              :                                                                 }
    4993              : 
    4994            0 :                                                                 if( vrtFromEdgeTwo == *iterV )
    4995              :                                                                 {
    4996              :                                                                         vrtEdgeTwoBegin = vrtFromEdgeTwo;
    4997              :                                                                 }
    4998              :                                                                 else
    4999              :                                                                 {
    5000              :                                                                         vrtEdgeTwoEnd = vrtFromEdgeTwo;
    5001              :                                                                 }
    5002              : 
    5003              :                                                         }
    5004              : 
    5005            0 :                                                         if( vrtEdgeOneBegin == nullptr || vrtEdgeTwoBegin == nullptr || vrtEdgeOneEnd == nullptr || vrtEdgeTwoEnd == nullptr )
    5006              :                                                         {
    5007            0 :                                                                 UG_THROW("lauter Nullen vertizes" << std::endl);
    5008              :                                                         }
    5009              : 
    5010              :                                                         vector3 fracVrtPos = aaPos[*iterV];
    5011              : 
    5012              :                                                         vector3 fracEdgOneEndPos = aaPos[ vrtEdgeOneEnd ];
    5013              :                                                         vector3 fracEdgTwoEndPos = aaPos[ vrtEdgeTwoEnd ];
    5014              : 
    5015              :                                                         vector3 directionEdgOne;
    5016              :                                                         VecSubtract(directionEdgOne, fracEdgOneEndPos, fracVrtPos);
    5017              : 
    5018              :                                                         vector3 directionEdgTwo;
    5019              :                                                         VecSubtract(directionEdgTwo, fracEdgTwoEndPos, fracVrtPos);
    5020              : 
    5021              :                                                         vector3 nrmdVecEdgOne;
    5022            0 :                                                         VecNormalize(nrmdVecEdgOne, directionEdgOne);
    5023              : 
    5024              :                                                         vector3 nrmdVecEdgTwo;
    5025            0 :                                                         VecNormalize(nrmdVecEdgTwo, directionEdgTwo);
    5026              : 
    5027              :                                                         number cosBetweenEdges = VecDot(nrmdVecEdgOne,nrmdVecEdgTwo);
    5028              : 
    5029              :                                                         // TODO FIXME wenn Winkel zu klein, dann die Methode verwenden der Mittelung der beiden Normalen!!!!
    5030              : 
    5031            0 :                                                         number angleEdges = std::acos( cosBetweenEdges );
    5032            0 :                                                         number angleNormls = std::acos( cosBetweenNormals );
    5033              : 
    5034            0 :                                                         totAnglsEdg += angleEdges;
    5035            0 :                                                         totAnglsNrm += angleNormls;
    5036              : 
    5037              :                                                         UG_LOG("cosinus Edges Normals " << cosBetweenEdges << "  " << cosBetweenNormals << std::endl);
    5038              :                                                         UG_LOG("angles edges normals " << angleEdges << "  " << angleNormls << std::endl);
    5039              : 
    5040              :                                                         // prject normal 1 onto edge 2 and normal 2 on edge 1, scale with width one half resp with width two half
    5041              : 
    5042              : 
    5043              :                                                         number cosBetweenNrmFraOneEdgTwo = VecDot(normalFracOne,nrmdVecEdgTwo);
    5044              :                                                         number cosBetweenNrmFraTwoEdgOne = VecDot(normalFracTwo,nrmdVecEdgOne);
    5045              : 
    5046              :                                                         vector3 projectNrmFraOneToEdgTwoDirection;
    5047            0 :                                                         VecScale(projectNrmFraOneToEdgTwoDirection, nrmdVecEdgTwo, 1./cosBetweenNrmFraOneEdgTwo);
    5048              : 
    5049              :                                                         vector3 projectNrmFraTwoToEdgOneDirection;
    5050            0 :                                                         VecScale(projectNrmFraTwoToEdgOneDirection, nrmdVecEdgOne, 1./cosBetweenNrmFraTwoEdgOne);
    5051              : 
    5052              :                 //                                      auto subsIndFracOne = sh.get_subset_index(edgeFracOne);
    5053              :                 //                                      auto subsIndFracTwo = sh.get_subset_index(edgeFracTwo);
    5054              : 
    5055            0 :                                                         number shiftOne = fracInfosBySubset.at( subsIndFracOne ).width / 2. ;
    5056            0 :                                                         number shiftTwo = fracInfosBySubset.at( subsIndFracTwo ).width / 2. ;
    5057              : 
    5058              :                                                         vector3 shiftAlongEdgeTwo;
    5059              :                                                         VecScale(shiftAlongEdgeTwo, projectNrmFraOneToEdgTwoDirection, shiftOne);
    5060              : 
    5061              :                                                         vector3 shiftAlongEdgeOne;
    5062              :                                                         VecScale(shiftAlongEdgeOne, projectNrmFraTwoToEdgOneDirection, shiftTwo);
    5063              : 
    5064              :                                                         vector3 shiftPart;
    5065              :                                                         VecAdd(shiftPart, fracVrtPos, shiftAlongEdgeTwo);
    5066              : 
    5067              : //                                                      vector3 posNewVrt;
    5068              :                                                         VecAdd( posNewVrt, shiftPart, shiftAlongEdgeOne);
    5069              : 
    5070            0 :                                                         UG_LOG("neuer Vertex Kreuzung " << posNewVrt << std::endl );
    5071              :                                                 }
    5072              : 
    5073            0 :                                                 Vertex * newShiftVrtx = *grid.create<RegularVertex>();
    5074              :                                                 aaPos[newShiftVrtx] = posNewVrt;
    5075              : 
    5076            0 :                                                 sh.assign_subset(newShiftVrtx, subsIndFracOne );
    5077              : 
    5078              : 
    5079            0 :                                                 if( numFracsCrossAtVrt > 2 )
    5080              :                                                 {
    5081              :                                                         bool isAtFreeTEnd = false;
    5082              : 
    5083            0 :                                                         if( numFracsCrossAtVrt == 3 && subsIndFracOne == subsIndFracTwo )
    5084              :                                                                 isAtFreeTEnd = true;
    5085              : 
    5086            0 :                                                         crossVrtInf.addShiftVrtx(newShiftVrtx, isAtFreeTEnd );
    5087              :                                                 }
    5088              : 
    5089              : #if 1
    5090            0 :                                                 teachAssoFacesNewVrtx(  segPart, aaVrtVecFace, *iterV, newShiftVrtx );
    5091              : 
    5092              : #else
    5093              :                                                 for( VertexOfFaceInfo const & vertFracInfoSeg : segPart )
    5094              :                                                 {
    5095              :                                                         Face * fac = vertFracInfoSeg.getFace();
    5096              : 
    5097              :         //                                              sh.assign_subset(fa,newSubsToAdd);
    5098              : 
    5099              :                                                         // ACHTUNG neue Variable Face klein geschrieben im Gegensatz zu SR! nicht später falsche verwenden!
    5100              :                                                         vector<Vertex*>& newVrts4Fac = aaVrtVecFace[ fac ];
    5101              : 
    5102              :                                                         IndexType vrtxFnd = 0;
    5103              : 
    5104              :                                                         for(size_t indVrt = 0; indVrt < (fac)->num_vertices();  indVrt++ )
    5105              :                                                         {
    5106              :                                                                 Vertex* facVrt = (fac)->vertex(indVrt);
    5107              : 
    5108              :                                                                 if(  facVrt == *iterV )
    5109              :                                                                 {
    5110              :                                                                         newVrts4Fac[ indVrt ] = newShiftVrtx;
    5111              :                                                                         vrtxFnd++;
    5112              : 
    5113              : //                                                                      UG_LOG("ADDED SHIFT VECTOR " << aaPos[newShiftVrtx] << std::endl);
    5114              : 
    5115              :                                                                 }
    5116              :                                                         }
    5117              : 
    5118              :                                                         if( vrtxFnd <= 0 )
    5119              :                                                         {
    5120              :                                                                 UG_THROW("vertex not found kreuzung!" << std::endl);
    5121              :                                                                                                                                 }
    5122              :                                                         else if( vrtxFnd > 1 )
    5123              :                                                         {
    5124              :                                                                 UG_THROW("vertex zu oft gefunden kreuzung " << vrtxFnd << std::endl );
    5125              :                                                         }
    5126              :                                                         else if ( vrtxFnd == 1 )
    5127              :                                                         {
    5128              :                                                         }
    5129              :                                                         else
    5130              :                                                         {
    5131              :                                                                 UG_THROW("vertex finden komisch kreuzung " << std::endl);
    5132              :                                                         }
    5133              : 
    5134              :                                                 }
    5135              : #endif
    5136              :                                         }
    5137              : 
    5138              :                                 }
    5139              : 
    5140              :                                 UG_LOG("sum angles edges normals " << totAnglsEdg << "  " << totAnglsNrm << std::endl);
    5141              : 
    5142              : //                              return true;
    5143              : 
    5144              : #if 0
    5145              :                                 // das folgende ist vermutlich Unsinn TODO FIXME, waren wohl Versuche am Anfang..... nochmal prüfen!!!!
    5146              : 
    5147              :                                 // get starting point of the "rotation" around the vertex where fractures are crossing
    5148              : //                              for( auto & attVFT : vVFT ) // not const, as we need to erase found elements!
    5149              :                                 for( VecVertFracTrip::iterator itAttVFT = vVFT.begin(); itAttVFT !=  vVFT.end(); )
    5150              :                                 {
    5151              :                                         Face * facAtVrtWithFrac = itAttVFT->getFace();
    5152              : 
    5153              :                                         bool facFound = false;
    5154              : 
    5155              : //                                      for( auto const & ifac : assoFaces ) // not const, as we need to erase found elements!
    5156              :                                         for( std::vector<Face*>::iterator itFac = aF.begin(); itFac != aF.end(); )
    5157              :                                         {
    5158              :                                                 if( *itFac == facAtVrtWithFrac )
    5159              :                                                 {
    5160              :                                                         // found a starting face
    5161              :                                                         // copy first the found info, then delete the original one
    5162              :                                                         auto attVFTCop = *itAttVFT; // copy, not reference!
    5163              : 
    5164              :                                                         vVFT.erase(itAttVFT);
    5165              :                                                         aF.erase(itFac);
    5166              : 
    5167              :                                                         // TODO FIXME erase ifac and attVFT, how to do?
    5168              : 
    5169              :                                                         Face * startFace = facAtVrtWithFrac;
    5170              : 
    5171              :                                                         // now determine the common edge(s), the first edge of the vector must be a frac edge, the second one might be one
    5172              : 
    5173              :                                                         Edge * startEdg = attVFTCop.getEdge();
    5174              : 
    5175              :                                                         // unnecessary check, but for test purposes at beginning, later should be removed
    5176              :                                                         if( !FaceContains(facAtVrtWithFrac, startEdg ))
    5177              :                                                         {
    5178              :                                                                 UG_THROW("face hat ecke nicht, die es haben soll" << std::endl);
    5179              :                                                         }
    5180              : 
    5181              :                                                         // loop around the edges of the ifac face attached to the vertex
    5182              : 
    5183              :                                                         // determin second edge of the startFace, not stored in the vecVertFracTrip information
    5184              :                                                         // check number of common edges containing the same vertex
    5185              : 
    5186              :                                                         IndexType fndCommEdg = 0;
    5187              :                                                         std::vector<Edge*> assoEdg2Fac;
    5188              : 
    5189              :                                                         assoEdg2Fac.push_back( startEdg );
    5190              : 
    5191              :                                                         std::vector<vector3> assoNorm;
    5192              : 
    5193              :                                                         vector3 norm2Frac = attVFTCop.getNormal();
    5194              : 
    5195              :                                                         Edge * secondEdge;
    5196              :                                                         secondEdge = NULL;
    5197              : 
    5198              :                                                         for( auto const & iE : allAssoEdges ) // werden nicht gelöscht, deswegen Zugriff auf attachment direkt
    5199              :                                                         {
    5200              :                                                                 if( FaceContains(facAtVrtWithFrac, iE) )
    5201              :                                                                 {
    5202              :                                                                         fndCommEdg++;
    5203              :                                                                         if( iE != startEdg )
    5204              :                                                                         {
    5205              :                                                                                 secondEdge = iE;
    5206              :                                                                         }
    5207              :                                                                 }
    5208              : 
    5209              :                                                                 if( fndCommEdg != 2 )
    5210              :                                                                 {
    5211              :                                                                         UG_THROW("komische Anzahl gemeinsamer Ecke " << fndCommEdg << std::endl);
    5212              :                                                                 }
    5213              : 
    5214              :                                                                 if( secondEdge == NULL )
    5215              :                                                                 {
    5216              :                                                                         UG_THROW("wieso keine zweite Ecke gefunden???? " << std::endl);
    5217              :                                                                 }
    5218              : 
    5219              :                                                                 assoEdg2Fac.push_back(secondEdge);
    5220              : 
    5221              :                                                                 // check, if second edge belongs to anothter fracture fac, i.e. if it is also a fracture edge
    5222              : 
    5223              :                                                                 // check if second edge is edge of a fracture face, i.e. either this edge, or another one is from a fracture
    5224              : 
    5225              :                                                                 bool scndEdgIsFracEdg = aaMarkEdgeB[secondEdge];
    5226              : 
    5227              :                                                                 if( scndEdgIsFracEdg )
    5228              :                                                                 {
    5229              :                                                                         // TODO FIXME figure out second vertex fracture info, in this case, we have found the next part of the chain!
    5230              : 
    5231              :                                                                         for( VecVertFracTrip::iterator itAttVFTTwo = vVFT.begin(); itAttVFTTwo !=  vVFT.end(); )
    5232              :                                                                         {
    5233              :                                                                                 // need to erase also this element soon, also in the list of all attached elements
    5234              : 
    5235              :                                                                                 Face* vFTTwoFac = itAttVFTTwo->getFace();
    5236              : 
    5237              :                                                                                 if( FaceContains( vFTTwoFac, secondEdge))
    5238              :                                                                                 {
    5239              :                                                                                         auto vVFT2 = *itAttVFTTwo;
    5240              :                                                                                         vVFT.erase( itAttVFTTwo );
    5241              : 
    5242              :                                                                                         Face * nextFace = vFTTwoFac;
    5243              : 
    5244              :                                                                                         if( secondEdge != vVFT2.getEdge() )
    5245              :                                                                                         {
    5246              :                                                                                                 UG_THROW("Ecke nicht Ecke " << std::endl);
    5247              :                                                                                         }
    5248              : 
    5249              : 
    5250              :                                                                                 }
    5251              :                                                                         }
    5252              :                                                                 }
    5253              :                                                                 else // find the next attached face, either from the
    5254              :                                                                 {
    5255              : 
    5256              :                                                                 }
    5257              :                                                         }
    5258              : 
    5259              :                                                         break;
    5260              :                                                 }
    5261              : 
    5262              :                                                 if( ! facFound )
    5263              :                                                 {
    5264              :                                                         UG_THROW("Gesicht unauffindbar" << std::endl);
    5265              :                                                 }
    5266              : 
    5267              :                                                 break;
    5268              :                                         }
    5269              :                                 }
    5270              : 
    5271              :                                 while( vVFT.size() != 0 )
    5272              :                                 {
    5273              :                                         while( aF.size() != 0 )
    5274              :                                         {
    5275              : 
    5276              :                                         }
    5277              :                                 }
    5278              : 
    5279              : #endif
    5280              : 
    5281              : //                              if( numFracsCrossAtVrt == 3 )
    5282              : //                              {
    5283              : //                                      teeVrts.push_back(*iterV);
    5284              : //                              }
    5285              : //                              else if( numFracsCrossAtVrt == 4 )
    5286              : //                              {
    5287              : //                                      crossVrts.push_back(*iterV);
    5288              : //                              }
    5289              : 
    5290            0 :                                 IndexType groesseShiVe = crossVrtInf.getVecShiftedVrts().size();
    5291              : 
    5292              :                                 auto gro = groesseShiVe;
    5293              : 
    5294              :                                 UG_LOG("GROESSE SHIFT VECTORS " << gro << std::endl);
    5295              : 
    5296            0 :                                 vecCrossVrtInf.push_back(crossVrtInf);
    5297              : 
    5298            0 :                         }
    5299              : 
    5300              :                 }
    5301              : //              // // different treatment for boundary vertizes
    5302              :                 else
    5303              :                 {
    5304              : 
    5305              :                         // es muss wohl noch ein Problem mit den Verschiebungen bei boundary Vertizes geben.....
    5306              : 
    5307              : 
    5308            0 :                         if( numFracsCrossAtVrt < 1 )
    5309              :                         {
    5310            0 :                                 UG_THROW("no fracs crossing but marked vertex at boundary? << std::endl");
    5311              :                         }
    5312            0 :                         else if( numFracsCrossAtVrt == 1 ) // no crossing point  at boundary
    5313              :                         {
    5314              :                                 // in this case, we have ONE attached edges, the edges has two attached faces
    5315              :                                 // the faces have a normal, and based on the normal, we can decide which faces belong to the same side of the edges
    5316              : 
    5317            0 :                                 if( numbAttTripl != 2 )
    5318              :                                 {
    5319            0 :                                         UG_THROW("Anzahl der angehaengten Triples kann nicht stimmen, Vertex einer Kluft ohne Schnittpunkte  am Rand " << std::endl);
    5320              :                                 }
    5321              : 
    5322              :                                 VecVertexOfFaceInfo orderedFaces;
    5323              :                                 SegmentsFractExtrus segments;
    5324              :                                 //VecVertexOfFaceInfo segmentPart;
    5325              : 
    5326              :                                 // Zuordnung der Edges und Faces, die auf der gleichen Seite der fracture sind
    5327              : 
    5328              :                                 // und gleich auch Erzeugung der neuen Knoten, die dann
    5329              :                                 // in einem Doublett zusammen mit ihren Normalen an die alten Vertizes
    5330              :                                 // angehängt werden; der Winkel zur Normalen hilft später, die Seite
    5331              :                                 // heraus zu finden, Seite von den Edges
    5332              : 
    5333              :                                 // get  edges adjacent to this vertex which lie on the boundary of the domain
    5334              : 
    5335              :                                 std::vector<Edge* > adjBndEdgs;
    5336              : 
    5337              : //                              std::vector<Edge*> & allAssoEdges = aaVrtInfoAssoEdges[*iterV];
    5338              : 
    5339              : //                              for( std::vector<Edge*>::iterator iterBVEdg = grid.associated_edges_begin(*iterV); iterBVEdg != grid.associated_edges_end(*iterV); iterBVEdg++  )
    5340              : //                              {
    5341              : //                                      if( IsBoundaryEdge2D(grid,*iterBVEdg) )
    5342              : //                                      {
    5343              : //                                              adjBndEdgs.push_back( *iterBVEdg );
    5344              : //                                      }
    5345              : //                              }
    5346            0 :                                 for( auto const & iBVE : allAssoEdges )
    5347              :                                 {
    5348            0 :                                         if( IsBoundaryEdge2D(grid, iBVE ) )
    5349              :                                         {
    5350            0 :                                                 adjBndEdgs.push_back( iBVE );
    5351              :                                         }
    5352              :                                 }
    5353              : 
    5354            0 :                                 if( adjBndEdgs.size() != 2  )
    5355            0 :                                         UG_THROW("how many boundary edges????" << std::endl);
    5356              : 
    5357              :                                 IndexType startInd = -1; // to avoid errornous use
    5358              : 
    5359            0 :                                 Face * attFaceOf1stBndEdg = nullptr; // TODO FIXME bestimmen sofort!!!
    5360              : 
    5361            0 :                                 Edge * begOrdEdg = adjBndEdgs[0];
    5362              : 
    5363              :                                 IndexType fndBndFac = 0;
    5364              : 
    5365            0 :                                 for( std::vector<Face* >::iterator itFa = grid.associated_faces_begin(begOrdEdg);
    5366            0 :                                                 itFa < grid.associated_faces_end(begOrdEdg);
    5367              :                                                 itFa++ )
    5368              :                                 {
    5369            0 :                                         attFaceOf1stBndEdg = *itFa;
    5370            0 :                                         fndBndFac++;
    5371              :                                 }
    5372              : 
    5373            0 :                                 if( fndBndFac != 1 || attFaceOf1stBndEdg == nullptr )
    5374              :                                 {
    5375            0 :                                         UG_THROW("Grenzgesicht nicht gefunden " << fndBndFac << std::endl);
    5376              :                                 }
    5377              : 
    5378            0 :                                 determineOrderOfFaces( vecVertFracTrip, assoFaces, orderedFaces,
    5379              :                                                                                 segments,  //segmentPart,
    5380              :                                                                                 startInd,
    5381              :                                                                                 allAssoEdges,
    5382              :                                                                                 sh,
    5383              :                                                                                 aaMarkEdgeB,
    5384              :                                                                                 adjBndEdgs,
    5385              :                                                                                 attFaceOf1stBndEdg
    5386              :                                                                                 );
    5387              : 
    5388              : //                              for( auto const & segPart : segments )
    5389              : //                              {
    5390              : //                                      for( auto const & vi : segPart )
    5391              : //                                      {
    5392              : //                                              Face * fac = vi.getFace();
    5393              : //
    5394              : //                                              IndexType sudoNew = sh.num_subsets();
    5395              : //
    5396              : //                                              sh.assign_subset(fac, sudoNew);
    5397              : //                                      }
    5398              : //                              }
    5399              : //
    5400              : //                              return true;
    5401              : 
    5402              :                                 // to compute the normals, compute the vector of the edge and normalize it
    5403              :                                 std::vector<vector3> bndEdgeDirection;
    5404              : 
    5405            0 :                                 for( auto const & bE : adjBndEdgs )
    5406              :                                 {
    5407              : 
    5408              :                                         // get vertices, i.e. get seocnd vertex, first one must be known
    5409              : 
    5410              : //                                      std::vector<Vertex* > verticesEdg;
    5411              : 
    5412              :                                         // DEBUG ASSERT TEST static_assert( std::is_same< Edge* const &, decltype( bE ) >::value );
    5413              : 
    5414              :                                         // DEBUG ASSERT TEST static_assert( std::is_same< Vertex*, decltype( bE->vertex(0) ) >::value );
    5415              : 
    5416              :                                         IndexType fndIV = 0;
    5417              : 
    5418              :                                         Vertex * vrtOtherEdg;
    5419              :                                         vrtOtherEdg = NULL;
    5420              : 
    5421            0 :                                         for( size_t i = 0; i < 2; ++i )
    5422              :                                         {
    5423              : //                                              verticesEdg.push_back( adjBndEdgs.vertex(i) );
    5424              : 
    5425            0 :                                                 Vertex * vrtOfEdg = bE->vertex(i);
    5426              : 
    5427            0 :                                                 if( vrtOfEdg == *iterV )
    5428              :                                                 {
    5429              :                                                         fndIV++;
    5430              :                                                 }
    5431              :                                                 else
    5432              :                                                 {
    5433              :                                                         vrtOtherEdg = vrtOfEdg;
    5434              :                                                 }
    5435              :                                         }
    5436              : 
    5437              :                                         vector3 posOtherVrt = aaPos[vrtOtherEdg];
    5438              : 
    5439            0 :                                         UG_LOG("BOUNDARY EDGE VERTIZES " << posOldVrt << ", " << posOtherVrt << std::endl);
    5440              : 
    5441              :                                         vector3 fromIterV2Other;
    5442              : 
    5443              :                                         VecSubtract(fromIterV2Other, posOtherVrt, posOldVrt);
    5444              : 
    5445              :                                         vector3 nV;
    5446              : 
    5447            0 :                                         VecNormalize(nV, fromIterV2Other);
    5448              : 
    5449            0 :                                         bndEdgeDirection.push_back(nV);
    5450              :                                 }
    5451              : 
    5452              : 
    5453              :                                 constexpr bool useOldBndryOdering = false;
    5454              : 
    5455              :                                 if( useOldBndryOdering )
    5456              :                                 {
    5457              : 
    5458              : #if WORKAROUND_ARTE_SEGFAULT
    5459              : 
    5460              :                                         IndexType dbg_lim = vecVertFracTrip.size();
    5461              : 
    5462              :                                         int dbg_cnt = 0;
    5463              : #endif
    5464              : 
    5465              :                                         // TODO FIXME HHHHHHHHH hier die Sortierungsroutine einbauen, um die attachten faces sicher richtig zu zu ordnen!!!
    5466              : 
    5467              :                                         for( VvftIterator vvftAtBnd = vecVertFracTrip.begin();
    5468              :                                                         vvftAtBnd != vecVertFracTrip.end();
    5469              :                                                         vvftAtBnd++
    5470              :                                         )
    5471              :                                         {
    5472              : #if WORKAROUND_ARTE_SEGFAULT
    5473              : 
    5474              :                                                 if( dbg_lim == dbg_cnt )
    5475              :                                                 {
    5476              :                                                         UG_LOG("DARF NICHT SEIN" << std::endl);
    5477              :                                                         break;
    5478              :                                                 }
    5479              : 
    5480              :                                                 dbg_cnt++;
    5481              : #endif
    5482              : 
    5483              :                                                 // Ziel: den parallelen Anteil der Normalen auf die jeweilige Randkante projizieren
    5484              : 
    5485              :                                                 vector3 nrmEdg = vvftAtBnd->getNormal();
    5486              : 
    5487              :                                                 Edge * edgeOfFrac = vvftAtBnd->getEdge();
    5488              : 
    5489              :                                                 // figure out the adjoint boundary edge into the same direction
    5490              : 
    5491              :                                                 // the normal in both directions have to be compared with the vectors in direction of boundary edges
    5492              :                                                 for( auto bED : bndEdgeDirection )
    5493              :                                                 {
    5494              :                                                         // check orientation of boundary edges wrt the normals
    5495              : 
    5496              :                                                         number cosinus = VecDot( nrmEdg, bED );
    5497              : 
    5498              :                                                         UG_LOG("BOUNDARY COSINUS between " << nrmEdg << " and " << bED << " -> " << cosinus << std::endl);
    5499              : 
    5500              :                                                         if( cosinus > 0 )
    5501              :                                                         {
    5502              :                                                                 // gleiche Seite vermutet
    5503              : 
    5504              :                                                                 // muessen wissen, wie lange das gestreckt werden soll
    5505              : 
    5506              :                                                                 vector3 alongEdgV;
    5507              : 
    5508              :                                                                 auto subsIndEdgOF = sh.get_subset_index(edgeOfFrac);
    5509              : 
    5510              :                                                                 number width = fracInfosBySubset.at(subsIndEdgOF).width;
    5511              : 
    5512              :                                                                 number scal = width / 2. / cosinus;
    5513              : 
    5514              :                                                                 VecScale( alongEdgV, bED, scal );
    5515              : 
    5516              :                                                                 vector3 posNewVrtOnBnd;
    5517              : 
    5518              :                                                                 VecAdd(posNewVrtOnBnd, posOldVrt, alongEdgV );
    5519              : 
    5520              :                                                                 UG_LOG("neuer Vertex Edge " << posNewVrtOnBnd << std::endl );
    5521              : 
    5522              :                                                                 Vertex * newShiftEdgVrtx = *grid.create<RegularVertex>();
    5523              :                                                                 aaPos[newShiftEdgVrtx] = posNewVrtOnBnd;
    5524              : 
    5525              :                                                                 sh.assign_subset(newShiftEdgVrtx, subsIndEdgOF );
    5526              : 
    5527              :                                                                 std::vector<Edge * > attEdg;
    5528              :                                                                 std::vector<Face * > attFac;
    5529              : 
    5530              :                                                                 attEdg.push_back(edgeOfFrac);
    5531              : 
    5532              :                                                                 Face * facFrac = vvftAtBnd->getFace();
    5533              : 
    5534              :                                                                 attFac.push_back( facFrac );
    5535              : 
    5536              :                                                                 // we store the boundary edge direction for boundary verzizes rather than the normal, in contrast to inner vertizes, where we store the averaged normal
    5537              :                                                                 ExpandVertexMultiplett vrtMtpl( attEdg, attFac, bED );
    5538              : 
    5539              :                                                                 aaVrtExpMP[ *iterV ].push_back( vrtMtpl );
    5540              : 
    5541              : #if 0
    5542              :                                                                 // the attached faces need to know that they need a new vertex to be shifted
    5543              :                                                                 for( std::vector<Face *>::iterator iterFac = grid.associated_faces_begin(*iterV); iterFac != grid.associated_faces_end(*iterV); iterFac++ )
    5544              :                                                                 {
    5545              :                                                                         bool isFromFrac = false;
    5546              : 
    5547              :                                                                         for( auto const & facFrac : attFac )
    5548              :                                                                         {
    5549              :                                                                                 if( *iterFac == facFrac )
    5550              :                                                                                 {
    5551              :                                                                                         isFromFrac = true;
    5552              :                                                                                 }
    5553              :                                                                         }
    5554              : 
    5555              :                                                                         bool atRightSide = false;
    5556              : 
    5557              :                                                                         if( isFromFrac )
    5558              :                                                                                 atRightSide = true;
    5559              : 
    5560              :                                                                         if( !isFromFrac )
    5561              :                                                                         {
    5562              : 
    5563              :                                                                                 // check if on same side of edge where the normal points to: compute cosinus between vector of face center
    5564              :                                                                                 //  perpendicular to the edge
    5565              :                                                                                 // TODO FIXME
    5566              : 
    5567              :                                                                                 vector3 facCenter = CalculateCenter( *iterFac, aaPos );
    5568              : 
    5569              :                                                                                 vector3 perpendicu;
    5570              : 
    5571              :                                                                                 DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]);
    5572              : 
    5573              :                                                                                 vector3 tmpN;
    5574              : 
    5575              :                                                                                 VecSubtract(tmpN, facCenter, perpendicu );
    5576              : 
    5577              :                                                                                 VecNormalize(tmpN, tmpN);
    5578              : 
    5579              :                                                                                 UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl);
    5580              : 
    5581              :                                                                                 number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg );
    5582              : 
    5583              :                                                                                 UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl);
    5584              : 
    5585              :                                                                                 if( cosBetwFracEdgAndDirection2Face > 0 )
    5586              :                                                                                 {
    5587              :                                                                                         UG_LOG("assuming boundary face to be on richt side" << std::endl);
    5588              : 
    5589              :                                                                                         atRightSide = true;
    5590              : 
    5591              : #if ESTABLISH_DEBUG_SUDOS
    5592              :                                                                                                         Vertex * otherFacCent = *grid.create<RegularVertex>();
    5593              :                                                                                                         aaPos[otherFacCent] = facCenter;
    5594              :                                                                                                         sh.assign_subset(otherFacCent, 5 );
    5595              : 
    5596              :                                                                                                         Vertex * pp = *grid.create<RegularVertex>();
    5597              :                                                                                                         aaPos[pp] = perpendicu;
    5598              :                                                                                                         sh.assign_subset(pp, 6 );
    5599              : 
    5600              :                                                                                                         sh.assign_subset(*iterFac,7);
    5601              : #endif
    5602              : 
    5603              : 
    5604              :                                                                                 }
    5605              :                                                                                 else
    5606              :                                                                                 {
    5607              :                                                                                         UG_LOG("assuming boundary face to be on wrong side" << std::endl);
    5608              :                                                                                 }
    5609              : 
    5610              :                                                                         }
    5611              : 
    5612              :                                                                         if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein
    5613              :                                                                         {
    5614              : 
    5615              : 
    5616              :                                                                                 vector<Vertex*>& newVrts4Fac = aaVrtVecFace[ * iterFac ];
    5617              : 
    5618              :                                                                                 IndexType vrtxFnd = 0;
    5619              : 
    5620              :                                                                                 for(size_t indVrt = 0; indVrt < (*iterFac)->num_vertices();  indVrt++ )
    5621              :                                                                                 {
    5622              :                                                                                         Vertex* facVrt = (*iterFac)->vertex(indVrt);
    5623              : 
    5624              :                                                                                         if(  facVrt == *iterV )
    5625              :                                                                                         {
    5626              :                                                                                                 newVrts4Fac[ indVrt ] = newShiftEdgVrtx;
    5627              :                                                                                                 vrtxFnd++;
    5628              :                                                                                         }
    5629              :                                                                                 }
    5630              : 
    5631              : 
    5632              : 
    5633              :                                                                                 if( vrtxFnd <= 0 )
    5634              :                                                                                 {
    5635              :                                                                                         UG_THROW("vertex not found bnd!" << std::endl);
    5636              :                                                                                 }
    5637              :                                                                                 else if( vrtxFnd > 1 )
    5638              :                                                                                 {
    5639              :                                                                                         UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl );
    5640              :                                                                                 }
    5641              :                                                                                 else if ( vrtxFnd == 1 )
    5642              :                                                                                 {
    5643              :         //                                                                                                              UG_LOG("vertex found abgeschlossen" << std::endl);
    5644              :                                                                                 }
    5645              :                                                                                 else
    5646              :                                                                                 {
    5647              :                                                                                         UG_THROW("vertex finden bnd komisch " << std::endl);
    5648              :                                                                                 }
    5649              :                                                                         }
    5650              : 
    5651              :                                                                 }
    5652              : #else
    5653              : 
    5654              :                                                                 // TODO FIXME HHHHHHHHH hier die Sortierungsroutine einbauen, um die attachten faces sicher richtig zu zu ordnen!!!
    5655              : 
    5656              :                                                                 for( auto const & ifac : assoFaces )
    5657              :                                                                 {
    5658              :                                                                         bool isFromFrac = false;
    5659              : 
    5660              :                                                                         for( auto const & facFrac : attFac )
    5661              :                                                                         {
    5662              :                                                                                 if( ifac == facFrac )
    5663              :                                                                                 {
    5664              :                                                                                         isFromFrac = true;
    5665              :                                                                                 }
    5666              :                                                                         }
    5667              : 
    5668              :                                                                         bool atRightSide = false;
    5669              : 
    5670              :                                                                         if( isFromFrac )
    5671              :                                                                                 atRightSide = true;
    5672              : 
    5673              :                                                                         if( !isFromFrac )
    5674              :                                                                         {
    5675              : 
    5676              :                                                                                 // check if on same side of edge where the normal points to: compute cosinus between vector of face center
    5677              :                                                                                 //  perpendicular to the edge
    5678              :                                                                                 // TODO FIXME
    5679              : 
    5680              :                                                                                 vector3 facCenter = CalculateCenter( ifac, aaPos );
    5681              : 
    5682              :                                                                                 vector3 perpendicu;
    5683              : 
    5684              :                                                                                 DropAPerpendicular(perpendicu, facCenter, aaPos[edgeOfFrac->vertex(0)], aaPos[edgeOfFrac->vertex(1)]);
    5685              : 
    5686              :                                                                                 vector3 tmpN;
    5687              : 
    5688              :                                                                                 VecSubtract(tmpN, facCenter, perpendicu );
    5689              : 
    5690              :                                                                                 VecNormalize(tmpN, tmpN);
    5691              : 
    5692              :                                                                                 UG_LOG("Normale Boundary zum Face ist " << tmpN << std::endl);
    5693              : 
    5694              :                                                                                 number cosBetwFracEdgAndDirection2Face = VecDot(tmpN, nrmEdg );
    5695              : 
    5696              :                                                                                 UG_LOG("Cosinus Boundary zur Normalen ist " << cosBetwFracEdgAndDirection2Face << std::endl);
    5697              : 
    5698              :                                                                                 if( cosBetwFracEdgAndDirection2Face > 0 )
    5699              :                                                                                 {
    5700              :                                                                                         UG_LOG("assuming boundary face to be on richt side" << std::endl);
    5701              : 
    5702              :                                                                                         atRightSide = true;
    5703              : 
    5704              : #if ESTABLISH_DEBUG_SUDOS
    5705              : 
    5706              :         //                                                                              IndexType suNu = sh.num_subsets();
    5707              : 
    5708              :                                                                                         Vertex * otherFacCent = *grid.create<RegularVertex>();
    5709              :                                                                                         aaPos[otherFacCent] = facCenter;
    5710              :                                                                                         sh.assign_subset(otherFacCent, sh.num_subsets() );
    5711              :                                                                                         // sh.assign_subset(otherFacCent, 5 );
    5712              : 
    5713              :                                                                                         Vertex * pp = *grid.create<RegularVertex>();
    5714              :                                                                                         aaPos[pp] = perpendicu;
    5715              :         //                                                                              sh.assign_subset(pp, 6 );
    5716              :                                                                                         sh.assign_subset(pp, sh.num_subsets() );
    5717              : 
    5718              :         //                                                                              sh.assign_subset(*iterFac,7);
    5719              :                                                                                         sh.assign_subset(*iterFac, sh.num_subsets() );
    5720              : #endif
    5721              : 
    5722              : 
    5723              :                                                                                 }
    5724              :                                                                                 else
    5725              :                                                                                 {
    5726              :                                                                                         UG_LOG("assuming boundary face to be on wrong side" << std::endl);
    5727              :                                                                                 }
    5728              : 
    5729              :                                                                         }
    5730              : 
    5731              :                                                                         if( atRightSide ) // atRightSide ) NOCH FALSCH TODO FIXME muss nur auf richtiger Seite sein
    5732              :                                                                         {
    5733              : 
    5734              : 
    5735              :                                                                                 vector<Vertex*>& newVrts4Fac = aaVrtVecFace[ ifac ];
    5736              : 
    5737              :                                                                                 IndexType vrtxFnd = 0;
    5738              : 
    5739              :                                                                                 for(size_t indVrt = 0; indVrt < (ifac)->num_vertices();  indVrt++ )
    5740              :                                                                                 {
    5741              :                                                                                         Vertex* facVrt = (ifac)->vertex(indVrt);
    5742              : 
    5743              :                                                                                         if(  facVrt == *iterV )
    5744              :                                                                                         {
    5745              :                                                                                                 newVrts4Fac[ indVrt ] = newShiftEdgVrtx;
    5746              :                                                                                                 vrtxFnd++;
    5747              :                                                                                         }
    5748              :                                                                                 }
    5749              : 
    5750              : 
    5751              : 
    5752              :                                                                                 if( vrtxFnd <= 0 )
    5753              :                                                                                 {
    5754              :                                                                                         UG_THROW("vertex not found bnd!" << std::endl);
    5755              :                                                                                 }
    5756              :                                                                                 else if( vrtxFnd > 1 )
    5757              :                                                                                 {
    5758              :                                                                                         UG_THROW("vertex zu oft gefunden bnd " << vrtxFnd << std::endl );
    5759              :                                                                                 }
    5760              :                                                                                 else if ( vrtxFnd == 1 )
    5761              :                                                                                 {
    5762              :         //                                                                                                              UG_LOG("vertex found abgeschlossen" << std::endl);
    5763              :                                                                                 }
    5764              :                                                                                 else
    5765              :                                                                                 {
    5766              :                                                                                         UG_THROW("vertex finden bnd komisch " << std::endl);
    5767              :                                                                                 }
    5768              :                                                                         }
    5769              :                                                                 }
    5770              : 
    5771              : #endif
    5772              :                                                         }
    5773              :                                                 }
    5774              :                                         }
    5775              :                                 }
    5776              :                                 else // sicher ordnungsbasiertes Arbeiten
    5777              :                                 {
    5778              : 
    5779            0 :                                         IndexType numbSegments = segments.size();
    5780              : 
    5781            0 :                                         if( numbSegments != 2 )
    5782            0 :                                                 UG_THROW("only two segments possible at boundary as long as only one ending fracture " << std::endl;)
    5783              : 
    5784              :                                         bool beforeFrac = true;
    5785              : 
    5786              :                                         IndexType segInd = 0;
    5787              : 
    5788              :                                         // TODO FIXME ausfuellen
    5789            0 :                                         for( VecVertexOfFaceInfo const & segPart : segments )
    5790              :                                         {
    5791              : 
    5792            0 :                                                 IndexType numbTriangs = segPart.size();
    5793              : 
    5794              :                                                 VertexOfFaceInfo const & vFISBegin = segPart[0];
    5795            0 :                                                 VertexOfFaceInfo const & vFISEnd = segPart[numbTriangs-1];
    5796              : 
    5797              :                                                 Face * fracFace = vFISEnd.getFace();
    5798              : 
    5799              :                                                 std::pair<Edge*, Edge* >  edgesBegin = vFISBegin.getEdge();
    5800              :                                                 std::pair<Edge*, Edge* >  edgesEnd = vFISEnd.getEdge();
    5801              : 
    5802              :                                                 std::pair<vector3, vector3> normalBegin = vFISBegin.getNormal();
    5803              :                                                 std::pair<vector3, vector3> normalEnd = vFISEnd.getNormal();
    5804              : 
    5805              :                                                 Edge* edgeBnd = edgesBegin.first;
    5806              :                                                 Edge* edgeFrac = edgesEnd.second;
    5807              : 
    5808              :                                                 vector3 normalBnd = normalBegin.first;
    5809              :                                                 vector3 normalFrac = normalEnd.second;
    5810              : 
    5811            0 :                                                 if( ! beforeFrac )
    5812              :                                                 {
    5813              :                                                         fracFace = vFISBegin.getFace();
    5814              : 
    5815              :                                                         edgeBnd = edgesEnd.second;
    5816              :                                                         edgeFrac = edgesBegin.first;
    5817              : 
    5818              :                                                         normalBnd = normalEnd.second;
    5819              :                                                         normalFrac = normalBegin.first;
    5820              :                                                 }
    5821              : 
    5822            0 :                                                 if( edgeBnd != adjBndEdgs[segInd] )
    5823            0 :                                                         UG_THROW("Boundary edge does not fit " << segInd << std::endl);
    5824              : 
    5825              : //                                              auto const & vft = vecVertFracTrip[segInd];
    5826              : //
    5827              : //                                              if( normalFrac != vft.getNormal())
    5828              : //                                                      UG_THROW("Normale nicht gegeben " << segInd << std::endl);
    5829              : //
    5830              : //                                              if( edgeFrac != vft.getEdge() )
    5831              : //                                                      UG_THROW("Kante nicht bekannt " << segInd << std::endl);
    5832              : //
    5833              : //                                              if( fracFace != vft.getFace() )
    5834              : //                                                      UG_THROW("Gesicht nicht bekannt " << segInd << std::endl);
    5835              : 
    5836              :                                                 // check if belonging to one vertFracTrip of bnd vrtx
    5837              : 
    5838              :                                                 IndexType fndNormal = 0;
    5839              :                                                 IndexType fndEdge = 0;
    5840              :                                                 IndexType fndFace = 0;
    5841              : 
    5842            0 :                                                 for( auto const & vft : vecVertFracTrip )
    5843              :                                                 {
    5844            0 :                                                         if( vft.getNormal() == normalFrac )
    5845            0 :                                                                 fndNormal++;
    5846              : 
    5847            0 :                                                         if( vft.getEdge() == edgeFrac )
    5848            0 :                                                                 fndEdge++;
    5849              : 
    5850            0 :                                                         if( vft.getFace() == fracFace )
    5851            0 :                                                                 fndFace++;
    5852              :                                                 }
    5853              : 
    5854            0 :                                                 if( fndNormal != 1 || fndEdge != 2 || fndFace != 1 )
    5855            0 :                                                         UG_THROW("Findungen komisch " << fndNormal << " " << fndEdge << " " << fndFace << std::endl);
    5856              : 
    5857            0 :                                                 auto subsIndFrac = sh.get_subset_index(edgeFrac);
    5858              : 
    5859              :                                                 // neue Punkte erzeugen
    5860              : 
    5861              :                                                 auto & bED = bndEdgeDirection[segInd];
    5862              : 
    5863              :                                                 // DEBUG ASSERT TEST static_assert( std::is_same< decltype( bED), vector3 & >::value );
    5864              : 
    5865              :                                                 vector3 & nrmEdg = normalFrac; //normalBnd;
    5866              : 
    5867              :                                                 Edge * edgeOfFrac = edgeFrac;
    5868              : 
    5869              :                                                 number cosinus = VecDot( nrmEdg, bED );
    5870              : 
    5871            0 :                                                 UG_LOG("BOUNDARY COSINUS between " << nrmEdg << " and " << bED << " -> " << cosinus << std::endl);
    5872              : 
    5873            0 :                                                 if( cosinus < 0 )
    5874              :                                                 {
    5875              :                                                         // andere Seite vermutet
    5876              : 
    5877            0 :                                                         UG_THROW("check if really on same side " << std::endl);
    5878              :                                                 }
    5879              : 
    5880              :                                                 // gleiche Seite muss es sein
    5881              : 
    5882              :                                                 // muessen wissen, wie lange das gestreckt werden soll
    5883              : 
    5884              :                                                 vector3 alongEdgV;
    5885              : 
    5886              :                                                 auto subsIndEdgOF = sh.get_subset_index(edgeOfFrac);
    5887              : 
    5888            0 :                                                 number width = fracInfosBySubset.at(subsIndEdgOF).width;
    5889              : 
    5890            0 :                                                 number scal = width / 2. / cosinus;
    5891              : 
    5892              :                                                 VecScale( alongEdgV, bED, scal );
    5893              : 
    5894              :                                                 vector3 posNewVrtOnBnd;
    5895              : 
    5896              :                                                 VecAdd(posNewVrtOnBnd, posOldVrt, alongEdgV );
    5897              : 
    5898            0 :                                                 UG_LOG("neuer Vertex Edge " << posNewVrtOnBnd << std::endl );
    5899              : 
    5900            0 :                                                 Vertex * newShiftEdgVrtx = *grid.create<RegularVertex>();
    5901              :                                                 aaPos[newShiftEdgVrtx] = posNewVrtOnBnd;
    5902              : 
    5903            0 :                                                 sh.assign_subset(newShiftEdgVrtx, subsIndEdgOF );
    5904              : 
    5905            0 :                                                 teachAssoFacesNewVrtx(  segPart, aaVrtVecFace, *iterV, newShiftEdgVrtx );
    5906              : 
    5907            0 :                                                 segInd++;
    5908              : 
    5909            0 :                                                 beforeFrac = ! beforeFrac; // more complicated eventual if more than one ending frac, but no topic so far
    5910              :                                         }
    5911              : 
    5912              :                                 }
    5913              : 
    5914              : //                              return true;
    5915              : 
    5916            0 :                         }
    5917              :                         else // fractures are crossing at boundary even
    5918              :                         {
    5919            0 :                                 UG_THROW("not implemented so far: multiple fractures crossing at boundary " << std::endl);
    5920              :                         }
    5921              : 
    5922              : 
    5923              :                         UG_LOG("END THIS BOUNDARY VERTEX" << std::endl);
    5924              :                 }
    5925              : 
    5926              :                 dbg_vertizesPassiert++;
    5927              : 
    5928              :         }
    5929              : 
    5930              : 
    5931              : //              // neue Vertizes in der Entfernung der Klüfte von den Klüften weg erzeugen,
    5932              : //              // basierend auf den Normalen multipliziert mit der halben Kluftdicke
    5933              : //              //für eine Kluft erstmal nur
    5934              : //              // die neuen Kanten und Faces erzeugen, die alten falschen Kanten löschen und ebenso die alten Faces
    5935              : //              // später auf mehr Klüfte ausdehnen, mit Problemstelle Kreuzung, aber erst, wenn eine Kluft funktioniert
    5936              : //
    5937              : 
    5938              : //      return true;
    5939              : 
    5940              :         // jetzt Seb Sachen beinahe unverändert
    5941              : 
    5942              :         ////////////////////////////////
    5943              :         //      create new elements
    5944              : 
    5945              :         //      first we create new edges from selected ones which are connected to
    5946              :         //      inner vertices. This allows to preserve old subsets.
    5947              :         //      Since we have to make sure that we use the right vertices,
    5948              :         //      we have to iterate over the selected faces and perform all actions on the edges
    5949              :         //      of those faces.
    5950            0 :         for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf)
    5951              :         {
    5952              :                 Face* sf = *iter_sf;
    5953              :                 //      check for each edge whether it has to be copied.
    5954            0 :                 for(size_t i_edge = 0; i_edge < sf->num_edges(); ++i_edge)
    5955              :                 {
    5956            0 :                         Edge* e = grid.get_edge(sf, i_edge);
    5957              : 
    5958            0 :                         if(sel.is_selected(e))
    5959              :                         {
    5960              :                                 //      check the associated vertices through the volumes aaVrtVecVol attachment.
    5961              :                                 //      If at least one has an associated new vertex and if no edge between the
    5962              :                                 //      new vertices already exists, we'll create the new edge.
    5963              :                                 size_t ind0 = i_edge;
    5964            0 :                                 size_t ind1 = (i_edge + 1) % sf->num_edges();
    5965              : 
    5966            0 :                                 Vertex* nv0 = (aaVrtVecFace[sf])[ind0];
    5967            0 :                                 Vertex* nv1 = (aaVrtVecFace[sf])[ind1];
    5968              : 
    5969            0 :                                 if(nv0 || nv1)
    5970              :                                 {
    5971              :                                         //      if one vertex has no associated new one, then we use the vertex itself
    5972            0 :                                         if(!nv0)
    5973            0 :                                                 nv0 = sf->vertex(ind0);
    5974            0 :                                         if(!nv1)
    5975            0 :                                                 nv1 = sf->vertex(ind1);
    5976              : 
    5977              :                                         //      create the new edge if it not already exists.
    5978            0 :                                         if(!grid.get_edge(nv0, nv1))
    5979            0 :                                                 grid.create_by_cloning(e, EdgeDescriptor(nv0, nv1), e);
    5980              :                                 }
    5981              :                         }
    5982              :                 }
    5983              :         }
    5984              : 
    5985              : 
    5986              :         std::vector<Face * > newFaces;
    5987              :         std::vector<int> subsOfNewFaces;
    5988              : 
    5989              :         //      iterate over all surrounding faces and create new vertices.
    5990              :         //      Since faces are replaced on the fly, we have to take care with the iterator.
    5991            0 :         for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end();)
    5992              :         {
    5993              :                 Face* sf = *iter_sf;
    5994              :                 ++iter_sf;
    5995              : 
    5996            0 :                 std::vector<Vertex*> newVrts = aaVrtVecFace[sf];
    5997              : 
    5998              :                 //      all new vertices have been assigned to newVrts.
    5999              :                 //      Note that if newVrts[i] == NULL, then we have to take the
    6000              :                 //      old vertex sf->vertex(i).
    6001              :                 //      now expand the fracture edges of sf to faces.
    6002            0 :                 for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt)
    6003              :                 {
    6004              :                         size_t iv1 = i_vrt;
    6005            0 :                         size_t iv2 = (i_vrt + 1) % sf->num_vertices();
    6006              : 
    6007            0 :                         Edge* tEdge = grid.get_edge(sf->vertex(iv1), sf->vertex(iv2));
    6008              : 
    6009            0 :                         if(tEdge)
    6010              :                         {
    6011            0 :                                 if( aaMarkEdgeB[tEdge] )
    6012              :                                 {
    6013            0 :                                         Face* expFace = NULL;
    6014            0 :                                         if(newVrts[iv1] && newVrts[iv2])
    6015              :                                         {
    6016              :                                                 //      create a new quadrilateral
    6017            0 :                                                 expFace = *grid.create<Quadrilateral>(
    6018            0 :                                                                                 QuadrilateralDescriptor(sf->vertex(iv1), sf->vertex(iv2),
    6019              :                                                                                                                                 newVrts[iv2], newVrts[iv1]));
    6020              :                                         }
    6021            0 :                                         else if(newVrts[iv1])
    6022              :                                         {
    6023              :                                                         //      create a new triangle
    6024            0 :                                                 expFace = *grid.create<Triangle>(
    6025            0 :                                                                                 TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv1]));
    6026              :                                         }
    6027            0 :                                         else if(newVrts[iv2])
    6028              :                                         {
    6029              :                                                 //      create a new triangle
    6030            0 :                                                 expFace = *grid.create<Triangle>(
    6031            0 :                                                                                 TriangleDescriptor(sf->vertex(iv1), sf->vertex(iv2), newVrts[iv2]));
    6032              :                                         }
    6033              :                                         else
    6034              :                                         {
    6035              : 
    6036              : ////                                            sh.assign_subset(*iter_sf,10);
    6037              : ////                                            sh.assign_subset(tEdge,11);
    6038              : //
    6039              : //                                              return true;
    6040              : //                                              //      this code-block should never be entered. If it is entered then
    6041              : //                                              //      we selected the wrong faces. This is would be a BUG!!!
    6042              : //                                              //      remove the temporary attachments and throw an error
    6043              : //
    6044              : //                                              //      remove the temporary attachments
    6045              : //#if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE
    6046              : //                                              grid.detach_from_vertices(aAdjMarker);
    6047              : //                                              grid.detach_from_edges(aAdjMarker);
    6048              : //#endif
    6049              : //                                              grid.detach_from_vertices(aAdjMarkerVFP);
    6050              : //                                              grid.detach_from_edges(aAdjMarkerB);
    6051              : //
    6052              : //                                              grid.detach_from_vertices( aAdjInfoAVVFT );
    6053              : //                                              grid.detach_from_faces(attVrtVec);
    6054              : //
    6055              : //                                              grid.detach_from_vertices( aAdjInfoEdges );
    6056              : //                                              grid.detach_from_vertices( aAdjInfoFaces );
    6057              : //
    6058              : //
    6059              : //                                              // TODO FIXME auch die weiteren Marker und INfos, alle Attachments, detachen!!!!
    6060              : //
    6061              : //                                              throw(UGError("Implementation error in ExpandFractures2d Arte."));
    6062              :                                         }
    6063              : 
    6064              :                                         // TODO FIXME selektion closen irgendwie, damit auch alle Randkanten zum subset gehoeren!!!
    6065              : 
    6066            0 :                                         if( expFace )
    6067              :                                         {
    6068            0 :                                                 sh.assign_subset(expFace, fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex);
    6069              : 
    6070            0 :                                                 int subs = fracInfosBySubset.at(sh.get_subset_index(tEdge)).newSubsetIndex;
    6071              : 
    6072            0 :                                                 subsOfNewFaces.push_back( subs );
    6073              : 
    6074            0 :                                                 newFaces.push_back( expFace );
    6075              :                                         }
    6076              :                                 }
    6077              :                         }
    6078              :                 }
    6079              : 
    6080              : 
    6081              : 
    6082              : 
    6083              :                 //      now set up a new face descriptor and replace the face.
    6084            0 :                 if(fd.num_vertices() != sf->num_vertices())
    6085            0 :                         fd.set_num_vertices(sf->num_vertices());
    6086              : 
    6087            0 :                 for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt)
    6088              :                 {
    6089            0 :                         if(newVrts[i_vrt])
    6090            0 :                                 fd.set_vertex(i_vrt, newVrts[i_vrt]);
    6091              :                         else
    6092            0 :                                 fd.set_vertex(i_vrt, sf->vertex(i_vrt));
    6093              :                 }
    6094              : 
    6095            0 :                 grid.create_by_cloning(sf, fd, sf);
    6096            0 :                 grid.erase(sf);
    6097            0 :         }
    6098              : 
    6099              :         //      we have to clean up unused edges.
    6100              :         //      All selected edges with mark 0 have to be deleted.
    6101            0 :         for(EdgeIterator iter = sel.edges_begin(); iter != sel.edges_end();)
    6102              :         {
    6103              :                 //      be careful with the iterator
    6104              :                 Edge* e = *iter;
    6105              :                 ++iter;
    6106              : 
    6107            0 :                 if(!aaMarkEdgeB[e])
    6108            0 :                         grid.erase(e);
    6109              :         }
    6110              : 
    6111            0 :         if( subsOfNewFaces.size() != newFaces.size() )
    6112              :         {
    6113            0 :                 UG_THROW("andere zahl neue faces als subdoms " << std::endl);
    6114              :         }
    6115              : 
    6116              :         IndexType nfn = 0;
    6117              : 
    6118            0 :         for( auto const & nf : newFaces )
    6119              :         {
    6120            0 :                 for(size_t i_edge = 0; i_edge < nf->num_edges(); ++i_edge)
    6121              :                 {
    6122            0 :                         Edge* edg = grid.get_edge(nf, i_edge);
    6123              : 
    6124            0 :                         sh.assign_subset( edg, subsOfNewFaces[nfn] );
    6125              : 
    6126              :                 }
    6127              : 
    6128            0 :                 for( size_t iVrt = 0; iVrt < nf->num_vertices(); iVrt++ )
    6129              :                 {
    6130            0 :                         Vertex * vrt = nf->vertex(iVrt);
    6131              : 
    6132            0 :                         sh.assign_subset( vrt, subsOfNewFaces[nfn] );
    6133              :                 }
    6134              : 
    6135            0 :                 nfn++;
    6136              :         }
    6137              : 
    6138              :         // sollen die Boundary Edges zur boundary gehören, oder zur Kluft?
    6139              :         // wie ist es mit den Knoten, sind die alle richtig zugewiesen bezüglich subset?
    6140              : 
    6141              :         // jetzt muss noch der Diamant erzeugt werden
    6142              :         // Ziel: KluftInnen erzeugen
    6143              : 
    6144              : 
    6145              :         //      remove the temporary attachments
    6146              : 
    6147              : #if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE
    6148              :         grid.detach_from_vertices(aAdjMarker);
    6149              :         grid.detach_from_edges(aAdjMarker);
    6150              : #endif
    6151              : //      grid.detach_from_vertices(aAdjMarkerVFP);
    6152              : //      grid.detach_from_edges(aAdjMarkerB);
    6153              : //
    6154              : //      grid.detach_from_vertices( aAdjInfoAVVFT );
    6155              : //      grid.detach_from_faces(attVrtVec);
    6156              : //
    6157              : //      grid.detach_from_vertices( aAdjInfoEdges );
    6158              : //      grid.detach_from_vertices(aAdjInfoFaces );
    6159              : 
    6160              : 
    6161              :         grid.detach_from_vertices(aAdjMarkerVFP );
    6162              :         grid.detach_from_edges(aAdjMarkerB);
    6163              :         grid.detach_from_vertices( aAdjInfoAVVFT  );
    6164              :         grid.detach_from_vertices( aAdjInfoEdges );
    6165              :         grid.detach_from_vertices( aAdjInfoFaces );
    6166              :         grid.detach_from_faces(attVrtVec);
    6167              :         grid.detach_from_vertices( aAdjInfoVVEVM );
    6168              : 
    6169              : //      sel.clear();
    6170              : 
    6171              : //      return true;
    6172              : 
    6173              :         // only Keile, basic system
    6174            0 :         if( ! establishDiamonds )
    6175              :                 return true;
    6176              : 
    6177              :         //  alles detachen, was noch attached ist, da ist einiges hinzu gekommen!
    6178              : 
    6179              : 
    6180              :         // Keilstruktur entfernen und durch den gewünschten Diamanten ersetzen
    6181              : 
    6182              :         // new vertices which divide the fracture edges
    6183              : 
    6184              : //      AVertex aAdjVert; // used to know if an edge is frac edge and in the old faces
    6185              : //      grid.attach_to_edges_dv( aAdjVert, nullptr );
    6186              : //      grid.attach_to_faces_dv( aAdjVert, nullptr );
    6187              : //      Grid::EdgeAttachmentAccessor<AVertex> aaEdgeVert( grid, aAdjVert );
    6188              : //      Grid::FaceAttachmentAccessor<AVertex> aaFaceVert( grid, aAdjVert );
    6189              : 
    6190            0 :         for( auto const & cfi : vecCrossVrtInf )
    6191              :         {
    6192              : 
    6193              : //              IndexType nuCroFra =  cfi.getNumbCrossFracs();
    6194              :                 CrossVertInf::FracTyp fracTyp =  cfi.getFracTyp();
    6195              : 
    6196            0 :                 if( fracTyp == CrossVertInf::SingleFrac )
    6197            0 :                         continue;
    6198              : 
    6199            0 :                 Vertex * crossPt = cfi.getCrossVertex();
    6200              : 
    6201              :                 std::vector<Vertex * > shiftVrtcs = cfi.getVecShiftedVrts();
    6202              : 
    6203              : //              IndexType shiffsOrig = shiftVrtcs.size();
    6204              : //
    6205              : //              auto soc = shiffsOrig;
    6206              : 
    6207              :                 VecEdge origFracEdg; // = cfi.getVecOrigFracEdges();
    6208              : 
    6209              :                 // all edges associated to the crossing point
    6210              :                 VecEdge allAssoEdgCP;
    6211              : 
    6212            0 :                 for( std::vector<Edge *>::iterator iterEdg = grid.associated_edges_begin(crossPt); iterEdg != grid.associated_edges_end(crossPt); iterEdg++ )
    6213              :                 {
    6214              : 
    6215            0 :                         allAssoEdgCP.push_back(*iterEdg);
    6216              : 
    6217              :                         bool hasShiftedVrtx = false;
    6218              : 
    6219            0 :                         for( IndexType i = 0; i < 2; i++ )
    6220              :                         {
    6221            0 :                                 Vertex * side = (*iterEdg)->vertex(i);
    6222              : 
    6223            0 :                                 for( auto const & vrt : shiftVrtcs )
    6224              :                                 {
    6225            0 :                                         if( side == vrt )
    6226              :                                                 hasShiftedVrtx = true;
    6227              :                                 }
    6228              : 
    6229              :                         }
    6230              : 
    6231            0 :                         if( ! hasShiftedVrtx )
    6232            0 :                                 origFracEdg.push_back(*iterEdg);
    6233              :                 }
    6234              : 
    6235              : 
    6236              : //              UG_LOG("Shift Vectors Orig " <<  soc << std::endl);
    6237              : 
    6238              : //              // aim: old cross vertex first, shift vertex second, new established vertex third
    6239              : //              using VrtxPair = std::pair<Vertex*, Vertex*>;
    6240              : //
    6241              : //              using DiamondVertexInfo = VertexFractureTriple<Edge*, Face*, Vertex *>;
    6242              : //
    6243              : //              using VecDiamondVertexInfo = std::vector<DiamondVertexInfo>;
    6244              : //
    6245              : //              VecDiamondVertexInfo vecDiamVrtInfo;
    6246              : 
    6247              :                 // need to know the subsets of all faces!
    6248              :                 std::vector<IndexType> subdomList;
    6249              : 
    6250              :                 // all faces associated to the crossing point
    6251              :                 std::vector<Face *> assoFacCross;
    6252              : 
    6253            0 :                 for( std::vector<Face *>::iterator iterFac = grid.associated_faces_begin(crossPt); iterFac != grid.associated_faces_end(crossPt); iterFac++ )
    6254              :                 {
    6255            0 :                         assoFacCross.push_back(*iterFac);
    6256              : 
    6257              :                         bool sudoAlreadyThere = false;
    6258              : 
    6259            0 :                         IndexType sudo = sh.get_subset_index(*iterFac);
    6260              : 
    6261            0 :                         for( auto sl : subdomList )
    6262              :                         {
    6263            0 :                                 if( sl == sudo )
    6264              :                                         sudoAlreadyThere = true;
    6265              :                         }
    6266              : 
    6267            0 :                         if( !sudoAlreadyThere )
    6268            0 :                                 subdomList.push_back(sudo);
    6269              :                 }
    6270              : 
    6271            0 :                 if( subdomList.size() != 2 )
    6272            0 :                         UG_THROW("wieviele Subdoms um Kreuz herum?         " << subdomList.size() << std::endl );
    6273              : 
    6274              : 
    6275              :                 // finales Ziel: alle neuen faces entfernen, die an den Schnittknoten anhängen
    6276              :                 // ein Test noch
    6277              : 
    6278            0 :                 for( auto const & afc : assoFacCross )
    6279              :                 {
    6280              :                         // figure out respective original frac edge, need to know all edges and all vertices of this fracture
    6281              : 
    6282              :                         // was sind die Ecken und Kanten dieses Faces? welche Ecke davon ist die originale Fracture edge?
    6283              :                         // was ist die subdomain der originalen Fracture edge? klar das ist die subdomain des faces
    6284              : 
    6285            0 :                         auto subdom = sh.get_subset_index(afc);
    6286              : 
    6287              :                         bool subdomFnd = false;
    6288              : 
    6289            0 :                         for( auto const & sd : subdomList )
    6290              :                         {
    6291            0 :                                 if( subdom == sd )
    6292              :                                         subdomFnd = true;
    6293              :                         }
    6294              : 
    6295            0 :                         if( ! subdomFnd )
    6296            0 :                                 UG_THROW("SUBDOM NOT found" << std::endl);
    6297              : 
    6298              : //                              for( auto const &  )
    6299              : //                              AssociatedEdgeIterator associated_edges_begin(Face* face);///< DO NOT INVOKE! Subject to change.
    6300              : //                                              AssociatedEdgeIterator associated_edges_end(Face* face);///
    6301              : 
    6302              : //                              std::vector<Edge*> edgesThisFac;
    6303              : //
    6304              : //                              for( std::vector<Edge *>::iterator iterEdgF = grid.associated_edges_begin(afc);
    6305              : //                                              iterEdgF != grid.associated_edges_end(afc); iterEdgF++ )
    6306              : //                              {
    6307              : //                                      edgesThisFac.push_back(*iterEdgF);
    6308              : //                              }
    6309              : 
    6310              : 
    6311              :                 }
    6312              : 
    6313              : //              //                      for( auto const & edg : origFracEdg )
    6314              : //                                      for( auto edg : origFracEdg )
    6315              : //                                      {
    6316              : //
    6317              : //                                              // DEBUG ASSERT TEST static_assert( std::is_same< decltype( edg ), Edge * >::value  );
    6318              : //              //                              // DEBUG ASSERT TEST static_assert( std::is_same< const_cast<Edge*>(decltype( edg )), Edge * >::value  );
    6319              : //
    6320              : //              //                              //Vertex* vrtSpliEd =
    6321              : //              //                              if( edg != nullptr )
    6322              : //              //                              SplitEdge<Vertex>( grid, static_cast<Edge*>(edg) );
    6323              : //              ////                            else
    6324              : //              ////                                    UG_LOG("Nullptr getroffen " << std::endl);
    6325              : //              //
    6326              : //              ////                            size_t numSubs = sh.num_subsets();
    6327              : //              ////
    6328              : //              ////                            sh.assign_subset(edg, numSubs );
    6329              : //              //
    6330              : //              //                              //SplitEdge
    6331              : //              //
    6332              : //              //                              return true;
    6333              : //
    6334              : //                                      }
    6335              : 
    6336              : 
    6337              : 
    6338              : 
    6339              :                 // different Vorgehensweisen for T End and X Cross
    6340              : 
    6341              : //              using ExpandCrossFracInfo = VertexFractureTriple< std::pair<Edge*, Edge*>, Face*, std::pair<Vertex*, Vertex*> >;
    6342              : //              // Vertex nullptr wo original fracture, und shift vertex, wo Keilecke, die weg soll
    6343              : //
    6344              : //              using VecExpandCrossFracInfo = std::vector<ExpandCrossFracInfo>;
    6345              : 
    6346              :                 Edge * avoidToDeleteEdge = nullptr;
    6347              : 
    6348              :                 VecExpandCrossFracInfo vecExpCrossFI;
    6349              : 
    6350              :                 //              if( nuCroFra == 3 )
    6351            0 :                 if( fracTyp == CrossVertInf::TEnd )
    6352              :                 {
    6353              : 
    6354            0 :                         std::vector<std::pair<Vertex*,bool>> shiftVertcsWithTI = cfi.getVecShiftedVrtsWithTypInfo();
    6355              : 
    6356              :                         // test if the vertex vector is the same as the vertex vector without info
    6357              : 
    6358            0 :                         if( shiftVertcsWithTI.size() != shiftVrtcs.size() )
    6359            0 :                                 UG_THROW("Unterschiedlich grosse shift vertices " << shiftVertcsWithTI.size() << " != " << shiftVrtcs.size()  << std::endl);
    6360              : 
    6361            0 :                         for( IndexType i = 0; i < shiftVertcsWithTI.size(); i++ )
    6362              :                         {
    6363            0 :                                 if( shiftVertcsWithTI[i].first != shiftVrtcs[i]  )
    6364            0 :                                         UG_THROW("komische Shift vertizes" << std::endl);
    6365              :                         }
    6366              : 
    6367              :                         // aim: sorting faces
    6368            0 :                         auto assoFacTEndCop = assoFacCross;
    6369              : 
    6370              :                         // figure out that shift vertex that is at the T End
    6371              : 
    6372              :                         // start at defined face or edge
    6373              :                         // start sorted faces at one of the faces which belong to the T End , i.e. that side where no fracture sorts
    6374              :                         // figure out the corresponding index
    6375              : 
    6376              :                         int indxFrcWithTE = -1;
    6377              :                         IndexType indxFnd = 0;
    6378              :                         IndexType startEdgeFnd = 0;
    6379              :                         IndexType endEdgFnd = 0;
    6380              : 
    6381              :                         IndexType cntr = 0;
    6382              : 
    6383              :                         // muss sofort festgelegt werden - Startecke und zweite Ecke des gewählten faces
    6384              :                         Edge * shiftVrtxAtFirstFacEdg = nullptr;
    6385              :                         Edge * fracVrtxAtFirstFacEdg = nullptr;
    6386              : 
    6387              :                         Vertex * shiftVrtxAtFreeEnd = nullptr;
    6388              : 
    6389            0 :                         for( auto const & aft : assoFacTEndCop )
    6390              :                         {
    6391            0 :                                 for( auto const & svwi : shiftVertcsWithTI )
    6392              :                                 {
    6393            0 :                                         if( svwi.second == true )
    6394              :                                         {
    6395              : 
    6396            0 :                                                 shiftVrtxAtFreeEnd = svwi.first;
    6397              : 
    6398              : //                                              if( FaceContains(aft, svwi.first ) )
    6399            0 :                                                 if( FaceContains(aft, shiftVrtxAtFreeEnd ) )
    6400              :                                                 {
    6401            0 :                                                         indxFrcWithTE = cntr;
    6402            0 :                                                         indxFnd++;
    6403              : 
    6404            0 :                                                         for( std::vector<Edge *>::iterator iterEdgF = grid.associated_edges_begin(aft);
    6405            0 :                                                                         iterEdgF != grid.associated_edges_end(aft); iterEdgF++ )
    6406              :                                                         {
    6407              : 
    6408              : //                                                              bool edgCntsShiVe = EdgeContains(*iterEdgF, svwi.first);
    6409            0 :                                                                 bool edgCntsShiVe = EdgeContains(*iterEdgF, shiftVrtxAtFreeEnd);
    6410            0 :                                                                 bool edgCntsCrsPt = EdgeContains(*iterEdgF,crossPt);
    6411              : 
    6412              : //                                                              if( EdgeContains(*iterEdgF, svwi.first) && EdgeContains(*iterEdgF,crossPt) )
    6413            0 :                                                                 if( edgCntsShiVe && edgCntsCrsPt )
    6414              :                                                                 {
    6415            0 :                                                                         shiftVrtxAtFirstFacEdg = *iterEdgF;
    6416            0 :                                                                         startEdgeFnd++;
    6417              :                                                                 }
    6418            0 :                                                                 else if( edgCntsCrsPt && ! edgCntsShiVe )
    6419              :                                                                 {
    6420            0 :                                                                         fracVrtxAtFirstFacEdg = *iterEdgF;
    6421            0 :                                                                         endEdgFnd++;
    6422              :                                                                 }
    6423              :                                                         }
    6424              : 
    6425              :                                                 }
    6426              :                                         }
    6427              :                                 }
    6428              : 
    6429            0 :                                 cntr++;
    6430              :                         }
    6431              : 
    6432              :                         // we hit twice, and finally take the second one, as we also want to count
    6433              : 
    6434            0 :                         if( indxFrcWithTE < 0 || indxFrcWithTE >=  assoFacTEndCop.size() )
    6435            0 :                                 UG_THROW("Start nicht gefunden, freies Ende verloren " << std::endl);
    6436              : 
    6437            0 :                         if( indxFnd != 2 || startEdgeFnd != 2 || endEdgFnd != 2 )
    6438            0 :                                 UG_THROW("Index Free point or edge not found correct number " << indxFnd << " " << startEdgeFnd << " " << endEdgFnd << std::endl);
    6439              : 
    6440            0 :                         Edge * firstEdgeFac = shiftVrtxAtFirstFacEdg;
    6441            0 :                         Edge * secondEdgeFac = fracVrtxAtFirstFacEdg;
    6442              : 
    6443            0 :                         if( firstEdgeFac == nullptr || secondEdgeFac == nullptr )
    6444            0 :                                 UG_THROW("nullecke am Anfang?" << std::endl);
    6445              : 
    6446            0 :                         Face * assoFacTEndConsider = assoFacTEndCop[ indxFrcWithTE ];
    6447              : 
    6448            0 :                         if( ! FaceContains(assoFacTEndConsider, firstEdgeFac ))
    6449            0 :                                 UG_THROW("Ecke verloren geangen T " << std::endl);
    6450              : 
    6451              : //                      bool atStartSort = true;
    6452              : 
    6453              :                         // already fixed in contrast to XCross case!
    6454            0 :                         Edge * assoFacEdgBeg2Fix = firstEdgeFac;
    6455              : 
    6456              :                         // soll erst ganz am Schluss festgelegt werden
    6457            0 :                         Edge * assoFacEdgEnd2Fix = nullptr;
    6458              : 
    6459            0 :                         if( ! SortFaces4DiamondCreation( sh, assoFacTEndCop, firstEdgeFac, secondEdgeFac,
    6460              :                                         assoFacTEndConsider, origFracEdg, shiftVrtcs,
    6461              :                                         crossPt, assoFacEdgBeg2Fix, assoFacEdgEnd2Fix, grid, vecExpCrossFI
    6462              :                                         , false
    6463              :                                 )
    6464              :                         )
    6465            0 :                                 UG_THROW("Ordnen Diamant TEnd schief gegangen " << std::endl);
    6466              : 
    6467              :                         UG_LOG("Kreis des Diamanten T End Fall geschlossen " << std::endl);
    6468              : 
    6469              : //                      for( auto const & ecf : vecExpCrossFI )
    6470              : //                      {
    6471              : //                              Face * fac = ecf.getFace();
    6472              : //
    6473              : //                              IndexType sudos = sh.num_subsets();
    6474              : //
    6475              : //                              sh.assign_subset(fac,sudos);
    6476              : //                      }
    6477              : 
    6478              :                         // erfuellt, aber keine so gute Idee
    6479              :                         // im Falle von gekrümmten Fractures:
    6480              :                         // first shift the free end shift vertex along prolongation of T End incoming edge, else later problematic
    6481              : 
    6482              : 
    6483              : 
    6484              : #if 0
    6485              :                         IndexType faceOrderNumber = 0;
    6486              : 
    6487              :                         // TODO FIXME hier muss die FUnkiton verwendet und angepasst werden!
    6488              :                         while( assoFacTEndCop.size() != 0 )
    6489              :                         {
    6490              :                                 Edge * fracEdge = nullptr;
    6491              :                                 Edge * shiftVrtxEdg = nullptr;
    6492              : 
    6493              :                                 std::vector<Edge*> edgesThisFac;
    6494              : 
    6495              :                                 edgesThisFac.clear();
    6496              : 
    6497              :                                 for( std::vector<Edge *>::iterator iterEdgF = grid.associated_edges_begin(assoFacTConsider);
    6498              :                                                 iterEdgF != grid.associated_edges_end(assoFacTConsider); iterEdgF++ )
    6499              :                                 {
    6500              :                                         edgesThisFac.push_back(*iterEdgF);
    6501              :                                 }
    6502              : 
    6503              :                                 if( ! atStartSort )
    6504              :                                 {
    6505              :                                         secondEdgeFac = nullptr;
    6506              :                                 }
    6507              : 
    6508              :                                 IndexType fndFracEdg = 0;
    6509              : 
    6510              :                                 for( auto const & etf : edgesThisFac )
    6511              :                                 {
    6512              :                                         for( auto const & ofe : origFracEdg )
    6513              :                                         {
    6514              :                                                 if( etf == ofe )
    6515              :                                                 {
    6516              :                                                         fndFracEdg++;
    6517              :                                                         fracEdge = etf;
    6518              :                                                 }
    6519              :                                         }
    6520              :                                 }
    6521              : 
    6522              :                                 if( fracEdge == nullptr || fndFracEdg != 1 )
    6523              :                                 {
    6524              :                                         UG_LOG("Frac Orig Ecke nicht gefunden oder falsche Zahl " << fndFracEdg << std::endl );
    6525              : //                                      return false;
    6526              :                                         UG_THROW("Frac Orig Ecke nicht gefunden oder falsche Zahl " << fndFracEdg << std::endl );
    6527              :                                 }
    6528              : 
    6529              :                                 // find expanded shift vertex
    6530              : 
    6531              :                                 Vertex * shiftVrtxFound = nullptr;
    6532              :                                 IndexType fndVrt = 0;
    6533              :                                 IndexType helpVarEdges = 0;
    6534              : 
    6535              :                                 bool isAtFreeSideShiVe = false;
    6536              : 
    6537              :                                 for( auto const & etf : edgesThisFac )
    6538              :                                 {
    6539              :                                         if( helpVarEdges >= edgesThisFac.size() )
    6540              :                                         {
    6541              :                                                 UG_LOG("Indexueberschreitung Edges" << std::endl);
    6542              :                                                 break;
    6543              :                                         }
    6544              : 
    6545              :                                         helpVarEdges++;
    6546              : 
    6547              :                                         IndexType helpShiVaNum = 0;
    6548              : 
    6549              :                                         for( auto const & svwi : shiftVertcsWithTI )
    6550              :                                         {
    6551              :                                                 Vertex * sv = svwi.first;
    6552              : 
    6553              :                                                 if( helpShiVaNum >= shiftVrtcs.size() )
    6554              :                                                 {
    6555              :                                                         UG_LOG("Shift Vertex Index Verletzung T " << std::endl);
    6556              :                                                         break;
    6557              :                                                 }
    6558              : 
    6559              :                                                 helpShiVaNum++;
    6560              : 
    6561              : //                                              for( IndexType i = 0; i < 2; i++ )
    6562              : //                                              {
    6563              : //                                                      if( etf->vertex(i) == crossPt && etf->vertex((i+1)%2) == sv )
    6564              : //                                                      {
    6565              : //                                                              shiftVrtxFound = sv;
    6566              : //                                                              fndVrt++;
    6567              : //                                                              shiftVrtxEdg = etf;
    6568              : //
    6569              : //                                                      }
    6570              : //                                              }
    6571              : 
    6572              :                                                 // TODO FIXME expand this construct also to X Cross, so far loop
    6573              :                                                 if( EdgeContains(etf, crossPt ) && EdgeContains( etf, sv ) )
    6574              :                                                 {
    6575              :                                                         shiftVrtxFound = sv;
    6576              :                                                         fndVrt++;
    6577              :                                                         shiftVrtxEdg = etf;
    6578              : 
    6579              :                                                         isAtFreeSideShiVe = svwi.second;
    6580              :                                                 }
    6581              :                                         }
    6582              :                                 }
    6583              : 
    6584              :                                 if( fndVrt != 1 || shiftVrtxFound == nullptr || shiftVrtxEdg == nullptr )
    6585              :                                 {
    6586              :                                         UG_LOG("shift vertex komische Zahl oder null T " << fndVrt << std::endl);
    6587              : //                                      return false;
    6588              :                                         UG_THROW("shift vertex komische Zahl oder null T " << fndVrt << std::endl);
    6589              :                                 }
    6590              : 
    6591              : 
    6592              :                                 Vertex * firstVrt = shiftVrtxFound;
    6593              :                                 Vertex * secondVrt = nullptr;
    6594              : 
    6595              :                                 if( atStartSort )
    6596              :                                 {
    6597              : 
    6598              :                                         if( fracEdge != secondEdgeFac || shiftVrtxEdg != firstEdgeFac )
    6599              :                                                 UG_THROW("ALler Anfang ist schwer " << std::endl);
    6600              : 
    6601              :                                         atStartSort = false;
    6602              :                                 }
    6603              :                                 else
    6604              :                                 {
    6605              :                                         bool setShftVrtFirst = false;
    6606              : //                                      bool boundAtShiftVrtEdg = true; TODO FIXME ist das global am Anfang vom while loop setzbar wie im anderen Fall?
    6607              : 
    6608              :                                         // TODO FIXME erfuellt durch den Wechsel, sowieso die Funktion anpassen oben
    6609              : //                                      switch ( faceOrderNumber )
    6610              : //                                      {
    6611              : //                                              case 2:
    6612              : //                                                      setShftVrtFirst = false;
    6613              : //                                                      break;
    6614              : //                                              case 3:
    6615              : //                                                      setShftVrtFirst = true;
    6616              : //                                                      break;
    6617              : //                                              case 4:
    6618              : //                                                      break;
    6619              : //                                              case 5:
    6620              : //                                                      break;
    6621              : //                                              default:
    6622              : //                                                      UG_THROW("zu grosse Ordnungsnummer " << std::endl);
    6623              : //                                                      break;
    6624              : //                                      }
    6625              : 
    6626              :                                         if( setShftVrtFirst )
    6627              :                                         {
    6628              : 
    6629              :                                         }
    6630              :                                         else
    6631              :                                         {
    6632              : 
    6633              :                                         }
    6634              : 
    6635              : //                                      firstEdgeFac = fracEdge;
    6636              : //                                      secondEdgeFac = shiftVrtxEdg;
    6637              : 
    6638              : 
    6639              : //                                      if( isAtFreeSideShiVe ) // obviously not at start
    6640              : //                                      {
    6641              : //
    6642              : //                                              firstEdgeFac = fracEdge;
    6643              : //                                              secondEdgeFac = shiftVrtxEdg;
    6644              : //
    6645              : //                                      }
    6646              : //                                              firstEdgeFac = shiftVrtxEdg;
    6647              : //                                              secondEdgeFac = fracEdge;
    6648              : //
    6649              : //                                              firstVrt = shiftVrtxFound;
    6650              : //                                              secondVrt = nullptr;
    6651              : //                                      }
    6652              : //
    6653              :         //                              UG_LOG("Debug Paarbildung   " << std::endl);
    6654              : 
    6655              : 
    6656              : 
    6657              :                                 }
    6658              : 
    6659              : //                              std::pair<Edge*, Edge*> edgesFac( firstEdgeFac, secondEdgeFac );
    6660              : //
    6661              : //                              std::pair<Vertex*,Vertex*> vrtcsSF( firstVrt, secondVrt );
    6662              : //                              ExpandCrossFracInfo startFacInf( edgesFac, assoFacConsider, vrtcsSF );
    6663              : 
    6664              : 
    6665              :                                 faceOrderNumber++;
    6666              : 
    6667              :                         }
    6668              : 
    6669              : #endif
    6670              : 
    6671              :                         // create new vertex
    6672              : 
    6673              :                         // for the ending frac region, the same algorithm applies as for the X Cross in all 4 branches
    6674              :                         // for the free end, no new vertex, but new vertices along the durchgehende fracture
    6675              :                         // repectively along the original edges of the durchgehende fracture
    6676              : 
    6677              : 
    6678              : 
    6679            0 :                         IndexType sizeECF = vecExpCrossFI.size();
    6680              : 
    6681            0 :                         if( sizeECF != 6 )
    6682            0 :                                 UG_THROW("Momische Länge TEnd " << std::endl);
    6683              : 
    6684            0 :                         for( IndexType i = 0; i < sizeECF; i = i + 2 )
    6685              :                         {
    6686            0 :                                 if( vecExpCrossFI[i].getNormal().first !=  vecExpCrossFI[(i+sizeECF-1) % sizeECF].getNormal().second  )
    6687            0 :                                         UG_THROW("Kleberei TEnd schief gegangen " << std::endl);
    6688              :                         }
    6689              : //
    6690              : //                      // new vertex between face 0 and 1 and between face 4 and 5
    6691              : //
    6692              : //                      // first those along the passing fracture
    6693              : //
    6694              : ////                    ExpandCrossFracInfo & alongFreeEndStartF = vecExpCrossFI[0];
    6695              : ////                    ExpandCrossFracInfo & closeToEndingCleftBeginF = vecExpCrossFI[1];
    6696              : ////                    ExpandCrossFracInfo & endingCleftBeginF = vecExpCrossFI[2];
    6697              : ////                    ExpandCrossFracInfo & endingCleftEndF = vecExpCrossFI[3];
    6698              : ////                    ExpandCrossFracInfo & closeToEndingCleftEndF = vecExpCrossFI[4];
    6699              : ////                    ExpandCrossFracInfo & alongFreeEndEndF = vecExpCrossFI[5];
    6700              : ////
    6701              : ////                    Vertex * remainVrtx = alongFreeEndStartF.getNormal().first;
    6702              : ////                    Vertex * shiftVrtxOne = closeToEndingCleftBeginF.getNormal().second;
    6703              : ////                    Vertex * shiftVrtxTwo = endingCleftEndF.getNomal().first;
    6704              : ////
    6705              : ////                    vector3 posVRem = aaPos[remainVrtx];
    6706              : ////                    vector3 posVOne = aaPos[shiftVrtxOne];
    6707              : ////                    vector3 posVTwo = aaPos[shiftVrtxTwo];
    6708              : ////
    6709              : ////                    vector3 distOne;
    6710              : ////                    VecSubtract(distOne, posVOne, posVRem);
    6711              : ////
    6712              : ////                    vector3 distTwo;
    6713              : ////                    VecSubtract(distTwo, posVTwo, posVRem);
    6714              : ////
    6715              : ////                    vector3 distOneHalf, distTwoHalf;
    6716              : ////                    VecScale(distOneHalf, distOne, 0.5 );
    6717              : ////                    VecScale(distTwoHalf, distTwo, 0.5 );
    6718              : ////
    6719              : ////                    vector3 posNewVrtOne, posNewVrtTwo;
    6720              : ////                    VecAdd(posNewVrtOne, posVRem, distOneHalf);
    6721              : ////                    VecAdd(posNewVrtTwo, posVRem, distTwoHalf);
    6722              : ////
    6723              : ////                    Vertex * newVrtOne = *grid.create<RegularVertex>();
    6724              : ////                    Vertex * newVrtTwo = *grid.create<RegularVertex>();
    6725              : ////
    6726              : ////                    aaPos[newVrtOne] = posNewVrtOne;
    6727              : ////                    aaPos[newVrtTwo] = posNewVrtTwo;
    6728              : ////
    6729              : ////                    IndexType sudoTEnd = sh.num_subsets();
    6730              : ////
    6731              : ////                    sh.assign_subset(newVrtOne, sudoTEnd);
    6732              : ////                    sh.assign_subset(newVrtTwo, sudoTEnd);
    6733              : ////
    6734              : ////
    6735              : ////                    std::pair<Vertex*,Vertex*>  vrtcsAlongFreeEndStartF = alongFreeEndStartF.getNormal();
    6736              : ////                    std::pair<Vertex*,Vertex*>  vrtcsCloseToEndingCleftBeginF = closeToEndingCleftBeginF.getNormal();
    6737              : ////                    std::pair<Vertex*,Vertex*>  vrtcsEndingCleftBeginF = endingCleftBeginF.getNormal();
    6738              : ////                    std::pair<Vertex*,Vertex*>  vrtcsEndingCleftEndF = endingCleftEndF.getNormal();
    6739              : ////                    std::pair<Vertex*,Vertex*>  vrtcsCloseToEndingCleftEndF = closeToEndingCleftEndF.getNormal();
    6740              : ////                    std::pair<Vertex*,Vertex*>  vrtcsAlongFreeEndEndF = alongFreeEndEndF.getNormal();
    6741              : ////
    6742              : ////
    6743              : ////                    alongFreeEndStartF.setNewNormal( vrtcsAlongFreeEndStartF );
    6744              : ////                    closeToEndingCleftBeginF.setNewNormal( vrtcsCloseToEndingCleftBeginF );
    6745              : ////                    endingCleftBeginF.setNewNormal( vrtcsEndingCleftBeginF );
    6746              : ////                    endingCleftEndF.setNewNormal( vrtcsEndingCleftEndF );
    6747              : ////                    closeToEndingCleftEndF.setNewNormal( vrtcsCloseToEndingCleftEndF );
    6748              : ////                    alongFreeEndEndF.setNewNormal( vrtcsAlongFreeEndEndF );
    6749              : //
    6750            0 :                         IndexType sudoTEnd = sh.num_subsets();
    6751              : 
    6752              :                         // gemeinsame Funktion wie bei XCross neue Punkte erzeugen und anwenden in dem einzigen speziellen Fall hier!
    6753              : 
    6754              :                         IndexType indBeforeT = sizeECF / 2 - 1;
    6755              :                         IndexType indAfterT = sizeECF / 2;
    6756              : 
    6757              :                         ExpandCrossFracInfo & expCFIBeforeFracEdg = vecExpCrossFI[ indBeforeT ];
    6758              :                         ExpandCrossFracInfo & expCFIAfterFracEdg = vecExpCrossFI[ indAfterT ];
    6759              : 
    6760              :                         vector3 distVecNewVrt2SCrossPt;
    6761              : 
    6762              :                         // new vertex in ending frac
    6763              : 
    6764              : //                      computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, sudoTEnd, distVecNewVrt2SCrossPt );
    6765              : 
    6766              :                         // shift of free shift point to virtual prolongation of ending fracture center line
    6767              : 
    6768              : //                      computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, sudoTEnd, distVecNewVrt2SCrossPt );
    6769            0 :                         computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, sudoTEnd, distVecNewVrt2SCrossPt, useTrianglesInDiamonds );
    6770              : 
    6771              :                         constexpr bool shiftFreePt = false;
    6772              : 
    6773              :                         if( shiftFreePt )
    6774              :                         {
    6775              : //                              computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, sudoTEnd, distVecNewVrt2SCrossPt );
    6776              : 
    6777              :                                 vector3 posCrossPt = aaPos[crossPt];
    6778              : 
    6779              :                                 vector3 newPosFreeShiftPt;
    6780              : 
    6781              :                                 VecAdd(newPosFreeShiftPt,posCrossPt,distVecNewVrt2SCrossPt);
    6782              : 
    6783              :                                 // assign this position to shift vertex at free end
    6784              : 
    6785              :                                 aaPos[shiftVrtxAtFreeEnd] = newPosFreeShiftPt;
    6786              : 
    6787              : 
    6788              :                                 for( IndexType i = 0; i < sizeECF; i = i + ( sizeECF ) / 2 + 1 )
    6789              :                                 {
    6790              :                                         bool atStart = ( i < sizeECF / 2 );
    6791              : 
    6792              :                                         IndexType firstInd = atStart ? ( i ) % sizeECF: ( i + 1 ) % sizeECF;
    6793              :                                         IndexType secndInd = atStart ? ( i + 1 ) % sizeECF : ( i ) % sizeECF;
    6794              : 
    6795              :                                         UG_LOG("indices " << firstInd << " " << secndInd << std::endl);
    6796              : 
    6797              :                                         ExpandCrossFracInfo & alongFreeEndF = vecExpCrossFI[firstInd];
    6798              :                                         ExpandCrossFracInfo & closeToTEndF = vecExpCrossFI[secndInd];
    6799              : 
    6800              :                                         std::pair<Edge*, Edge*> freeEdgs = alongFreeEndF.getEdge();
    6801              :                                         std::pair<Edge*, Edge*> tEndEdgs = closeToTEndF.getEdge();
    6802              : 
    6803              :                                         Edge * freeCommEdg = atStart ? freeEdgs.second : freeEdgs.first;
    6804              :                                         Edge * closTCommEdg = atStart ? tEndEdgs.first : tEndEdgs.second;
    6805              : 
    6806              :                                         if( freeCommEdg != closTCommEdg || freeCommEdg == nullptr || closTCommEdg == nullptr )
    6807              :                                                 UG_THROW("freie und geschlossene Ecke ungleich oder null " << freeCommEdg << " " << closTCommEdg << std::endl);
    6808              : 
    6809              :                                         std::pair<Vertex*, Vertex*> freeVrtcs = alongFreeEndF.getNormal();
    6810              :                                         std::pair<Vertex*, Vertex*> tEndVrtcs = closeToTEndF.getNormal();
    6811              : 
    6812              :                                         Vertex * remainVrtx = atStart ? freeVrtcs.first : freeVrtcs.second;
    6813              :                                         Vertex * shiftTVrt = atStart ? tEndVrtcs.second : tEndVrtcs.first;
    6814              : 
    6815              :                                         Vertex * freeNull = atStart ? freeVrtcs.second : freeVrtcs.first;
    6816              :                                         Vertex * teNull = atStart ? tEndVrtcs.first : tEndVrtcs.second;
    6817              : 
    6818              :                                         if( freeNull != nullptr || teNull != nullptr ||  remainVrtx == nullptr || shiftTVrt == nullptr )
    6819              :                                         {
    6820              :         //                                      UG_THROW("TEnd schon falsch zugewiesene Vertizex" << std::endl);
    6821              :                                                 UG_LOG("TEnd schon falsch zugewiesene Vertizex" << std::endl);
    6822              : 
    6823              :                                                 UG_LOG("Falsch feee null " << freeNull << " T " << teNull << " R " << remainVrtx << " S " << shiftTVrt << std::endl);
    6824              : 
    6825              :                                                 UG_THROW("TEnd schon falsch zugewiesene Vertizex" << std::endl);
    6826              : 
    6827              :                                                 UG_THROW("Falsch feee null " << freeNull << " T " << teNull << " R " << remainVrtx << " S " << shiftTVrt << std::endl);
    6828              :                                         }
    6829              :                                         else
    6830              :                                         {
    6831              :                                                 UG_LOG("TEnd richtig zugewiesene Vertizex" << std::endl);
    6832              : 
    6833              :                                                 UG_LOG("Richtig feee null " << freeNull << " T " << teNull << " R " << remainVrtx << " S " << shiftTVrt << std::endl);
    6834              : 
    6835              :                                         }
    6836              : 
    6837              :                                         vector3 posVRem = aaPos[remainVrtx];
    6838              :                                         vector3 posShiVe = aaPos[shiftTVrt];
    6839              : 
    6840              :         //                              UG_LOG("pos T " << posVRem << " " << posShiVe << std::endl);
    6841              :         //
    6842              :                                         vector3 dist;
    6843              :                                         VecSubtract(dist, posShiVe, posVRem);
    6844              :         //
    6845              :         //                              UG_LOG("dist TR " << dist << std::endl);
    6846              :         //
    6847              :                                         vector3 distHalf;
    6848              :                                         VecScale(distHalf, dist, 0.5);
    6849              :         //
    6850              :         //                              UG_LOG("dist half TR " << distHalf << std::endl);
    6851              :         //
    6852              :                                         vector3 posNewVrt;
    6853              :                                         VecAdd(posNewVrt, posVRem, distHalf);
    6854              :         //
    6855              :         //                              UG_LOG("neuer Vertex Position " << posNewVrt << std::endl);
    6856              :         //
    6857              : 
    6858              :                                         Vertex * newVrt = *grid.create<RegularVertex>();
    6859              :                                         aaPos[newVrt] = posNewVrt;
    6860              : 
    6861              :                                         sh.assign_subset(newVrt, sudoTEnd);
    6862              :         //
    6863              :                                         if( atStart )
    6864              :                                         {
    6865              :                                                 freeVrtcs.second = newVrt;
    6866              :                                                 tEndVrtcs.first = newVrt;
    6867              :                                         }
    6868              :                                         else
    6869              :                                         {
    6870              :                                                 freeVrtcs.first = newVrt;
    6871              :                                                 tEndVrtcs.second = newVrt;
    6872              :                                         }
    6873              :         //
    6874              :                                         alongFreeEndF.setNewNormal( freeVrtcs );
    6875              :                                         closeToTEndF.setNewNormal( tEndVrtcs );
    6876              : 
    6877              :                                 }
    6878              : 
    6879              :                         }
    6880              :                         else // go to left and right from crossPt at same distance as where the ending cleft enters the durchgehende one
    6881              :                         {
    6882              : 
    6883              : //                              vector3 distVecNewVrt2ShiVeBefore;
    6884              : //                              vector3 distVecNewVrt2ShiVeAfter;
    6885              : 
    6886              : 
    6887              : //                              computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, sudoTEnd,
    6888              : //                                                                                         distVecNewVrt2SCrossPt. distVecNewVrt2ShiVeBefore, distVecNewVrt2ShiVeAfter, true );
    6889              :                                 //              VecSubtract(distVecNewVrt2ShiVeBefore, posShiftBefore, posNewVrtOnEdg );
    6890              : 
    6891              : 
    6892            0 :                                 for( IndexType i = 0; i < sizeECF; i = i + ( sizeECF ) / 2 + 1 )
    6893              :                                 {
    6894              :                                         bool atStart = ( i < sizeECF / 2 );
    6895              : 
    6896            0 :                                         IndexType firstInd = atStart ? ( i ) % sizeECF: ( i + 1 ) % sizeECF;
    6897            0 :                                         IndexType secndInd = atStart ? ( i + 1 ) % sizeECF : ( i ) % sizeECF;
    6898              : 
    6899              :                                         UG_LOG("indices " << firstInd << " " << secndInd << std::endl);
    6900              : 
    6901              :                                         ExpandCrossFracInfo & alongFreeEndF = vecExpCrossFI[firstInd];
    6902              :                                         ExpandCrossFracInfo & closeToTEndF = vecExpCrossFI[secndInd];
    6903              : 
    6904              :                                         std::pair<Edge*, Edge*> freeEdgs = alongFreeEndF.getEdge();
    6905              :                                         std::pair<Edge*, Edge*> tEndEdgs = closeToTEndF.getEdge();
    6906              : 
    6907            0 :                                         Edge * freeCommEdg = atStart ? freeEdgs.second : freeEdgs.first;
    6908            0 :                                         Edge * closTCommEdg = atStart ? tEndEdgs.first : tEndEdgs.second;
    6909              : 
    6910            0 :                                         if( freeCommEdg != closTCommEdg || freeCommEdg == nullptr || closTCommEdg == nullptr )
    6911            0 :                                                 UG_THROW("freie und geschlossene Ecke ungleich oder null " << freeCommEdg << " " << closTCommEdg << std::endl);
    6912              : 
    6913              :                                         std::pair<Vertex*, Vertex*> freeVrtcs = alongFreeEndF.getNormal();
    6914              :                                         std::pair<Vertex*, Vertex*> tEndVrtcs = closeToTEndF.getNormal();
    6915              : 
    6916            0 :                                         Vertex * remainVrtx = atStart ? freeVrtcs.first : freeVrtcs.second;
    6917            0 :                                         Vertex * shiftTVrt = atStart ? tEndVrtcs.second : tEndVrtcs.first;
    6918              : 
    6919            0 :                                         Vertex * freeNull = atStart ? freeVrtcs.second : freeVrtcs.first;
    6920            0 :                                         Vertex * teNull = atStart ? tEndVrtcs.first : tEndVrtcs.second;
    6921              : 
    6922            0 :                                         if( freeNull != nullptr || teNull != nullptr ||  remainVrtx == nullptr || shiftTVrt == nullptr )
    6923              :                                         {
    6924              :         //                                      UG_THROW("TEnd schon falsch zugewiesene Vertizex" << std::endl);
    6925              :                                                 UG_LOG("TEnd schon falsch zugewiesene Vertizex" << std::endl);
    6926              : 
    6927              :                                                 UG_LOG("Falsch feee null " << freeNull << " T " << teNull << " R " << remainVrtx << " S " << shiftTVrt << std::endl);
    6928              : 
    6929            0 :                                                 UG_THROW("TEnd schon falsch zugewiesene Vertizex" << std::endl);
    6930              : 
    6931              :                                                 UG_THROW("Falsch feee null " << freeNull << " T " << teNull << " R " << remainVrtx << " S " << shiftTVrt << std::endl);
    6932              :                                         }
    6933              :                                         else
    6934              :                                         {
    6935              :                                                 UG_LOG("TEnd richtig zugewiesene Vertizex" << std::endl);
    6936              : 
    6937              :                                                 UG_LOG("Richtig feee null " << freeNull << " T " << teNull << " R " << remainVrtx << " S " << shiftTVrt << std::endl);
    6938              : 
    6939              :                                         }
    6940              : 
    6941            0 :                                         vector3 posCrossPt = aaPos[crossPt];
    6942              :                                         vector3 posShiVe = aaPos[shiftTVrt];
    6943              : 
    6944              :                                         vector3 posNewVrtOnFrctrsTouchEdg;
    6945              :                                         VecSubtract( posNewVrtOnFrctrsTouchEdg, posCrossPt, distVecNewVrt2SCrossPt );
    6946              : 
    6947              :                                         vector3 distNewTouchEdgVrt2ShiVe;
    6948              :                                         VecSubtract(distNewTouchEdgVrt2ShiVe, posShiVe, posNewVrtOnFrctrsTouchEdg);
    6949              : 
    6950              :                                         number distNrm = VecLength(distNewTouchEdgVrt2ShiVe);
    6951              : 
    6952              :                                         // go along old frac edge with this length
    6953              : 
    6954              :                                         Vertex * endEdgFracV = nullptr;
    6955              : 
    6956              :                                         IndexType fndCr = 0;
    6957              : 
    6958            0 :                                         for( IndexType i = 0; i < 2; i++ )
    6959              :                                         {
    6960              : 
    6961            0 :                                                 Vertex * tV =  closTCommEdg->vertex(i);
    6962              : 
    6963            0 :                                                 if( tV == crossPt )
    6964            0 :                                                         fndCr++;
    6965              :                                                 else
    6966              :                                                         endEdgFracV = tV;
    6967              :                                         }
    6968              : 
    6969            0 :                                         if( fndCr != 1 || endEdgFracV == nullptr )
    6970            0 :                                                 UG_THROW("ENde nicht gefunden " << std::endl);
    6971              : 
    6972              :                                         vector3 posEndPt = aaPos[endEdgFracV];
    6973              : 
    6974              :                                         vector3 crsPt2EndPt;
    6975              :                                         VecSubtract(crsPt2EndPt, posEndPt, posCrossPt);
    6976              : 
    6977              :                                         vector3 unitAlong;
    6978            0 :                                         VecNormalize(unitAlong, crsPt2EndPt);
    6979              : 
    6980              :                                         vector3 scaAlong;
    6981              :                                         VecScale(scaAlong, unitAlong, distNrm);
    6982              : 
    6983              :                                         vector3 posNewVrt;
    6984              : 
    6985              :                                         VecAdd(posNewVrt, posCrossPt, scaAlong);
    6986              : 
    6987            0 :                                         Vertex * newVrt = *grid.create<RegularVertex>();
    6988              :                                         aaPos[newVrt] = posNewVrt;
    6989              : 
    6990            0 :                                         sh.assign_subset(newVrt, sudoTEnd);
    6991              :         //
    6992            0 :                                         if( atStart )
    6993              :                                         {
    6994              :                                                 freeVrtcs.second = newVrt;
    6995              :                                                 tEndVrtcs.first = newVrt;
    6996              :                                         }
    6997              :                                         else
    6998              :                                         {
    6999              :                                                 freeVrtcs.first = newVrt;
    7000              :                                                 tEndVrtcs.second = newVrt;
    7001              :                                         }
    7002              :         //
    7003              :                                         alongFreeEndF.setNewNormal( freeVrtcs );
    7004              :                                         closeToTEndF.setNewNormal( tEndVrtcs );
    7005              : 
    7006              :                                 }
    7007              : 
    7008              :                         }
    7009              : 
    7010              : 
    7011              :                         // create new edges and new faces
    7012              : 
    7013              :                         // edges and faces outside the diamond, at the crossing fractures attached to the diamond
    7014              : 
    7015              :                         std::vector<Face*> newFracFaceVec = std::vector<Face*>();
    7016              : 
    7017            0 :                         bool boundAtShiftVrtEdg = false;
    7018              : //                      bool atStartSort = false;
    7019              : 
    7020              : //                      for( IndexType i = indBeforeT; i <= indAfterT; i++ )
    7021            0 :                         for( auto const & ecf : vecExpCrossFI )
    7022              :                         {
    7023              : //                              createNewFacesForExtXCrossFracs( vecExpCrossFI[i], newFracFaceVec, boundAtShiftVrtEdg, atStartSort, sh, grid, crossPt, subdomList );
    7024            0 :                                 createNewFacesForExtXCrossFracs( ecf, newFracFaceVec, boundAtShiftVrtEdg, sh, grid, crossPt, subdomList );
    7025              :                         }
    7026              : 
    7027              :                         // edges and faces of the diamond itself respectively its analogon for the TEnd case here
    7028              : 
    7029              :                         std::vector<Face*> newDiamFaceVec = std::vector<Face*>();
    7030              : 
    7031              : //                      ExpandCrossFracInfo & expCFIBeforeFracEdg = vecExpCrossFI[ indBeforeT ];
    7032              : //                      ExpandCrossFracInfo & expCFIAfterFracEdg = vecExpCrossFI[ indAfterT ];
    7033              : 
    7034              : 
    7035              : //                      createDiamondFacesXCrossType( expCFIAfterFracEdg, expCFIBeforeFracEdg,
    7036              : //                                                                      newDiamFaceVec,  sh, grid, sudoTEnd, crossPt );
    7037              : 
    7038              :                         // only the non free part
    7039              : //                      for( int indC = 1; indC < sizeECF-2; indC = indC + 2 )
    7040            0 :                         for( int indC = -1; indC < sizeECF-2; indC = indC + 2 )
    7041              :                         {
    7042              : 
    7043              :                                 // Create Spitze at free side
    7044            0 :                                 bool isAtFreeEnd = ( indC == -1 );
    7045              : 
    7046            0 :                                 IndexType indBefore = ( indC + sizeECF ) % sizeECF;
    7047            0 :                                 IndexType indAfter = ( indC + 1 + sizeECF ) % sizeECF;
    7048              : 
    7049              : 
    7050            0 :                                 ExpandCrossFracInfo & expCFIBeforeFracEdg = vecExpCrossFI[ indBefore ];
    7051            0 :                                 ExpandCrossFracInfo & expCFIAfterFracEdg = vecExpCrossFI[ indAfter ];
    7052              : 
    7053              : 
    7054              : //                              createDiamondFacesXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg,
    7055              : //                                              newDiamFaceVec,  sh, grid, sudoTEnd, crossPt, isAtFreeEnd );
    7056            0 :                                 createDiamondFacesXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg,
    7057            0 :                                                 newDiamFaceVec,  sh, grid, sudoTEnd, crossPt, isAtFreeEnd || useTrianglesInDiamonds );
    7058              : 
    7059              :                         }
    7060              : //                      }
    7061              : 
    7062              : 
    7063              : 
    7064            0 :                         std::string diamNam = std::string("spitzDiam_") + std::string(const_cast<char*>( sh.get_subset_name( subdomList[0] ) ))
    7065            0 :                                                       + std::string("_") + std::string(const_cast<char*>( sh.get_subset_name( subdomList[1] ) ));
    7066              : 
    7067            0 :                         sh.set_subset_name(diamNam.c_str(),sudoTEnd);
    7068              : 
    7069            0 :                         assignFaceSubsetToClosedFace( newFracFaceVec, grid, sh );
    7070            0 :                         assignFaceSubsetToClosedFace( newDiamFaceVec, grid, sh );
    7071              : 
    7072              : //                      for( auto const & fdel : vecExpCrossFI )
    7073              : //                      {
    7074              : //                              Face * fac2BeDeleted = fdel.getFace();
    7075              : //
    7076              : //                              if( fac2BeDeleted != nullptr )
    7077              : //                                      grid.erase(fac2BeDeleted);
    7078              : //                              else
    7079              : //                                      UG_THROW("hier fehlt ein Gesicht " << std::endl);
    7080              : //                      }
    7081              : //
    7082              : //                      for( auto const & edg : allAssoEdgCP )
    7083              : //                      {
    7084              : ////                            Edge * e2D = oEdg;
    7085              : //
    7086              : //                              if( edg != nullptr && edg != shiftVrtxAtFirstFacEdg )
    7087              : //                              {
    7088              : //                                      UG_LOG("will erasieren " << edg << std::endl );
    7089              : //                                      grid.erase(edg);
    7090              : //
    7091              : ////                                    sh.assign_subset( e2D, subsNumNow );
    7092              : ////                                    sh.assign_subset( e2D, subsNumNow );
    7093              : //                              }
    7094              : //                              else
    7095              : //                              {
    7096              : //                                      UG_LOG("hier fehlt eine Ecke " << std::endl);
    7097              : //                              }
    7098              : //                      }
    7099              : 
    7100              :                         avoidToDeleteEdge = shiftVrtxAtFirstFacEdg;
    7101              : 
    7102            0 :                         UG_LOG("T End Kreis fertig an " << aaPos[crossPt] << std::endl );
    7103              : 
    7104            0 :                 }
    7105              :                 //              else if( nuCroFra == 4 )
    7106            0 :                 else if( fracTyp == CrossVertInf::XCross )
    7107              :                 {
    7108              :                         // sort faces and corresponding edges, start with an oririnal fracture edge and select the next edge which
    7109              :                         // has a newly created shift vertex
    7110              : 
    7111            0 :                         auto assoFacXCrossCop = assoFacCross;
    7112              : 
    7113              :                         // "durchdrehen"
    7114              : 
    7115              : //                      Face * assoFacConsider = *(assoFacXCrossCop.begin());
    7116            0 :                         Face * assoFacConsider = assoFacXCrossCop[0];
    7117              : 
    7118              :                         // soll einmal am Anfang festgelegt werden und dann bleiben
    7119            0 :                         Edge * assoFacEdgBeg2Fix = nullptr;
    7120              :                         // soll erst ganz am Schluss festgelegt werden
    7121            0 :                         Edge * assoFacEdgEnd2Fix = nullptr;
    7122              : 
    7123              :                         // soll in jedem Lauf aktualisiert werden
    7124            0 :                         Edge * firstEdgeFac = assoFacEdgBeg2Fix;
    7125            0 :                         Edge * secondEdgeFac = nullptr;
    7126              : 
    7127              : //                      bool atStartSort = true;
    7128              : 
    7129              : //                      using ExpandCrossFracInfo = VertexFractureTriple< std::pair<Edge*, Edge*>, Face*, std::pair<Vertex*, Vertex*> >;
    7130              : //                      // Vertex nullptr wo original fracture, und shift vertex, wo Keilecke, die weg soll
    7131              : //
    7132              : //                      using VecExpandCrossFracInfo = std::vector<ExpandCrossFracInfo>;
    7133              : 
    7134              : //                      VecExpandCrossFracInfo vecExpCrossFI;
    7135              : 
    7136              : //                      bool boundAtShiftVrtEdg = true;
    7137              : 
    7138              : //                      auto shiftVrtcsCop = shiftVrtcs;
    7139              : 
    7140              : //                      UG_LOG("starting Rundlauf " << std::endl);
    7141              : 
    7142              : //                      IndexType dbg_rndl = 0;
    7143              : 
    7144            0 :                         if( ! SortFaces4DiamondCreation( sh, assoFacXCrossCop, firstEdgeFac, secondEdgeFac,
    7145              :                                         assoFacConsider, origFracEdg, shiftVrtcs,
    7146              :                                         crossPt, assoFacEdgBeg2Fix, assoFacEdgEnd2Fix, grid, vecExpCrossFI
    7147              :                                         , true
    7148              :                                 )
    7149              :                         )
    7150            0 :                                 UG_THROW("Ordnen Diamant X Cross schief gegangen " << std::endl);
    7151              : 
    7152              : #if 0
    7153              :                         while( assoFacXCrossCop.size() != 0 )
    7154              :                         {
    7155              : 
    7156              : //                              UG_LOG("Debug Rundlauf " << dbg_rndl << std::endl);
    7157              : 
    7158              :                                 dbg_rndl++;
    7159              : 
    7160              :                                 secondEdgeFac = nullptr;
    7161              : 
    7162              :                                 Edge * fracEdge = nullptr;
    7163              :                                 Edge * shiftVrtxEdg = nullptr;
    7164              : 
    7165              : //                              IndexType fndEdgEnd = 0;
    7166              : 
    7167              :                                 std::vector<Edge*> edgesThisFac;
    7168              : 
    7169              :                                 edgesThisFac.clear();
    7170              : 
    7171              : //                              IndexType eoeo = edgesThisFac.size();
    7172              : //
    7173              : //                              auto eiei = eoeo;
    7174              : 
    7175              : //                              UG_LOG("Edges this fac Orig Orig " << eiei <<  " " << dbg_rndl << std::endl);
    7176              : 
    7177              : 
    7178              : //                              UG_LOG("Debug Ecken " << std::endl);
    7179              : 
    7180              :                                 IndexType dbg_itEd = 0;
    7181              : 
    7182              :                                 for( std::vector<Edge *>::iterator iterEdgF = grid.associated_edges_begin(assoFacConsider);
    7183              :                                                 iterEdgF != grid.associated_edges_end(assoFacConsider); iterEdgF++ )
    7184              :                                 {
    7185              :                                         edgesThisFac.push_back(*iterEdgF);
    7186              : 
    7187              : //                                      UG_LOG("und noch eines dazu " << dbg_itEd << " " << dbg_rndl << std::endl);
    7188              : 
    7189              :                                         //IndexType sudos = sh.num_subsets();
    7190              : 
    7191              :                                         //sh.assign_subset(*iterEdgF,sudos);
    7192              :                                 }
    7193              : 
    7194              : //                              IndexType effsOrig = edgesThisFac.size();
    7195              : 
    7196              : //                              auto efeu = effsOrig;
    7197              : 
    7198              : //                              UG_LOG("Edges this fac Orig " << efeu <<  dbg_rndl << std::endl);
    7199              : 
    7200              : 
    7201              :                                 // figure out original fracture edge
    7202              : 
    7203              :                                 IndexType fndFracEdg = 0;
    7204              : 
    7205              :                                 for( auto const & etf : edgesThisFac )
    7206              :                                 {
    7207              :                                         for( auto const & ofe : origFracEdg )
    7208              :                                         {
    7209              :                                                 if( etf == ofe )
    7210              :                                                 {
    7211              :                                                         fndFracEdg++;
    7212              :                                                         fracEdge = etf;
    7213              :                                                 }
    7214              :                                         }
    7215              :                                 }
    7216              : 
    7217              : //                              UG_LOG("Debug Ofen  " << std::endl);
    7218              : 
    7219              : 
    7220              :                                 if( fracEdge == nullptr || fndFracEdg != 1 )
    7221              :                                 {
    7222              :                                         UG_LOG("Frac Orig Ecke nicht gefunden oder falsche Zahl " << fndFracEdg << std::endl );
    7223              : //                                      return false;
    7224              :                                         UG_THROW("Frac Orig Ecke nicht gefunden oder falsche Zahl " << fndFracEdg << std::endl );
    7225              :                                 }
    7226              : 
    7227              : 
    7228              :                                 // find expanded shift vertex
    7229              : 
    7230              :                                 Vertex * shiftVrtxFound = nullptr;
    7231              :                                 IndexType fndVrt = 0;
    7232              : 
    7233              : //                              IndexType suse = sh.num_subsets();
    7234              : 
    7235              :                                 //sh.assign_subset(crossPt,suse);
    7236              : 
    7237              : //                              for( auto & sv : shiftVrtcsCop )
    7238              : //                              {
    7239              : //                                      IndexType suseV = sh.num_subsets();
    7240              : //                                      //sh.assign_subset(sv,suseV);
    7241              : //                              }
    7242              : 
    7243              : //                              return true;
    7244              : 
    7245              : //                              UG_LOG("Debug Entfernene    " << std::endl);
    7246              : 
    7247              :                                 IndexType dbg_edgnum = 0;
    7248              : 
    7249              :                                 IndexType helpVarEdges = 0;
    7250              : 
    7251              : //                              IndexType effs = edgesThisFac.size();
    7252              : //                              IndexType shiffs = shiftVrtcs.size();
    7253              : 
    7254              : //                              UG_LOG("Edges this fac " <<  effs <<  dbg_rndl << std::endl);
    7255              : //                              UG_LOG("Shift Vectors " <<  shiffs <<  dbg_rndl << std::endl);
    7256              : 
    7257              : 
    7258              :                                 for( auto const & etf : edgesThisFac )
    7259              :                                 {
    7260              : 
    7261              :                                         if( helpVarEdges >= edgesThisFac.size() )
    7262              :                                         {
    7263              :                                                 UG_LOG("Indexueberschreitung Edges" << std::endl);
    7264              :                                                 break;
    7265              :                                         }
    7266              : 
    7267              :                                         helpVarEdges++;
    7268              : 
    7269              :                                         dbg_edgnum++;
    7270              : 
    7271              :                                         IndexType helpShiVaNum = 0;
    7272              : 
    7273              :                                         IndexType dbg_shiVe = 0;
    7274              : 
    7275              : //                                      for( Vertex * const & sv : shiftVrtcs )
    7276              :                                         for( auto const & sv : shiftVrtcs )
    7277              :                                         {
    7278              : 
    7279              :                                                 if( helpShiVaNum >= shiftVrtcs.size() )
    7280              :                                                 {
    7281              :                                                         UG_LOG("Shift Vertex Index Verletzung " << std::endl);
    7282              :                                                         break;
    7283              :                                                 }
    7284              : 
    7285              :                                                 helpShiVaNum++;
    7286              : 
    7287              :                                                 dbg_shiVe++;
    7288              : 
    7289              :                                                 for( IndexType i = 0; i < 2; i++ )
    7290              :                                                 {
    7291              : //                                                      if( ( etf->vertex(i) == crossPt && etf->vertex((i+1)%2) == sv )  || (etf->vertex((i+1)%2) == crossPt && etf->vertex(i) == sv ))
    7292              :                                                         if( etf->vertex(i) == crossPt && etf->vertex((i+1)%2) == sv )
    7293              :                                                         {
    7294              :                                                                 shiftVrtxFound = sv;
    7295              :                                                                 fndVrt++;
    7296              :                                                                 shiftVrtxEdg = etf;
    7297              : 
    7298              : //                                                              UG_LOG("Shift Vertex " << aaPos[shiftVrtxFound] << " " << dbg_edgnum << " " << dbg_shiVe << " " << dbg_rndl << std::endl);
    7299              : //                                                              UG_LOG("Cross Vertex " << aaPos[crossPt] << " " << dbg_edgnum << " " << dbg_shiVe <<  " " << dbg_rndl <<  std::endl );
    7300              : //
    7301              : //                                                              UG_LOG("dbg edgenu shive " << dbg_edgnum << " " << dbg_shiVe <<  " " << dbg_rndl <<  std::endl);
    7302              :                                                         }
    7303              :                                                 }
    7304              :                                         }
    7305              :                                 }
    7306              : 
    7307              : //                              UG_LOG("Debug Entfert durch         " << std::endl);
    7308              : 
    7309              : 
    7310              :                                 if( fndVrt != 1 || shiftVrtxFound == nullptr || shiftVrtxEdg == nullptr )
    7311              :                                 {
    7312              :                                         UG_LOG("shift vertex komische Zahl oder null " << fndVrt << std::endl);
    7313              : //                                      return false;
    7314              :                                         UG_THROW("shift vertex komische Zahl oder null " << fndVrt << std::endl);
    7315              :                                 }
    7316              : 
    7317              : //                              UG_LOG("Debug Entfert Text durch    " << std::endl);
    7318              : 
    7319              : 
    7320              : //                              for( std::vector<Vertex*>::iterator itV = shiftVrtcsCop.begin(); itV != shiftVrtcsCop.end(); itV++ )
    7321              : //                              {
    7322              : //                                      Vertex * vrt = *itV;
    7323              : //
    7324              : //                                      if( vrt == shiftVrtxFound )
    7325              : //                                      {
    7326              : //                                              shiftVrtcsCop.erase(itV);
    7327              : //                                              break;
    7328              : //                                      }
    7329              : //                              }
    7330              : //
    7331              : //                              UG_LOG("Debug Rasieren durch        " << std::endl);
    7332              : 
    7333              : 
    7334              :                                 if( atStartSort )
    7335              :                                 {
    7336              :                                         assoFacEdgBeg2Fix = fracEdge;
    7337              :                                         atStartSort = false;
    7338              :                                 }
    7339              : 
    7340              : //                              Edge * firstEdgeFac = fracEdge;
    7341              : //                              Edge * secondEdgeFac = shiftEdge;
    7342              :                                 firstEdgeFac = fracEdge;
    7343              :                                 secondEdgeFac = shiftVrtxEdg;
    7344              : 
    7345              : 
    7346              :                                 Vertex * firstVrt = nullptr;
    7347              :                                 Vertex * secondVrt = shiftVrtxFound;
    7348              : 
    7349              :                                 if( !boundAtShiftVrtEdg )
    7350              :                                 {
    7351              :                                         firstEdgeFac = shiftVrtxEdg;
    7352              :                                         secondEdgeFac = fracEdge;
    7353              : 
    7354              :                                         firstVrt = shiftVrtxFound;
    7355              :                                         secondVrt = nullptr;
    7356              :                                 }
    7357              : 
    7358              : //                              UG_LOG("Debug Paarbildung   " << std::endl);
    7359              : 
    7360              : 
    7361              :                                 std::pair<Edge*, Edge*> edgesFac( firstEdgeFac, secondEdgeFac );
    7362              : 
    7363              :                                 std::pair<Vertex*,Vertex*> vrtcsSF( firstVrt, secondVrt );
    7364              : 
    7365              :                                 ExpandCrossFracInfo startFacInf( edgesFac, assoFacConsider, vrtcsSF );
    7366              : 
    7367              :                                 vecExpCrossFI.push_back(startFacInf);
    7368              : 
    7369              : //                              IndexType sui = sh.num_subsets();
    7370              : //
    7371              : //                              sh.assign_subset(assoFacConsider,sui);
    7372              : 
    7373              : //                              UG_LOG("Debug Paarbildung  Rasieren " << std::endl);
    7374              : 
    7375              :                                 IndexType dbg_it_er = 0;
    7376              : 
    7377              :                                 for( std::vector<Face*>::iterator itFac = assoFacXCrossCop.begin(); itFac != assoFacXCrossCop.end(); itFac++ )
    7378              :                                 {
    7379              :                                         Face * iFa = *itFac;
    7380              : 
    7381              : //                                      UG_LOG("interieren " << dbg_it_er << std::endl );
    7382              : 
    7383              :                                         dbg_it_er++;
    7384              : 
    7385              : //                                      UG_LOG("ifa " << iFa << std::endl );
    7386              : //                                      UG_LOG("assoFac " << assoFacConsider << std::endl );
    7387              : 
    7388              : //                                      bool enthaltung = FaceContains( iFa, firstEdgeFac );
    7389              : //
    7390              : ////                                    UG_LOG("Enthaltung " << std::endl);
    7391              : //
    7392              : //                                      bool entzwei = FaceContains(iFa, secondEdgeFac);
    7393              : //
    7394              : ////                                    UG_LOG("Entzweiung " << std::endl);
    7395              : 
    7396              : 
    7397              :                                         if( iFa == assoFacConsider && FaceContains( iFa, firstEdgeFac ) && FaceContains(iFa, secondEdgeFac) )
    7398              :                                         {
    7399              : //                                              UG_LOG("Erasieren " << std::endl);
    7400              :                                                 assoFacXCrossCop.erase(itFac);
    7401              :                                                 break;
    7402              :                                         }
    7403              :                                 }
    7404              : 
    7405              : //                              UG_LOG("Debug Paarbildung  Rasieren durch " << std::endl);
    7406              : 
    7407              : 
    7408              :                                 if( assoFacXCrossCop.size() == 0 )
    7409              :                                 {
    7410              :                                         if( secondEdgeFac != assoFacEdgBeg2Fix )
    7411              :                                         {
    7412              :                                                 UG_LOG("Gesichter Diamant leer, aber keine Anfangsecke gefunden" << std::endl);
    7413              : //                                              return false;
    7414              :                                                 UG_THROW("Gesichter Diamant leer, aber keine Anfangsecke gefunden" << std::endl);
    7415              :                                         }
    7416              :                                         else
    7417              :                                         {
    7418              :                                                 assoFacEdgEnd2Fix = secondEdgeFac;
    7419              : 
    7420              :                                                 break; // while loop zu Ende, raus aus dem while loop, den Rest nicht mehr machen, würde schief gehen zwingendermassen
    7421              :                                         }
    7422              : 
    7423              :                                 }
    7424              : 
    7425              :                                 // figure out the next face
    7426              : 
    7427              :                                 firstEdgeFac = secondEdgeFac;
    7428              :                                 secondEdgeFac = nullptr;
    7429              : 
    7430              :                                 IndexType nextFaceFound = 0;
    7431              : 
    7432              :                                 for( std::vector<Face*>::iterator itFac = assoFacXCrossCop.begin(); itFac != assoFacXCrossCop.end(); itFac++ )
    7433              :                                 {
    7434              :                                         Face * iFa = *itFac;
    7435              : 
    7436              :                                         if( FaceContains(iFa, firstEdgeFac ) )
    7437              :                                         {
    7438              :                                                 nextFaceFound++;
    7439              :                                         }
    7440              :                                 }
    7441              : 
    7442              :                                 if( nextFaceFound != 1 )
    7443              :                                 {
    7444              :                                         UG_LOG("folgendes Gesicht in falscher Anztahl gefunden Diamant " << nextFaceFound << std::endl);
    7445              : //                                      return false;
    7446              :                                         UG_THROW("folgendes Gesicht in falscher Anztahl gefunden Diamant " << nextFaceFound << std::endl);
    7447              :                                 }
    7448              : 
    7449              :                                 for( std::vector<Face*>::iterator itFac = assoFacXCrossCop.begin(); itFac != assoFacXCrossCop.end(); itFac++ )
    7450              :                                 {
    7451              :                                         Face * iFa = *itFac;
    7452              : 
    7453              :                                         if( FaceContains(iFa, firstEdgeFac ) )
    7454              :                                         {
    7455              :                                                 assoFacConsider = iFa;
    7456              :                                                 break;
    7457              :                                         }
    7458              :                                 }
    7459              : 
    7460              : 
    7461              :                                 boundAtShiftVrtEdg = ! boundAtShiftVrtEdg;
    7462              :                         }
    7463              : 
    7464              : 
    7465              :                         if( assoFacEdgEnd2Fix != assoFacEdgBeg2Fix || assoFacEdgEnd2Fix == nullptr || assoFacEdgBeg2Fix == nullptr )
    7466              :                         {
    7467              :                                 UG_THROW("Anfang und Ende stimmen nicht ueberein " << std::endl);
    7468              : //                              return false;
    7469              :                                 UG_THROW("Anfang und Ende stimmen nicht ueberein " << std::endl);
    7470              :                         }
    7471              : 
    7472              : //                      if( shiftVrtcsCop.size() != 0 )
    7473              : //                      {
    7474              : //                              UG_LOG("Shift vertizes nicht alle gefinden " << std::endl);
    7475              : //                              return false;
    7476              : //                              UG_THROW("Shift vertizes nicht alle gefinden " << std::endl);
    7477              : //                      }
    7478              : 
    7479              :                         if( assoFacXCrossCop.size() != 0 )
    7480              :                         {
    7481              :                                 UG_LOG("nicht alle asso facs gefunden " << std::endl);
    7482              : //                              return false;
    7483              :                                 UG_THROW("nicht alle asso facs gefunden " << std::endl);
    7484              :                         }
    7485              : #endif
    7486              : 
    7487              :                         UG_LOG("Kreis des Diamanten X Fall geschlossen " << std::endl);
    7488              : 
    7489              :                         // create new vertices and new edges and new faces, delete the old ones at end not to forget
    7490              : 
    7491              : //                      IndexType vecfis = vecExpCrossFI.size();
    7492              : //
    7493              : //                      UG_LOG("Punkte werden erzeugt " << vecfis << std::endl);
    7494              : //
    7495              : //                      for( IndexType i = -1; i < 8; i = i + 2 )
    7496              : //                              UG_LOG("iiii " << i << std::endl);
    7497              : //
    7498              : //                      for( IndexType indC = -1; indC < 8; indC = indC + 2 )
    7499              : //                      {
    7500              : //
    7501              : //                              UG_LOG("Punkterzeugung Test " << indC << std::endl );
    7502              : //
    7503              : //                      }
    7504              : //
    7505              : //                      return true;
    7506              : 
    7507              :                         //                      IndexType diamantSubsNum = sh.num_subsets()+1; // +1 notwendig? TODO FIXME wieso nicht +1?
    7508            0 :                         IndexType diamantSubsNum = sh.num_subsets(); // +1 notwendig? TODO FIXME
    7509              : 
    7510            0 :                         int vecfis = vecExpCrossFI.size();
    7511              : 
    7512              : //                      for( int indC = -1; indC < vecfis; indC = indC + 2 )
    7513              : //                              UG_LOG("Punkterzeugung " << indC << std::endl );
    7514              : //
    7515              : 
    7516              : //                      for( int indC = -1; indC < vecExpCrossFI.size(); indC = indC + 2 )
    7517            0 :                         for( int indC = -1; indC < vecfis-2; indC = indC + 2 )
    7518              :                         {
    7519              : 
    7520              : //                              UG_LOG("Punkterzeugung X " << indC << std::endl );
    7521              : 
    7522              : 
    7523            0 :                                 IndexType indBefore = ( indC + vecExpCrossFI.size() ) % vecExpCrossFI.size();
    7524            0 :                                 IndexType indAfter = ( indC + 1 + vecExpCrossFI.size() ) % vecExpCrossFI.size();
    7525              : 
    7526              :                                 // TODO FIXME ab hier in externe Funktion stecken, damit auch für TEnd endende Frac Seite verwendbar!!!!
    7527              : 
    7528              :                                 ExpandCrossFracInfo & expCFIBeforeFracEdg = vecExpCrossFI[ indBefore ];
    7529              :                                 ExpandCrossFracInfo & expCFIAfterFracEdg = vecExpCrossFI[ indAfter ];
    7530              : 
    7531              :                                 vector3 distVecNewVrt2SCrossPt; // not ot interest here, but only with c++17 possible to rule out computation in a clever way
    7532              : 
    7533              : //                              computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, diamantSubsNum, distVecNewVrt2SCrossPt );
    7534            0 :                                 computeDiamondPointXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg, crossPt, aaPos, sh, grid, diamantSubsNum, distVecNewVrt2SCrossPt, useTrianglesInDiamonds );
    7535              : 
    7536              : #if 0
    7537              : 
    7538              : 
    7539              :                                 // compute cross point
    7540              : 
    7541              :                                 std::pair<Edge*, Edge*> edgesCrossSegBefore = expCFIBeforeFracEdg.getEdge();
    7542              :                                 std::pair<Edge*, Edge*> edgesCrossSegAfter = expCFIAfterFracEdg.getEdge();
    7543              : 
    7544              :                                 Edge * beforeShiftEdg = edgesCrossSegBefore.first;
    7545              :                                 Edge * beforeFracEdg = edgesCrossSegBefore.second;
    7546              :                                 Edge * afterFracEdg = edgesCrossSegAfter.first;
    7547              :                                 Edge * afterShiftEdg = edgesCrossSegAfter.second;
    7548              : 
    7549              :                                 std::pair<Vertex*,Vertex*> vrtcsCrossSegBefore = expCFIBeforeFracEdg.getNormal();
    7550              :                                 std::pair<Vertex*,Vertex*> vrtcsCrossSegAfter = expCFIAfterFracEdg.getNormal();
    7551              : 
    7552              :                                 Vertex * shiftBefore = vrtcsCrossSegBefore.first;
    7553              :                                 Vertex * shiftAfter = vrtcsCrossSegAfter.second;
    7554              : 
    7555              :                                 // zur Zielsetzung
    7556              : //                              Vertex * toBeEstablishedCutEdgeVrtBefore = vrtcsCrossSegBefore.second;
    7557              : //                              Vertex * toBeEstablishedCutEdgeVrtAfter = vrtcsCrossSegAfter.first;
    7558              : 
    7559              :                                 if(    vrtcsCrossSegBefore.second != nullptr ||  vrtcsCrossSegAfter.first != nullptr
    7560              :                                         ||      shiftBefore == nullptr || shiftAfter == nullptr
    7561              : //                              if(    toBeEstablishedCutEdgeVrtBefore != nullptr ||  toBeEstablishedCutEdgeVrtAfter != nullptr
    7562              : //                                      ||      shiftBefore == nullptr || shiftAfter == nullptr
    7563              :                                   )
    7564              :                                         UG_THROW("Nullpointer fehlen oder zu viel " << std::endl);
    7565              : 
    7566              :                                 if(    beforeFracEdg != afterFracEdg || beforeFracEdg == nullptr || afterFracEdg == nullptr
    7567              :                                         || beforeShiftEdg == nullptr || afterShiftEdg == nullptr
    7568              :                                   )
    7569              :                                         UG_LOG("Ecken Nullpunkter " << std::endl);
    7570              : 
    7571              :                                 // determin cut point of line between the shift vertices and the frac edge
    7572              : 
    7573              :                                 Edge * fracEdge = beforeFracEdg; // muss gleich sein offenkundig afterFracEdge, ist getestet auch
    7574              : 
    7575              :                                 // Gerade bestimmen, die durch fracEdge bestimmt wird, und Gerade, die durch Verbindungsvektor shift Verzices bestimmt wird
    7576              : 
    7577              :                                 // figure out frac vertex which is the cross point
    7578              : 
    7579              :                                 IndexType fracEdgInd = -1;
    7580              : 
    7581              :                                 for( IndexType fiv = 0; fiv < 2; fiv++ )
    7582              :                                 {
    7583              :                                         if( fracEdge->vertex(fiv) == crossPt )
    7584              :                                                 fracEdgInd = fiv;
    7585              :                                 }
    7586              : 
    7587              :                                 if( fracEdgInd < 0 || fracEdgInd > 1 )
    7588              :                                         UG_THROW("cross point nicht Teil von fracture edge" << std::endl );
    7589              : 
    7590              :                                 Vertex * fracEdgEnd = fracEdge->vertex( ( fracEdgInd + 1 ) % 2 );
    7591              : 
    7592              :                                 vector3 posCrossPt = aaPos[ crossPt ];
    7593              :                                 vector3 posFracEnd = aaPos[ fracEdgEnd ];
    7594              : 
    7595              :                                 vector3 posShiftBefore = aaPos[ shiftBefore ];
    7596              :                                 vector3 posShiftAfter = aaPos[ shiftAfter ];
    7597              : 
    7598              :                                 vector3 directionFrac;
    7599              : 
    7600              :                                 VecSubtract(directionFrac, posFracEnd, posCrossPt );
    7601              : 
    7602              :                                 vector3 directionShiftBefore;
    7603              : 
    7604              :                                 VecSubtract(directionShiftBefore, posShiftBefore, posCrossPt);
    7605              : 
    7606              :                                 vector3 directionShiftAfter;
    7607              : 
    7608              :                                 VecSubtract(directionShiftAfter, posShiftAfter, posCrossPt );
    7609              : 
    7610              :                                 vector3 sumShift;
    7611              : 
    7612              :                                 VecAdd(sumShift, directionShiftBefore, directionShiftAfter);
    7613              : 
    7614              :                                 vector3 halfSumShift;
    7615              : 
    7616              :                                 VecScale(halfSumShift,sumShift,0.5);
    7617              : 
    7618              :                                 vector3 posNewVrtOnEdg;
    7619              : 
    7620              :                                 VecAdd( posNewVrtOnEdg, posCrossPt, halfSumShift );
    7621              : 
    7622              :                                 Vertex * newEdgVrtx = *grid.create<RegularVertex>();
    7623              :                                 aaPos[newEdgVrtx] = posNewVrtOnEdg;
    7624              : 
    7625              :                                 IndexType sudoEdg = sh.get_subset_index(fracEdge);
    7626              : 
    7627              :                                 Face * faceBefore = expCFIBeforeFracEdg.getFace();
    7628              :                                 Face * faceAfter = expCFIAfterFracEdg.getFace();
    7629              : 
    7630              :                                 IndexType sudoBefore = sh.get_subset_index(faceBefore);
    7631              :                                 IndexType sudoAfter = sh.get_subset_index(faceAfter);
    7632              : 
    7633              :                                 if( sudoEdg != sudoBefore || sudoBefore != sudoAfter )
    7634              :                                         UG_THROW("komische sudos vor Diamant " << std::endl);
    7635              : 
    7636              :                                 sh.assign_subset(newEdgVrtx, sudoEdg);
    7637              : 
    7638              :                                 UG_LOG("neuer Diamant Vorbereitungs Vertex " << posNewVrtOnEdg << std::endl);
    7639              : 
    7640              :                                 //                              Vertex * toBeEstablishedCutEdgeVrtBefore = vrtcsCrossSegBefore.second;
    7641              :                                 //                              Vertex * toBeEstablishedCutEdgeVrtAfter = vrtcsCrossSegAfter.first;
    7642              : 
    7643              : 
    7644              : 
    7645              :                                 // gleich neue Faces erzeugen?
    7646              : //                              std::pair<Vertex*,Vertex*> vrtcsCrossSegBefore = expCFIBeforeFracEdg.getNormal();
    7647              : //                              std::pair<Vertex*,Vertex*> vrtcsCrossSegAfter = expCFIAfterFracEdg.getNormal();
    7648              : 
    7649              :                                 // insert the newly established vertex into the vertex info of the ExpandCrossFracInfo of the face
    7650              : ////                            vrtcsCrossSegBefore.second = newEdgVrtx;
    7651              : ////                            vrtcsCrossSegAfter.first = newEdgVrtx;
    7652              : ////
    7653              : //                              std::pair<Vertex*,Vertex*> vrtcsCrossSegBeforeNew( vrtcsCrossSegBefore.first, newEdgVrtx );
    7654              : //                              std::pair<Vertex*,Vertex*> vrtcsCrossSegAfterNew( newEdgVrtx, vrtcsCrossSegAfter.second );
    7655              : //
    7656              : //
    7657              : //                              expCFIBeforeFracEdg.setNewNormal( vrtcsCrossSegBeforeNew );
    7658              : //                              expCFIAfterFracEdg.setNewNormal( vrtcsCrossSegAfterNew );
    7659              : 
    7660              :                                 vrtcsCrossSegBefore.second = newEdgVrtx;
    7661              :                                 vrtcsCrossSegAfter.first = newEdgVrtx;
    7662              :                                 expCFIBeforeFracEdg.setNewNormal( vrtcsCrossSegBefore );
    7663              :                                 expCFIAfterFracEdg.setNewNormal( vrtcsCrossSegAfter );
    7664              : 
    7665              : #endif
    7666              : 
    7667              : //                               vecExpCrossFI[ indBefore ].setNewEdgVertex(newEdgVrtx);
    7668              : //                               vecExpCrossFI[ indAfter ].setNewEdgVertex(newEdgVrtx);
    7669              : 
    7670              : //                               DiamondVertexInfo dviBefore();
    7671              : //                               DiamondVertexInfo dviAfter();
    7672              : 
    7673              :                         }
    7674              : 
    7675              : 
    7676              :                         // create new edges and new faces
    7677              : 
    7678              :                         std::vector<Face*> newFracFaceVec = std::vector<Face*>();
    7679              : 
    7680            0 :                         bool boundAtShiftVrtEdg = true;
    7681              : //                      bool atStartSort = true;
    7682              : 
    7683              :                         // ecf typ: ExpandCrossFracInfo
    7684              : 
    7685            0 :                         for( auto const & ecf : vecExpCrossFI )
    7686              :                         {
    7687              : 
    7688              :                                 // DEBUG ASSERT TEST static_assert( std::is_same< ExpandCrossFracInfo const &, decltype( ecf ) >::value );
    7689              :                                 // get new vertex at the original fracture edge
    7690              : 
    7691              :                                 // extract this functionality to own function
    7692              : 
    7693              : //                              void createNewFacesForExtXCrossFracs( ExpandCrossFracInfo const & ecf,
    7694              : //                                                                                                        std::vector<Face*> & newFracFaceVec,
    7695              : //
    7696              : //                              )
    7697              : 
    7698              : //                              createNewFacesForExtXCrossFracs( ecf, newFracFaceVec, boundAtShiftVrtEdg, atStartSort, sh, grid, crossPt, subdomList );
    7699            0 :                                 createNewFacesForExtXCrossFracs( ecf, newFracFaceVec, boundAtShiftVrtEdg, sh, grid, crossPt, subdomList );
    7700              : 
    7701              : #if 0
    7702              :                                 std::pair<Edge*, Edge*> edgesCrossSeg = ecf.getEdge();
    7703              : 
    7704              :                                 Face * facSeg = ecf.getFace();
    7705              : 
    7706              :                                 std::pair<Vertex*, Vertex*> vertcsCrossSeg = ecf.getNormal();
    7707              : 
    7708              :                                 std::pair<Vertex*, Vertex*> vertcsCrossSegWithNewV = ecf.getNewNormal();
    7709              : 
    7710              : 
    7711              :                                 if( atStartSort || boundAtShiftVrtEdg )
    7712              :                                 {
    7713              :                                         if( vertcsCrossSeg.first != nullptr || vertcsCrossSeg.second == nullptr )
    7714              :                                                 UG_THROW("Verwechslung " << vertcsCrossSeg.first << " " << vertcsCrossSeg.second << std::endl);
    7715              :                                 }
    7716              : 
    7717              :                                 atStartSort = false;
    7718              : 
    7719              :                                 Edge * fracEdge = boundAtShiftVrtEdg ? edgesCrossSeg.first : edgesCrossSeg.second;
    7720              :                                 Edge * shiftVrtEdge = boundAtShiftVrtEdg ?  edgesCrossSeg.second : edgesCrossSeg.first;
    7721              : 
    7722              :                                 Vertex * fracVrtNew =  boundAtShiftVrtEdg ? vertcsCrossSegWithNewV.first : vertcsCrossSegWithNewV.second; // should be nullptr at first segment, to be assigned afterwards / shifted
    7723              :                                 Vertex * shiftVrt = boundAtShiftVrtEdg ? vertcsCrossSeg.second : vertcsCrossSeg.first;
    7724              :                                 Vertex * shiftVrtTest = boundAtShiftVrtEdg ? vertcsCrossSegWithNewV.second : vertcsCrossSegWithNewV.first;
    7725              : 
    7726              :                                 if( shiftVrtTest != shiftVrt )
    7727              :                                         UG_THROW("Shift Vertex verloren gegangen " << std::endl);
    7728              : 
    7729              :                                 IndexType sudoFac = sh.get_subset_index(facSeg);
    7730              : 
    7731              :                                 IndexType sudoFracEdge = sh.get_subset_index(fracEdge);
    7732              : 
    7733              :                                 if( sudoFac != sudoFracEdge )
    7734              :                                 {
    7735              :                                         UG_THROW("subdoms frac edge und face nicht gleich " << std::endl);
    7736              :                                 }
    7737              : 
    7738              :                                 // get all vertices of face, check if both known ones are contained, delete the face, create
    7739              :                                 // the additional needed edge, and create new face with new vertex
    7740              : 
    7741              : 
    7742              :                                 std::vector<Vertex*> vrtcsFace;
    7743              :                                 // assign first old vertices, then replace
    7744              : //                              std::vector<Vertex*> vrtcsNewFaceFrac = vrtcsFace;
    7745              : //                              std::vector<Vertex*> vrtcsNewFaceDiam = vrtcsFace;
    7746              : 
    7747              :                                 //      all new vertices have been assigned to newVrts.
    7748              :                                 //      Note that if newVrts[i] == NULL, then we have to take the
    7749              :                                 //      old vertex sf->vertex(i).
    7750              :                                 //      now expand the fracture edges of sf to faces.
    7751              :                                 for(size_t iVrt = 0; iVrt < facSeg->num_vertices(); iVrt++ )
    7752              :                                 {
    7753              : 
    7754              :                                         Vertex * vrt = facSeg->vertex(iVrt);
    7755              :                                         vrtcsFace.push_back( vrt );
    7756              : //                                      vrtcsNewFaceFrac.push_back( vrt );
    7757              : //                                      vrtcsNewFaceDiam.push_back( vrt );
    7758              :                                 }
    7759              : 
    7760              :                                 std::vector<Vertex*> vrtcsNewFaceFrac = vrtcsFace;
    7761              : //                              std::vector<Vertex*> vrtcsNewFaceDiam = vrtcsFace;
    7762              : 
    7763              : 
    7764              :                                 // check if known vertices are contained
    7765              : 
    7766              :                                 IndexType fraVeNuInd = -1;
    7767              :                                 IndexType shiftVeNuInd = -1;
    7768              : 
    7769              :                                 IndexType cntr = 0;
    7770              : 
    7771              :                                 for( auto const & vf : vrtcsFace )
    7772              :                                 {
    7773              :                                         if( vf == fracVrtNew )
    7774              :                                         {
    7775              :                                                 fraVeNuInd = cntr;
    7776              :                                                 UG_THROW("wie kann man hierher kommen?" << std::endl);
    7777              :                                         }
    7778              : 
    7779              :                                         if( vf == crossPt )
    7780              :                                         {
    7781              :                                                 fraVeNuInd = cntr;
    7782              :                                         }
    7783              : 
    7784              : //
    7785              :                                         if( vf == shiftVrt )
    7786              :                                                 shiftVeNuInd = cntr;
    7787              : 
    7788              :                                         cntr++;
    7789              :                                 }
    7790              : 
    7791              :                                 if( fraVeNuInd < 0 || shiftVeNuInd < 0 )
    7792              :                                         UG_THROW("frac vertex oder shift vertex not contained " << std::endl);
    7793              : 
    7794              :                                 UG_LOG("neuer frac vertex " << fraVeNuInd << " " << shiftVeNuInd << std::endl );
    7795              : 
    7796              :                                 // replace vrtcs
    7797              :                                 vrtcsNewFaceFrac[fraVeNuInd] = fracVrtNew;
    7798              : 
    7799              :                                 // compute shift of center vertex along frac edge
    7800              : 
    7801              :                                 // check subdom of frac vertex and check if in subdom List of X cross
    7802              : 
    7803              :                                 IndexType sudoOther = -1;
    7804              : 
    7805              :                                 IndexType foundSudoOther = 0;
    7806              :                                 IndexType foundSudoFac = 0;
    7807              : 
    7808              :                                 for( auto const & sd : subdomList )
    7809              :                                 {
    7810              :                                         if( sd != sudoFac )
    7811              :                                         {
    7812              :                                                 sudoOther = sd;
    7813              :                                                 foundSudoOther++;
    7814              :                                         }
    7815              :                                         else if( sd == sudoFac )
    7816              :                                         {
    7817              :                                                 foundSudoFac++;
    7818              :                                         }
    7819              :                                         else
    7820              :                                         {
    7821              :                                                 UG_THROW("Sudo not from frac and not from other?" << std::endl);
    7822              :                                         }
    7823              :                                 }
    7824              : 
    7825              :                                 if( foundSudoFac != 1 && foundSudoOther != 1 )
    7826              :                                         UG_THROW("sudo zu oft oder zu selten gefunden " << std::endl);
    7827              : 
    7828              :                                 // establish new edges and new faces
    7829              : 
    7830              :                                 if( vrtcsNewFaceFrac.size() != 4 )
    7831              :                                         UG_LOG("komische Groesse Gesicht " << std::endl);
    7832              : 
    7833              :                                 for( IndexType i = 0; i < vrtcsNewFaceFrac.size(); i++ )
    7834              :                                 {
    7835              :                                         if( vrtcsNewFaceFrac[i] == nullptr )
    7836              :                                         {
    7837              :                                                 UG_THROW("null auf " << i << std::endl);
    7838              :                                         }
    7839              : //                                      else
    7840              : //                                      {
    7841              : //                                              UG_LOG("kein null auf " << i << std::endl );
    7842              : //                                      }
    7843              :                                 }
    7844              : 
    7845              : 
    7846              :                                 UG_LOG("neue Gesichter ausserhalb Diamant Ziel " << std::endl);
    7847              : 
    7848              : //                              int a = 1 + 2;
    7849              : //
    7850              :                                 Face * newFracFace =
    7851              :                                         *grid.create<Quadrilateral>( QuadrilateralDescriptor( vrtcsNewFaceFrac[0], vrtcsNewFaceFrac[1],
    7852              :                                                                                                                                                   vrtcsNewFaceFrac[2], vrtcsNewFaceFrac[3]
    7853              :                                                                                                 ) );
    7854              : 
    7855              :                                 sh.assign_subset(newFracFace, sh.get_subset_index(facSeg) );
    7856              : //                              sh.assign_subset(newFracFace, diamantSubsNum ); testweise
    7857              : 
    7858              :                                 newFracFaceVec.push_back(newFracFace);
    7859              : 
    7860              :                                 boundAtShiftVrtEdg = ! boundAtShiftVrtEdg;
    7861              : #endif
    7862              : 
    7863              :                         }
    7864              : 
    7865              :                         UG_LOG("neue Gesichter ausserhalb Diamant erzeugt " << std::endl);
    7866              : 
    7867              :                         std::vector<Face*> newDiamFaceVec = std::vector<Face*>();
    7868              : 
    7869            0 :                         for( int indC = 0; indC < vecfis-1; indC = indC + 2 )
    7870              :                         {
    7871              : //                              IndexType indBefore = ( indC + vecExpCrossFI.size() ) % vecExpCrossFI.size();
    7872              : //                              IndexType indAfter = ( indC + 1 + vecExpCrossFI.size() ) % vecExpCrossFI.size();
    7873            0 :                                 IndexType indBefore = ( indC + vecfis ) % vecfis;
    7874            0 :                                 IndexType indAfter = ( indC + 1 + vecfis ) % vecfis;
    7875              : 
    7876              : 
    7877            0 :                                 ExpandCrossFracInfo & expCFIBeforeFracEdg = vecExpCrossFI[ indBefore ];
    7878            0 :                                 ExpandCrossFracInfo & expCFIAfterFracEdg = vecExpCrossFI[ indAfter ];
    7879              : 
    7880              :                                 // auslagern
    7881              : 
    7882              : //                              createDiamondFacesXCrossType( ExpandCrossFracInfo & expCFIBeforeFracEdg, ExpandCrossFracInfo & expCFIAfterFracEdg,
    7883              : //                                              std::vector<Face*> newDiamFaceVec )
    7884              : 
    7885              : #if 1
    7886              : //                              createDiamondFacesXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg,
    7887              : //                                              newDiamFaceVec,  sh, grid, diamantSubsNum, crossPt );
    7888              : 
    7889            0 :                                 createDiamondFacesXCrossType( expCFIBeforeFracEdg, expCFIAfterFracEdg,
    7890              :                                                 newDiamFaceVec,  sh, grid, diamantSubsNum, crossPt, useTrianglesInDiamonds );
    7891              : 
    7892              : #else
    7893              :                                 Face * facBefore = expCFIBeforeFracEdg.getFace();
    7894              :                                 Face * facAfter = expCFIAfterFracEdg.getFace();
    7895              : 
    7896              :                                 std::vector<Vertex*> vrtcsFaceBefore;
    7897              :                                 std::vector<Vertex*> vrtcsFaceAfter;
    7898              : 
    7899              : 
    7900              :                                 for(size_t iVrt = 0; iVrt < facBefore->num_vertices(); iVrt++ )
    7901              :                                 {
    7902              :                                         Vertex * vrt = facBefore->vertex(iVrt);
    7903              :                                         vrtcsFaceBefore.push_back( vrt );
    7904              :                                 }
    7905              : 
    7906              :                                 for(size_t iVrt = 0; iVrt < facAfter->num_vertices(); iVrt++ )
    7907              :                                 {
    7908              :                                         Vertex * vrt = facAfter->vertex(iVrt);
    7909              :                                         vrtcsFaceAfter.push_back( vrt );
    7910              :                                 }
    7911              : 
    7912              :                                 Vertex * newVrtBefore = expCFIBeforeFracEdg.getNewNormal().first;
    7913              :                                 Vertex * shiftVrt = expCFIBeforeFracEdg.getNewNormal().second;
    7914              :                                 Vertex * newVrtAfter = expCFIAfterFracEdg.getNewNormal().second;
    7915              : 
    7916              :                                 if(    expCFIBeforeFracEdg.getNewNormal().second != expCFIBeforeFracEdg.getNormal().second
    7917              :                                         || expCFIBeforeFracEdg.getNewNormal().second == nullptr
    7918              :                                         || expCFIBeforeFracEdg.getNewNormal().second != expCFIAfterFracEdg.getNewNormal().first
    7919              :                                         || expCFIAfterFracEdg.getNewNormal().first == nullptr
    7920              :                                         || expCFIAfterFracEdg.getNewNormal().first != expCFIAfterFracEdg.getNormal().first
    7921              :                                 )
    7922              :                                 {
    7923              :                                         UG_THROW("Vektorchaos " << std::endl);
    7924              :                                 }
    7925              : 
    7926              :                                 std::vector<Vertex *> vrtxSmallDiam;
    7927              : 
    7928              :                                 vrtxSmallDiam.push_back( crossPt );
    7929              :                                 vrtxSmallDiam.push_back( newVrtBefore );
    7930              :                                 vrtxSmallDiam.push_back( shiftVrt );
    7931              :                                 vrtxSmallDiam.push_back( newVrtAfter );
    7932              : 
    7933              :                                 Face * newFracFace =
    7934              :                                         *grid.create<Quadrilateral>( QuadrilateralDescriptor( vrtxSmallDiam[0], vrtxSmallDiam[1],
    7935              :                                                                                                                                                   vrtxSmallDiam[2], vrtxSmallDiam[3]
    7936              :                                                                                                 ) );
    7937              : 
    7938              :                                 sh.assign_subset(newFracFace, diamantSubsNum );
    7939              : 
    7940              :                                 newDiamFaceVec.push_back(newFracFace);
    7941              : 
    7942              : #endif
    7943              : 
    7944              :                         }
    7945              : 
    7946              : //                      sh.get_subset_name() XXXXX
    7947              : 
    7948              : //                      auto sunam = sh.get_subset_name(subdomList[0]);
    7949              : //
    7950              : //                      for( auto const & su : subdomList )
    7951              : //                      {
    7952              : //
    7953              : //                      }
    7954              : 
    7955              : //                      using SuNaTyp = decltype( sh.get_subset_name(0) );
    7956              : 
    7957              :                         // DEBUG ASSERT TEST static_assert( std::is_same<char const *, decltype( sh.get_subset_name(subdomList[0]) ) >::value );
    7958              : 
    7959            0 :                         std::string diamNam = std::string("diamant_") + std::string(const_cast<char*>( sh.get_subset_name( subdomList[0] ) ))
    7960            0 :                                                       + std::string("_") + std::string(const_cast<char*>( sh.get_subset_name( subdomList[1] ) ));
    7961              : 
    7962            0 :                         sh.set_subset_name(diamNam.c_str(),diamantSubsNum);
    7963              : 
    7964              :                         // TODO FIXME in extra Funktion packen, vielfach aufgerufen in der Art!
    7965              : 
    7966            0 :                         assignFaceSubsetToClosedFace( newFracFaceVec, grid, sh );
    7967              : 
    7968              : //                      for( auto const & nF : newFracFaceVec )
    7969              : //                      {
    7970              : //                              for(size_t iEdge = 0; iEdge < nF->num_edges(); iEdge++ )
    7971              : //                              {
    7972              : //                                      Edge* edg = grid.get_edge(nF, iEdge);
    7973              : //
    7974              : //                                      sh.assign_subset( edg, sh.get_subset_index(nF) );
    7975              : //
    7976              : //                              }
    7977              : //
    7978              : //                              for( size_t iVrt = 0; iVrt < nF->num_vertices(); iVrt++ )
    7979              : //                              {
    7980              : //                                      Vertex * vrt = nF->vertex(iVrt);
    7981              : //
    7982              : //                                      sh.assign_subset( vrt, sh.get_subset_index(nF) );
    7983              : //                              }
    7984              : //
    7985              : //                      }
    7986              : 
    7987            0 :                         assignFaceSubsetToClosedFace( newDiamFaceVec, grid, sh );
    7988              : 
    7989              : 
    7990              : //                      for( auto const & nF : newDiamFaceVec )
    7991              : //                      {
    7992              : //                              for(size_t iEdge = 0; iEdge < nF->num_edges(); iEdge++ )
    7993              : //                              {
    7994              : //                                      Edge* edg = grid.get_edge(nF, iEdge);
    7995              : //
    7996              : //                                      sh.assign_subset( edg, sh.get_subset_index(nF) );
    7997              : //
    7998              : //                              }
    7999              : //
    8000              : //                              for( size_t iVrt = 0; iVrt < nF->num_vertices(); iVrt++ )
    8001              : //                              {
    8002              : //                                      Vertex * vrt = nF->vertex(iVrt);
    8003              : //
    8004              : //                                      sh.assign_subset( vrt, sh.get_subset_index(nF) );
    8005              : //                              }
    8006              : //
    8007              : //                      }
    8008              : 
    8009              : 
    8010              : #if 0
    8011              :                         // at end delete all fracture edges which are too long
    8012              : 
    8013              :                         for( auto const & fdel : vecExpCrossFI )
    8014              :                         {
    8015              :                                 Face * fac2BeDeleted = fdel.getFace();
    8016              : 
    8017              :                                 if( fac2BeDeleted != nullptr )
    8018              :                                         grid.erase(fac2BeDeleted);
    8019              :                                 else
    8020              :                                         UG_THROW("hier fehlt ein Gesicht " << std::endl);
    8021              :                         }
    8022              : 
    8023              : //                      IndexType subsNumNow = sh.num_subsets();
    8024              : //
    8025              : ////                    IndexType susu = subsNumNow;
    8026              : //
    8027              : ////                    UG_LOG("subs num " << susu << std::endl);
    8028              : //                      UG_LOG("subs num " << subsNumNow << std::endl);
    8029              : //
    8030              :                         for( auto const & edg : allAssoEdgCP )
    8031              :                         {
    8032              : //                              Edge * e2D = oEdg;
    8033              : 
    8034              :                                 if( edg != nullptr )
    8035              :                                 {
    8036              :                                         UG_LOG("will erasieren " << edg << std::endl );
    8037              :                                         grid.erase(edg);
    8038              : 
    8039              : //                                      sh.assign_subset( e2D, subsNumNow );
    8040              : //                                      sh.assign_subset( e2D, subsNumNow );
    8041              :                                 }
    8042              :                                 else
    8043              :                                 {
    8044              :                                         UG_LOG("hier fehlt eine Ecke " << std::endl);
    8045              :                                 }
    8046              :                         }
    8047              : 
    8048              :                         UG_LOG("ALles erasiert " << std::endl);
    8049              : #endif
    8050              : //                      for( auto & afc : assoFacCross )
    8051              : //                      {
    8052              : //                              grid.erase(afc);
    8053              : //                      }
    8054              : //
    8055              : //                      // von den Edges, die vom Schnittknoten ausgehen, die anderen Endvertizes merken, dann edges löschen
    8056              : //
    8057              : //                      std::vector<Edge *> assoEdgCross;
    8058              : //                      std::vector<Vertex *> endVertices;
    8059              : //
    8060              : //                      for( std::vector<Edge *>::iterator iterEdg = grid.associated_edges_begin(crossPt); iterEdg != grid.associated_edges_end(crossPt); iterEdg++ )
    8061              : //                      {
    8062              : //                              assoEdgCross.push_back(*iterEdg);
    8063              : //
    8064              : //                              for( size_t i = 0; i < 2; i++ )
    8065              : //                              {
    8066              : //                                      Vertex * vrtEdgEnd = (*iterEdg)->vertex(i);
    8067              : //
    8068              : //                                      if( vrtEdgEnd != crossPt )
    8069              : //                                      {
    8070              : //                                              endVertices.push_back( vrtEdgEnd );
    8071              : //                                      }
    8072              : //                              }
    8073              : //                      }
    8074              : //
    8075              : //#if 0
    8076              : //                      vector3 shiftPart;
    8077              : //                      VecAdd(shiftPart, fracVrtPos, shiftAlongEdgeTwo);
    8078              : //
    8079              : //                      vector3 posNewVrt;
    8080              : //                      VecAdd( posNewVrt, shiftPart, shiftAlongEdgeOne);
    8081              : //
    8082              : //                      UG_LOG("neuer Vertex Kreuzung " << posNewVrt << std::endl );
    8083              : //
    8084              : //                      Vertex * newShiftVrtx = *grid.create<RegularVertex>();
    8085              : //                      aaPos[newShiftVrtx] = posNewVrt;
    8086              : //
    8087              : //#endif
    8088              : //
    8089              : //                      for( auto & aec : assoEdgCross )
    8090              : //                      {
    8091              : //                              grid.erase(aec);
    8092              : //                      }
    8093              : 
    8094              : 
    8095            0 :                 }
    8096              : 
    8097              : #if 1
    8098            0 :                 for( auto const & fdel : vecExpCrossFI )
    8099              :                 {
    8100              :                         Face * fac2BeDeleted = fdel.getFace();
    8101              : 
    8102            0 :                         if( fac2BeDeleted != nullptr )
    8103            0 :                                 grid.erase(fac2BeDeleted);
    8104              :                         else
    8105            0 :                                 UG_THROW("hier fehlt ein Gesicht " << std::endl);
    8106              :                 }
    8107              : 
    8108            0 :                 if( ! useTrianglesInDiamonds ) // stamdard case
    8109              :                 {
    8110            0 :                         for( auto const & edg : allAssoEdgCP )
    8111              :                         {
    8112            0 :                                 if( edg != nullptr && edg != avoidToDeleteEdge )
    8113              :                                 {
    8114            0 :                                         UG_LOG("will erasieren " << edg << std::endl );
    8115            0 :                                         grid.erase(edg);
    8116              : 
    8117              :                                 }
    8118              :                                 else
    8119              :                                 {
    8120              :                                         UG_LOG("hier fehlt eine Ecke " << std::endl);
    8121              :                                 }
    8122              :                         }
    8123              :                 }
    8124              :                 else
    8125              :                 {
    8126            0 :                         for( auto const & edg : origFracEdg )
    8127              :                         {
    8128            0 :                                 grid.erase(edg);
    8129              :                         }
    8130              :                 }
    8131              : 
    8132              : 
    8133              :                 UG_LOG("ALles erasiert " << std::endl);
    8134              : #endif
    8135            0 :         }
    8136              : 
    8137              : //      grid.detach_from_edges( aAdjVert );
    8138              : 
    8139              :         // die frac vertices entfernen noch
    8140              : 
    8141              : //      for( auto const & cfi : vecCrossVrtInf )
    8142              : //      {
    8143              : //              IndexType nuCroFra =  cfi.getNumbCrossFracs();
    8144              : //
    8145              : //              VecEdge origFracEdg = cfi.getVecOrigFracEdges();
    8146              : //
    8147              : //
    8148              : //              if( nuCroFra == 3 )
    8149              : //              {
    8150              : //
    8151              : //              }
    8152              : //              else if( nuCroFra == 4 )
    8153              : //              {
    8154              : //                      IndexType subsNumNow = sh.num_subsets();
    8155              : //
    8156              : //      //                      IndexType susu = subsNumNow;
    8157              : //
    8158              : //      //                      UG_LOG("subs num " << susu << std::endl);
    8159              : //                      UG_LOG("subs num " << subsNumNow << std::endl);
    8160              : //
    8161              : //                      for( auto const & oEdg : origFracEdg )
    8162              : //                      {
    8163              : //                              Edge * e2D = oEdg;
    8164              : //
    8165              : //                              if( e2D != nullptr )
    8166              : //                              {
    8167              : //      //                                      grid.erase(edg2BeDel);
    8168              : //                                      UG_LOG("will erasieren " << e2D << std::endl );
    8169              : //
    8170              : //                                      sh.assign_subset( e2D, subsNumNow );
    8171              : //      //                                      sh.assign_subset( e2D, subsNumNow );
    8172              : //                              }
    8173              : //                              else
    8174              : //                              {
    8175              : //                                              UG_LOG("hier fehlt eine Ecke " << std::endl);
    8176              : //                              }
    8177              : //                      }
    8178              : //
    8179              : //              }
    8180              : //      }
    8181              : 
    8182              :         UG_LOG("zu Ende gekommen mit Arte 2D" << std::endl);
    8183              : 
    8184              :         return true;
    8185              : 
    8186              :         // ENDE NEUES ZEUG SELEKTION
    8187              : 
    8188              : 
    8189              : 
    8190              : 
    8191              : 
    8192              : 
    8193              : 
    8194              : #if FORMER_PROMESH_FINITE_CLEFT_TECHNIQUE
    8195              :         // TODO FIXME von diesem Loop kann man noch für oben die calculate crease normal lernen, vielleicht minimal abgewandelt, vielleicht exakt gleich
    8196              : 
    8197              :         //      a callback that returns true if the edge is a fracture edge, neues System
    8198              :         AttachmentUnequal<Edge, Grid::EdgeAttachmentAccessor<ABool> > isFracEdgeB(aaMarkEdgeB, false);
    8199              : 
    8200              :         //      iterate over all surrounding faces and create new vertices.
    8201              :         for(FaceIterator iter_sf = sel.faces_begin(); iter_sf != sel.faces_end(); ++iter_sf)
    8202              :         {
    8203              :                 Face* sf = *iter_sf;
    8204              : 
    8205              :         //      check for each vertex whether it lies in the fracture
    8206              :         //      (aaMarkVRT > 1 in this case)
    8207              :         //      if so, we have to copy or create a vertex from/in aaVrtVec[vrt] which is
    8208              :         //      associated with the crease normal on the side of sf.
    8209              :                 for(size_t i_vrt = 0; i_vrt < sf->num_vertices(); ++i_vrt)
    8210              :                 {
    8211              :                         Vertex* vrt = sf->vertex(i_vrt);
    8212              :                         if(aaMarkVRT[vrt] > 1)
    8213              :                         {
    8214              :                         //      calculate the normal on this side of the frac
    8215              :                                 // TODO FIXME so eine Funktion brauchen wir vielleicht oben auch zur Vereinfachung des Codes!!!
    8216              :                                 vector3 n_v2 = CalculateCreaseNormal(grid, sf, vrt, isFracEdgeB, aaPos);
    8217              :                                 // das calculate crease normal scheint mir ein Schwachsinn zu sein
    8218              :                                 // aber vielleicht doch nicht?
    8219              : 
    8220              :                                 UG_LOG("calculated crease normal v2: " << n_v2 << endl);
    8221              : 
    8222              :                 }
    8223              :         }
    8224              : #endif
    8225              : 
    8226              : 
    8227            0 : }
    8228              : 
    8229              : }
    8230              : 
    8231              : 
    8232              : }// end of namespace
    8233              : 
        

Generated by: LCOV version 2.0-1