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

Generated by: LCOV version 2.0-1