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

            Line data    Source code
       1              : /*
       2              :  * ArteExpandFracs3D.cpp
       3              :  *
       4              :  *  Created on: 06.10.2024
       5              :  *      Author: Markus M. Knodel
       6              :  *
       7              :  *  * expand fractures using the Arte algorithm, 3D case
       8              :  *
       9              :  * Author: Markus Knodel, inspired by Arte from Fuchs and Sebastian Reiters code for fracture expansion without Arte
      10              :  *
      11              :  * implementing a class that gives the basic tools for Arte in 3D
      12              :  * might be templated at a later stage to fulfill 2D and 3D purposes, if suitable
      13              :  * ( so far 2D case one entire function, not so perfect, but running....)
      14              :  *
      15              :  *
      16              :  * This file is part of UG4.
      17              :  *
      18              :  * UG4 is free software: you can redistribute it and/or modify it under the
      19              :  * terms of the GNU Lesser General Public License version 3 (as published by the
      20              :  * Free Software Foundation) with the following additional attribution
      21              :  * requirements (according to LGPL/GPL v3 §7):
      22              :  *
      23              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      24              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      25              :  *
      26              :  * (2) The following notice must be displayed at a prominent place in the
      27              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      28              :  *
      29              :  * (3) The following bibliography is recommended for citation and must be
      30              :  * preserved in all covered files:
      31              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      32              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      33              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      34              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      35              :  *   flexible software system for simulating pde based models on high performance
      36              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      37              :  *
      38              :  * This program is distributed in the hope that it will be useful,
      39              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      40              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      41              :  * GNU Lesser General Public License for more details.
      42              :  */
      43              : 
      44              : #include <boost/function.hpp>
      45              : 
      46              : #include "lib_grid/algorithms/geom_obj_util/geom_obj_util.h"
      47              : #include "lib_grid/callbacks/callbacks.h"
      48              : #include "lib_grid/grid/grid_util.h"
      49              : 
      50              : #include <stack>
      51              : #include <utility>
      52              : #include <vector>
      53              : #include <type_traits>
      54              : #include <limits>
      55              : #include <atomic>
      56              : #include <cstddef>
      57              : #include <bitset>
      58              : #include <string>
      59              : #include <cmath>
      60              : 
      61              : #include "support.h"
      62              : #include "support3D.h"
      63              : 
      64              : 
      65              : #include <lib_grid/algorithms/extrusion/ArteExpandFracs3D.h>
      66              : 
      67              : #include "simpleMatrixOps.h"
      68              : 
      69              : #include "DiamondInfo.h"
      70              : 
      71              : namespace ug
      72              : {
      73              : 
      74              : namespace arte
      75              : {
      76              : 
      77            0 : ArteExpandFracs3D::ArteExpandFracs3D(
      78              :                 Grid & grid, SubsetHandler & sh,
      79              :             std::vector<FractureInfo> const & fracInfos,
      80            0 :                 bool useTrianglesInDiamonds, bool establishDiamonds )
      81            0 :         : m_grid(grid),
      82            0 :           m_sh(sh),
      83            0 :           m_fracInfos(fracInfos),
      84            0 :           m_useTrianglesInDiamonds(useTrianglesInDiamonds),
      85            0 :           m_establishDiamonds(establishDiamonds),
      86              :           m_aaPos(Grid::VertexAttachmentAccessor<APosition>()),
      87              : //        m_facDescr(FaceDescriptor()),
      88              : //        m_volDescr(VolumeDescriptor()),
      89              :           m_fracInfosBySubset(std::vector<FractureInfo>()),
      90              :           //m_sel(Selector()),
      91              :           m_aAdjMarkerVFP(AttVertFracProp()),
      92              :           m_aaMarkVrtVFP( Grid::VertexAttachmentAccessor<AttVertFracProp>()),
      93              : //        m_aAdjMarkerVFP(AttVertFracProp()),
      94              :           m_aaMarkEdgeVFP(Grid::EdgeAttachmentAccessor<AttVertFracProp>()),
      95              :           m_aAdjMarkerFaceIsFracB(ABool()),
      96              :           m_aaMarkFaceIsFracB(Grid::FaceAttachmentAccessor<ABool>()),
      97              : //        m_aaMarkFaceHasUnclosedFracSideB(Grid::FaceAttachmentAccessor<ABool>()),
      98              : //        m_aAdjMarkerVrtxHasUnclosedFracB(ABool()),
      99              : //        m_aaMarkVrtxHasUnclosedFracB(Grid::VertexAttachmentAccessor<ABool>()),
     100              :           m_aAdjMarkerFaceWithEndingCrossingCleft(ABool()),
     101              :           m_aaMarkFaceWithEndingCrossingCleft(Grid::FaceAttachmentAccessor<ABool>()),
     102              :           m_aAdjMarkerVrtxAtEndingCrossingCleft(ABool()),
     103              :           m_aaMarkVrtxAtEndingCrossingCleft(Grid::VertexAttachmentAccessor<ABool>()),
     104              : //        m_aAdjMarkerVrtx2AtInnerEndOfEndingCrossingFract(ABool()),
     105              : //        m_aaMarkVrtx2AtInnerEndOfEndingCrossingFract(Grid::VertexAttachmentAccessor<ABool>()),
     106            0 :           m_needToSplitEdgesConnectingNeighbrdEndingCrossCleftVrtx(false),
     107              :           m_originalFractureFaces(std::vector<Face*>()),
     108              : //        m_attVrtVec(AttVrtVec()),
     109              : //        m_aaVrtVecVol( Grid::VolumeAttachmentAccessor<AttVrtVec>() ),
     110              :           m_aAdjInfoEdges(AttVecEdge()),
     111              :           m_aAdjInfoFaces(AttVecFace()),
     112              : //        m_aAdjInfoVols(AttVecVol()),
     113              :           m_aaVrtInfoAssoEdges( Grid::VertexAttachmentAccessor<AttVecEdge>()),
     114              :           m_aaVrtInfoAssoFaces( Grid::VertexAttachmentAccessor<AttVecFace>()),
     115              : //        m_aaVrtInfoAssoVols( Grid::VertexAttachmentAccessor<AttVecVol>()),
     116              : //        m_aAdjInfoAVVFT( AttVecVertFracTrip() ),
     117              : //        m_aaVrtInfoFraTri(Grid::VertexAttachmentAccessor<AttVecVertFracTrip>()),
     118              : //        m_vrtxFractrQuadrplVec(VrtxFractrQuadrplArte3DVec())
     119              :           m_attVrtVec(AttVrtVec()),
     120              :           m_aaVrtVecVol( Grid::VolumeAttachmentAccessor<AttVrtVec>() ),
     121              :           m_vecCrossVrtInf(std::vector<CrossVertInf>()),
     122              : //        m_aAdjVolElmInfo(AttVecAttachedVolumeElemInfo()),
     123              : //        m_aaVolElmInfo(Grid::VertexAttachmentAccessor<AttVecAttachedVolumeElemInfo>()),
     124              :           m_attAdjVecSegVolElmInfo( AttVecSegmentVolElmInfo() ),
     125              :           m_accsAttVecSegVolElmInfo( Grid::VertexAttachmentAccessor<AttVecSegmentVolElmInfo>() ),
     126              :           m_attVecSegmLimSid(AttVecSegmLimSid()),
     127              :           m_vrtxAttAccsVecSegmLimSid(Grid::VertexAttachmentAccessor<AttVecSegmLimSid>()),
     128              :           m_vecEdgeDirectConnectingEndingCrossCleftVrtcs( std::vector<Edge* >() ),
     129              :           m_vecEndCrossFractSegmInfo( VecEndingCrossingFractureSegmentInfo() ),
     130              : //        m_vecEndCrossFractSegmInfo(VecEndingCrossingFractureSegmentInfo()),
     131              :           m_attAtVrtxVecEndingCrossFractSegmInfo(AttVecEndingCrossingFractureSegmentInfo()),
     132              :           m_vrtxAttAccsVecEndingCrossFractSegmInfo(Grid::VertexAttachmentAccessor<AttVecEndingCrossingFractureSegmentInfo>()),
     133              : //        m_attAtVrtxIfVrtxIsEndingCrossingCleftVrtx(ABool()),
     134              : //        m_vrtxAttAccsVrtxIsEndingCrossingCleftVrtx(Grid::VertexAttachmentAccessor<ABool>()),
     135              :           m_attAtFaceIfFaceIsSegmLimFaceEndingCrossingCleft(ABool()),
     136              :           m_facAttAccsIfFaceIsSegmLimFaceEndingCrossingCleft(Grid::FaceAttachmentAccessor<ABool>()),
     137              :           m_attAtVolIfVolTouchesEndingCrossingCleft(ABool()),
     138              :           m_volAttAccsVolTouchesEndingCrossingCleft(Grid::VolumeAttachmentAccessor<ABool>()),
     139              :           m_attAtVrtxIfVrtxArisesFromExpandedEndingCrossingCleft(ABool()),
     140              :           m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft(Grid::VertexAttachmentAccessor<ABool>()),
     141              :           m_vrtxArisesFromExpandedEndingCrossingCleft(std::vector<Vertex*>()),
     142            0 :           m_allowedSqueeze(0.9),
     143              :           m_vrtcsViolatingExpansion(std::vector<Vertex*>()),
     144              :           m_volsViolatingExpansion(std::vector<Volume*>()),
     145            0 :           m_vecVolManifVrtxCombiToShrink4Diams(VecVolManifVrtxCombi())
     146              : //        m_diamInfos3D(std::vector<DiamantInfo3D>()),
     147              : //        m_oldNewVrtcs4Diams(std::vector<VrtxPair>())
     148              : {
     149              : //      // Notloesung, nicht in die erste Initialisierung vor geschweifter Klammer, da copy constructor privat
     150            0 :         m_sel = Selector();
     151            0 : }
     152              : 
     153              : 
     154            0 : ArteExpandFracs3D::~ArteExpandFracs3D()
     155              : {
     156              :         //  Auto-generated destructor stub
     157            0 : }
     158              : 
     159            0 : bool ArteExpandFracs3D::run( bool & needToRestart )
     160              : {
     161            0 :         needToRestart = false;
     162              : 
     163              : //      if( ! m_establishDiamonds )
     164              : //      {
     165              : //              UG_LOG("NO DIAMS " << std::endl);
     166              : //      }
     167              : 
     168            0 :         if( ! initialize() )
     169              :                 return false;
     170              : 
     171              :         UG_LOG("initialisiert" << std::endl);
     172              : 
     173            0 :         if( ! setSelector() )
     174              :                 return false;
     175              : 
     176              :         UG_LOG("selektiert" << std::endl);
     177              : 
     178            0 :         if( ! attachMarkers() )
     179              :                 return false;
     180              : 
     181              :         UG_LOG("attached" << std::endl);
     182              : 
     183            0 :         int splittedEdges = splitInnerFreeFracEdgs();
     184              : 
     185            0 :         UG_LOG("splitted edges " << splittedEdges << std::endl);
     186              : //
     187              : //      return false;
     188              : //
     189              : //      UG_LOG("Splitted inner free frac edges" << splittedEdges << std::endl);
     190              : 
     191            0 :         if( ! countAndSelectFracBaseNums() )
     192              :                 return false;
     193              : 
     194              :         UG_LOG("gezaehlt" << std::endl);
     195              : 
     196              : //      constexpr bool assignFracInfosFirst = true;
     197              : //
     198              : //      if( assignFracInfosFirst )
     199              : //      {
     200            0 :         if( ! assignOrigFracInfos() )
     201              :                 return false;
     202              : 
     203              :         UG_LOG("assigniert zuerst " << std::endl);
     204              : 
     205            0 :         if( ! enableVolOptAutoGenFac() )
     206              :         {
     207              :                 UG_LOG("autogen war schon eingestellt" << std::endl);
     208              :         }
     209              :         else
     210              :         {
     211              :                 UG_LOG("Autogen einstellen" << std::endl);
     212              :         }
     213              :         // TODO FIXME für was gebraucht????
     214              : 
     215              : //      }
     216              : 
     217              : //      constexpr bool generVrtInfoFirst = true;
     218              : //
     219              : //      if( generVrtInfoFirst )
     220              : //      {
     221              : //      if( ! generateVertexInfos() )
     222              : //              return false;
     223              : //
     224              : //      UG_LOG("generiert zuerst " << std::endl);
     225              : 
     226              : //      }
     227              : 
     228              : //      if( ! prepareStasi() )
     229              : //              return false;
     230              : //
     231              : //      UG_LOG("Stasi vorbereitet " << std::endl);
     232              : 
     233            0 :         if( ! distinguishSegments() )
     234              :                 return false;
     235              : 
     236              :         UG_LOG("Segmente erzeugt " << std::endl);
     237              : 
     238              : 
     239              :         UG_LOG("check unclosed frac faces" << std::endl);
     240              : 
     241            0 :         if( ! establishSegmentLimitingSidesInfo() )
     242              :                 return false;
     243              : 
     244              :         UG_LOG("established Segment limiting sides info" << std::endl);
     245              : 
     246            0 :         if( ! detectEndingCrossingCleftsSegmBased() )
     247              :         {
     248            0 :                 if( m_needToSplitEdgesConnectingNeighbrdEndingCrossCleftVrtx )
     249              :                 {
     250            0 :                         needToRestart = true;
     251              :                         UG_LOG("Restart due to splitted edges" << std::endl);
     252              :                 }
     253              :                 else
     254              :                 {
     255            0 :                         needToRestart = false;
     256              :                         UG_LOG("No need to restart due to splitted edges" << std::endl);
     257              :                 }
     258              : 
     259            0 :                 return false;
     260              :         }
     261              : 
     262              :         UG_LOG("Ending crossing clefts detected" << std::endl);
     263              : 
     264            0 :         if( ! seletForSegmented() )
     265              :                 return false;
     266              : 
     267              :         UG_LOG("Closed Open Vertex Fract untersucht " << std::endl);
     268              : 
     269              : //      if( ! assignFracInfosFirst )
     270              : //      {
     271              : //              if( ! assignOrigFracInfos() )
     272              : //                      return false;
     273              : //
     274              : //              UG_LOG("assigniert danach " << std::endl);
     275              : //
     276              : //      }
     277              : 
     278              : 
     279            0 :         if( ! establishNewVrtBase() )
     280              :                 return false;
     281              : 
     282              :         UG_LOG("etabliert" << std::endl);
     283              : 
     284              : //      if( ! generVrtInfoFirst )
     285              : //      {
     286              : //
     287              : //              if( ! generateVertexInfos() )
     288              : //                      return false;
     289              : //
     290              : //              UG_LOG("generiert danach " << std::endl);
     291              : //      }
     292              : 
     293            0 :         if( ! createConditionForNewVrtcs() )
     294              :                 return false;
     295              : 
     296              :         UG_LOG("kreiert" << std::endl);
     297              : 
     298            0 :         if( ! loop2EstablishNewVertices() )
     299              :                 return false;
     300              : 
     301              :         UG_LOG("loopiert" << std::endl);
     302              : 
     303              :         UG_LOG("under construction " << std::endl);
     304              : 
     305            0 :         if( ! createNewElements() )
     306              :                 return false;
     307              : 
     308              :         UG_LOG("new elements created " << std::endl);
     309              : 
     310            0 :         if( ! detachMarkers() )
     311              :                 return false;
     312              : 
     313              :         UG_LOG("detachiert" << std::endl);
     314              : 
     315              : //      assignDebugSubsets( false );
     316              : 
     317              :         UG_LOG("Debug subsets assigned" << std::endl );
     318              : 
     319            0 :         IndexType numDelEndCrossCleftFacs = deleteEndingCrossingCleftOrigFacs();
     320              : 
     321              :         UG_LOG("deleted ending crossing cleft changed faces and direction edges " << numDelEndCrossCleftFacs << std::endl);
     322              : 
     323            0 :         if( m_establishDiamonds )
     324              :         {
     325            0 :                 if( ! createTheDiamonds() )
     326              :                 {
     327              :                         UG_LOG("Diamond creation failed " << std::endl);
     328            0 :                         return false;
     329              : //                      UG_THROW("Diamonds not creatable" << std::endl);
     330              :                 }
     331              :         }
     332              : 
     333              :         UG_LOG("diamonds created if desired")
     334              : 
     335            0 :         return true;
     336              : }
     337              : 
     338              : ////////////////////////////////////////////////
     339              : 
     340            0 : bool ArteExpandFracs3D::splitEdgesOfNeighboredEndingCrossingFracVrtcs()
     341              : {
     342              : //      IndexType numberSplittedEdges = 0;
     343              : 
     344              :         // TODO FIXME vergleichen, was bei den debug Ecken alles an Randvertizes ist, und was bei
     345              :         // den hochstehenden Edges für Randvertizes sind, ob da was verloren gegangen ist
     346              :         // oder ob bei den modernen SegmentEnding Infos was fehlt an Vertizes.....
     347              :         // angefangen mit dem simplen Beispiel!
     348              :         // wenn das klappt, können die debug m_d_ Variablen entfernt werden.....
     349              : 
     350              :         UG_LOG("NUMBER EDGES DIRECT " << m_vecEdgeDirectConnectingEndingCrossCleftVrtcs.size() << std::endl );
     351              : 
     352              :         UG_LOG("NUMBER VERTICES FRAC SEGMENTS " << m_vecEndCrossFractSegmInfo.size() << std::endl );
     353              : 
     354            0 :         for( Edge * edg : m_vecEdgeDirectConnectingEndingCrossCleftVrtcs )
     355              :         {
     356              : 
     357            0 :                 UG_LOG("trying to split edge " << CalculateCenter( edg, m_aaPos ) << std::endl);
     358              : 
     359            0 :                 UG_LOG("E VERTEX ONE " << m_aaPos[ edg->vertex(0) ] << std::endl);
     360            0 :                 UG_LOG("E VERTEX TWO " << m_aaPos[ edg->vertex(1) ] << std::endl);
     361              : 
     362            0 :                 for( EndingCrossingFractureSegmentInfo const & ecfsiOne : m_vecEndCrossFractSegmInfo )
     363              :                 {
     364              :                         Vertex * vrtOne = ecfsiOne.spuckUnclosedVrtx();
     365              : 
     366            0 :                         UG_LOG("V ONE " << m_aaPos[vrtOne] << std::endl);
     367              : 
     368            0 :                         for( EndingCrossingFractureSegmentInfo const & ecfsiTwo : m_vecEndCrossFractSegmInfo )
     369              :                         {
     370              :                                 Vertex * vrtTwo = ecfsiTwo.spuckUnclosedVrtx();
     371              : 
     372            0 :                                 UG_LOG("V TWO " << m_aaPos[vrtTwo] << std::endl);
     373              : 
     374            0 :                                 if( vrtOne != vrtTwo )
     375              :                                 {
     376            0 :                                         if( EdgeContains(edg, vrtOne) && EdgeContains( edg, vrtTwo) )
     377              :                                         {
     378              :                                                 UG_LOG("Edge needs to be splitted" << std::endl);
     379              : 
     380            0 :                                                 int suse = m_sh.num_subsets();
     381              : 
     382            0 :                                                 m_sh.assign_subset( edg, suse );
     383              : 
     384              :                                                 UG_LOG("need to detach markers" << std::endl);
     385            0 :                                                 detachMarkers();
     386              : 
     387            0 :                                                 vector3 center = CalculateCenter(edg, m_aaPos);
     388            0 :                                                 UG_LOG("splitting ECCV edge at " << center << std::endl);
     389            0 :                                                 RegularVertex* vrtSE = SplitEdge<RegularVertex>(m_grid, edg, false);
     390              :                                                 m_aaPos[vrtSE] = center;
     391              : 
     392              :                                                 UG_LOG("Edge splitted, please restart process with the thus changed geometry" << std::endl);
     393              : 
     394              :                                                 return true;
     395              : 
     396              :                                         }
     397              : 
     398              :                                 }
     399              : 
     400              :                         }
     401              : 
     402              : 
     403              :                 }
     404              :         }
     405              : 
     406              :         return false;
     407              : 
     408              : //      if( numberSplittedEdges > 0 )
     409              : //              UG_LOG("Edge splitted, please restart process with the thus changed geometry, new edges " << numberSplittedEdges << std::endl);
     410              : //
     411              : //      return numberSplittedEdges;
     412              : 
     413              :         // TODO FIXME das ganze nochmal mit dem Debug Zeug
     414              : 
     415              : //      UG_LOG("DEBUG" << std::endl);
     416              : //
     417              : //      int suse = m_sh.num_subsets();
     418              : //
     419              : //      for( Edge * edg : m_d_allContributingEdges )
     420              : //      {
     421              : //              UG_LOG("E VERTEX ONE " << m_aaPos[ edg->vertex(0) ] << std::endl);
     422              : //              UG_LOG("E VERTEX TWO " << m_aaPos[ edg->vertex(1) ] << std::endl);
     423              : //
     424              : //              for( Vertex * vrtOne : m_d_endingCrossingCleftVrtcs )
     425              : //              {
     426              : //                      UG_LOG("V ONE " << m_aaPos[vrtOne] << std::endl);
     427              : //
     428              : //                      for( Vertex * vrtTwo : m_d_endingCrossingCleftVrtcs )
     429              : //                      {
     430              : //
     431              : //                              UG_LOG("V Two " << m_aaPos[vrtTwo] << std::endl);
     432              : //
     433              : //                              if( vrtOne != vrtTwo )
     434              : //                              {
     435              : //                                      if( EdgeContains(edg, vrtOne) && EdgeContains( edg, vrtTwo) )
     436              : //                                      {
     437              : //                                              UG_LOG("Edge needs to be splitted" << std::endl);
     438              : //
     439              : //                                              m_sh.assign_subset( edg, suse );
     440              : //
     441              : //                                              vector3 center = CalculateCenter(edg, m_aaPos);
     442              : //                                              UG_LOG("splitting ECCV edge at " << center << std::endl);
     443              : //                                              RegularVertex* vrtSE = SplitEdge<RegularVertex>(m_grid, edg, false);
     444              : //                                              m_aaPos[vrtSE] = center;
     445              : //
     446              : //                                              UG_LOG("Edge splitted, please restart process with the thus changed geometry" << std::endl);
     447              : //
     448              : //                                              return 1;
     449              : //
     450              : //                                      }
     451              : //                              }
     452              : //                      }
     453              : //
     454              : //              }
     455              : //      }
     456              : //
     457              : //      return 0;
     458              : //
     459              : //      return false;
     460              : 
     461              : }
     462              : 
     463              : ////////////////////////////////////////////////
     464              : 
     465            0 : void ArteExpandFracs3D::assignDebugSubsets( bool intermediate )
     466              : {
     467              : //      return;
     468              : 
     469              :         std::vector<Face*> d_endingCrossingCleftFaces;
     470              :         std::vector<Face*> d_endingCrossingCleftFacesNoCut;
     471              :         std::vector<Vertex*> d_endingCrossingCleftVrtcs;
     472              :         std::vector<Edge*> d_cuttingEdges;
     473              :         std::vector<Edge*> d_shiftEdges;
     474              :         std::vector<Face*> d_crossingNeighboredNotEndingFaces;
     475              :         std::vector<Face*> d_crossingNeighboredNotEndingFacesCommEdg;
     476              :         std::vector<Face*> d_notEndingCrossingFacesNotNeighbour;
     477              :         std::vector<Volume*> d_vols;
     478              :         std::vector<Vertex*> d_shiftVrtcs;
     479              : 
     480              :         UG_LOG("Number ending crossing clefts " << m_vecEndCrossFractSegmInfo.size()  << std::endl);
     481              : 
     482            0 :         for( EndingCrossingFractureSegmentInfo const & ecfsi : m_vecEndCrossFractSegmInfo )
     483              :         {
     484            0 :                 Vertex * vrt = ecfsi.spuckUnclosedVrtx();
     485              : 
     486            0 :                 d_endingCrossingCleftVrtcs.push_back(vrt);
     487              : 
     488              :                 std::vector<Face*> vecClosFracFacNoNeig = ecfsi.spuckVecClosedFracManifElNoNeighbr();
     489              : 
     490            0 :                 for( Face * fac : vecClosFracFacNoNeig )
     491              :                 {
     492            0 :                         d_crossingNeighboredNotEndingFaces.push_back(fac);
     493              :                 }
     494              : 
     495            0 :                 Face * endingFacCut = ecfsi.spuckEndingFractManifCutting();
     496              : 
     497            0 :                 d_endingCrossingCleftFaces.push_back(endingFacCut);
     498              : 
     499            0 :                 for( Face * endingFacNoCut : ecfsi.spuckVecEndingFractManifNotCutting() )
     500              :                 {
     501            0 :                         if( endingFacNoCut != nullptr )
     502              :                         {
     503            0 :                                 d_endingCrossingCleftFacesNoCut.push_back(endingFacNoCut);
     504              :                         }
     505            0 :                 }
     506              : 
     507            0 :                 Edge * cutEdge = ecfsi.spuckOldLowDimElCut();
     508              : 
     509            0 :                 d_cuttingEdges.push_back(cutEdge);
     510              : 
     511            0 :                 std::pair<Face*,Face*> const & neighrdFacsClos = ecfsi.spuckPairNeighbouredFractClosedManifEl();
     512              : 
     513            0 :                 d_crossingNeighboredNotEndingFacesCommEdg.push_back(neighrdFacsClos.first);
     514            0 :                 d_crossingNeighboredNotEndingFacesCommEdg.push_back(neighrdFacsClos.second);
     515              : 
     516              :                 std::vector<Volume*> vols = ecfsi.spuckVecFulldimEl();
     517              : 
     518            0 :                 for( Volume * v : vols )
     519              :                 {
     520            0 :                         d_vols.push_back(v);
     521              :                 }
     522              : 
     523            0 :                 Edge * shiftEdge = ecfsi.spuckLowdimElmShiftDirection();
     524            0 :                 d_shiftEdges.push_back(shiftEdge);
     525              : 
     526              : 
     527            0 :                 if( ! intermediate )
     528              :                 {
     529            0 :                         Vertex * shiVe = ecfsi.spuckShiftVrtx();
     530              : 
     531            0 :                         if( shiVe == nullptr )
     532              :                         {
     533            0 :                                 m_sh.assign_subset(vrt, m_sh.num_subsets());
     534            0 :                                 m_sh.assign_subset(shiftEdge, m_sh.num_subsets());
     535              : 
     536              :                                 UG_LOG("no shift vertex for ending crossing cleft segment " << std::endl);
     537            0 :                                 UG_THROW("no shift vertex for ending crossing cleft segment " << std::endl);
     538              : 
     539              :                         }
     540            0 :                         d_shiftVrtcs.push_back(shiVe);
     541              :                 }
     542              : 
     543              : 
     544              : 
     545            0 :         }
     546              : 
     547            0 :         int suse = m_sh.num_subsets();
     548              : 
     549            0 :         if( ! intermediate )
     550              :         {
     551              : 
     552            0 :                 for( Face * fac : d_endingCrossingCleftFaces )
     553              :                 {
     554            0 :                         if( fac != nullptr )
     555            0 :                                 m_sh.assign_subset( fac, suse );
     556              : 
     557              :                 }
     558              : 
     559            0 :                 suse = m_sh.num_subsets();
     560              : 
     561            0 :                 for( Face * fac : d_endingCrossingCleftFacesNoCut )
     562              :                 {
     563            0 :                         if( fac != nullptr )
     564            0 :                                 m_sh.assign_subset( fac, suse );
     565              : 
     566              :                 }
     567              : 
     568            0 :                 suse = m_sh.num_subsets();
     569              : 
     570            0 :                 for( Vertex * vrt : d_endingCrossingCleftVrtcs )
     571              :                 {
     572            0 :                         if( vrt != nullptr )
     573            0 :                                 m_sh.assign_subset( vrt, suse );
     574              :                 }
     575              : 
     576            0 :                 suse = m_sh.num_subsets();
     577              : 
     578            0 :                 for( Edge * edg : d_cuttingEdges )
     579              :                 {
     580            0 :                         if( edg == nullptr )
     581              :                         {
     582              :                                 UG_LOG("NULL UNERLAUBT" << std::endl);
     583            0 :                                 UG_THROW("NULL UNERLAUBT" << std::endl);
     584              :                         }
     585              : 
     586            0 :                         m_sh.assign_subset( edg, suse );
     587              : 
     588              :                 }
     589              : 
     590            0 :                 suse = m_sh.num_subsets();
     591              : 
     592            0 :                 for( Edge * edg : d_shiftEdges )
     593              :                 {
     594            0 :                         if( edg == nullptr )
     595              :                         {
     596              :                                 UG_LOG("NULL UNERLAUBT" << std::endl);
     597            0 :                                 UG_THROW("NULL UNERLAUBT" << std::endl);
     598              :                         }
     599              : 
     600            0 :                         m_sh.assign_subset( edg, suse );
     601              : 
     602              :                 }
     603              : 
     604              : 
     605            0 :                 suse = m_sh.num_subsets();
     606              : 
     607            0 :                 for( Face * fac : d_crossingNeighboredNotEndingFaces )
     608              :                 {
     609            0 :                         if( fac != nullptr )
     610            0 :                                 m_sh.assign_subset( fac, suse );
     611              :                 }
     612              : 
     613            0 :                 suse = m_sh.num_subsets();
     614              : 
     615            0 :                 for( Face * fac : d_notEndingCrossingFacesNotNeighbour )
     616              :                 {
     617            0 :                         m_sh.assign_subset( fac, suse );
     618              :                 }
     619              : 
     620            0 :                 suse = m_sh.num_subsets();
     621              : 
     622            0 :                 for( Face * fac : d_crossingNeighboredNotEndingFacesCommEdg )
     623              :                 {
     624            0 :                         m_sh.assign_subset( fac, suse );
     625              :                 }
     626              : 
     627            0 :                 suse = m_sh.num_subsets();
     628              : 
     629            0 :                 for( Vertex * vrtx : d_shiftVrtcs )
     630              :                 {
     631            0 :                         if( vrtx != nullptr )
     632            0 :                                 m_sh.assign_subset( vrtx, suse );
     633              :                 }
     634              : 
     635              : //      suse = m_sh.num_subsets();
     636              :         }
     637              :         else
     638              :         {
     639              : 
     640            0 :                 for( Volume * v : d_vols )
     641              :                 {
     642            0 :                         if( v != nullptr )
     643            0 :                                 m_sh.assign_subset( v, suse );
     644              :                 }
     645              :         }
     646              : 
     647            0 :         return;
     648              : 
     649              : #if 0
     650              : //      if( numEndingCrossingClefts == 0 )
     651              : //              return true;
     652              : 
     653              :         // debug for ending crossing clefts
     654              : 
     655              :         suse = m_sh.num_subsets();
     656              : 
     657              :         for( Face * fac : m_d_endingCrossingCleftFaces )
     658              :         {
     659              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
     660              :                 m_sh.assign_subset( fac, suse );
     661              : 
     662              :         }
     663              : 
     664              :         suse = m_sh.num_subsets();
     665              : 
     666              :         for( Vertex * vrt : m_d_endingCrossingCleftVrtcs )
     667              :         {
     668              : //              m_sh.assign_subset( vrt, m_sh.num_subsets());
     669              :                 m_sh.assign_subset( vrt, suse );
     670              :         }
     671              : 
     672              :         suse = m_sh.num_subsets();
     673              : 
     674              :         for( Edge * edg : m_d_cuttingEdges )
     675              :         {
     676              :                 if( edg == nullptr )
     677              :                 {
     678              :                         UG_LOG("NULL UNERLAUBT" << std::endl);
     679              :                         UG_THROW("NULL UNERLAUBT" << std::endl);
     680              :                 }
     681              : 
     682              : //              m_sh.assign_subset( edg, m_sh.num_subsets());
     683              :                 m_sh.assign_subset( edg, suse );
     684              : 
     685              :         }
     686              : 
     687              :         suse = m_sh.num_subsets();
     688              : 
     689              :         for( Face * fac : m_d_crossingNeighboredNotEndingFaces )
     690              :         {
     691              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
     692              :                 m_sh.assign_subset( fac, suse );
     693              :         }
     694              : 
     695              : //      for( Edge * edg : otherEdgeOfCrossingNotEndingFace )
     696              : //      {
     697              : //              if( edg == nullptr )
     698              : //              {
     699              : //                      UG_LOG("NULL C UNERLAUBT" << std::endl);
     700              : //                      UG_THROW("NULL C UNERLAUBT" << std::endl);
     701              : //              }
     702              : //
     703              : //              m_sh.assign_subset( edg, m_sh.num_subsets());
     704              : //
     705              : //      }
     706              :         suse = m_sh.num_subsets();
     707              : 
     708              :         for( Face * fac : m_d_notEndingCrossingFacesNotNeighbour )
     709              :         {
     710              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
     711              :                 m_sh.assign_subset( fac, suse );
     712              :         }
     713              : 
     714              :         suse = m_sh.num_subsets();
     715              : 
     716              :         for( Face * fac : m_d_crossingNeighboredNotEndingFacesCommEdg )
     717              :         {
     718              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
     719              :                 m_sh.assign_subset( fac, suse );
     720              :         }
     721              : 
     722              : //      suse = m_sh.num_subsets();
     723              : //
     724              : //      for( Edge * edg : m_d_allContributingEdges )
     725              : //      {
     726              : //              for( Vertex * vrtOne : m_d_endingCrossingCleftVrtcs )
     727              : //              {
     728              : //                      for( Vertex * vrtTwo : m_d_endingCrossingCleftVrtcs )
     729              : //                      {
     730              : //                              if( vrtOne != vrtTwo )
     731              : //                              {
     732              : //                                      if( EdgeContains(edg, vrtOne) && EdgeContains( edg, vrtTwo) )
     733              : //                                      {
     734              : //                                              UG_LOG("Edge needs to be splitted" << std::endl);
     735              : //
     736              : //                                              m_sh.assign_subset( edg, suse );
     737              : //
     738              : //
     739              : ////                                            vector3 center = CalculateCenter(edg, m_aaPos);
     740              : ////                                            UG_LOG("splitting ECCV edge at " << center << std::endl);
     741              : ////                                            RegularVertex* vrtSE = SplitEdge<RegularVertex>(m_grid, edg, false);
     742              : ////                                            m_aaPos[vrtSE] = center;
     743              : //
     744              : //                                      }
     745              : //                              }
     746              : //                      }
     747              : //
     748              : //              }
     749              : //      }
     750              : 
     751              : 
     752              :         return;
     753              : #endif
     754              : 
     755              : //      return false;
     756            0 : }
     757              : 
     758              : ////////////////////////////////////////////////
     759              : 
     760            0 : bool ArteExpandFracs3D::initialize()
     761              : {
     762              :         UG_LOG("initialize " << std::endl);
     763              : 
     764              :         //      access position attachment
     765            0 :         if(!m_grid.has_vertex_attachment(aPosition) )
     766              :         {
     767              :                 UG_LOG("Error in ExpandFractures Arte 3D: Missing position attachment");
     768            0 :                 return false;
     769              :         }
     770              : 
     771            0 :         m_aaPos = Grid::VertexAttachmentAccessor<APosition>(m_grid, aPosition);
     772              : 
     773              :         //      make sure that the required options are enabled.
     774              : 
     775            0 :         if( ! m_grid.option_is_enabled(VOLOPT_AUTOGENERATE_FACES) )
     776              :         {
     777              :                 UG_LOG("WARNING in Arte 3D init : grid option VOLOPT_AUTOGENERATE_FACES autoenabled.\n");
     778            0 :                 m_grid.enable_options(VOLOPT_AUTOGENERATE_FACES);
     779              :         }
     780              : 
     781            0 :         if( ! m_grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES) )
     782              :         {
     783              :                 UG_LOG("WARNING in Arte 3D init: grid option FACEOPT_AUTOGENERATE_EDGES autoenabled.\n");
     784            0 :                 m_grid.enable_options(FACEOPT_AUTOGENERATE_EDGES);
     785              :         }
     786              : 
     787              :         //      vectors that allow to access fracture properties by subset index
     788            0 :         m_fracInfosBySubset = std::vector<FractureInfo>( m_sh.num_subsets(), FractureInfo(-1, -1, 0) );
     789              : 
     790            0 :         for( size_t i = 0; i < m_fracInfos.size(); ++i)
     791              :         {
     792            0 :                 if( m_fracInfos[i].subsetIndex >= m_sh.num_subsets())
     793              :                 {
     794            0 :                         throw(UGError("Bad subsetIndex in given fracInfos."));
     795              :                 }
     796              : 
     797            0 :                 m_fracInfosBySubset[ m_fracInfos[i].subsetIndex] = m_fracInfos[i];
     798              : 
     799              :         }
     800              : 
     801              : 
     802              :         return true;
     803              : }
     804              : 
     805              : 
     806            0 : bool ArteExpandFracs3D::setSelector()
     807              : {
     808              :         //      Collect surrounding volumes, faces and edges of all fractures in a selector
     809              :         //      and select fracture faces, edges and vertices too.
     810              : 
     811              : //      m_sel = Selector(m_grid);
     812              : 
     813            0 :         m_sel.assign_grid(m_grid);
     814              : 
     815            0 :         m_sel.enable_autoselection(false);
     816            0 :         m_sel.enable_selection_inheritance(true);       //required for select and mark, disabled later
     817            0 :         m_sel.enable_strict_inheritance(false);
     818              : 
     819              : //      bool strictInherit = m_sel.strict_inheritance_enabled();
     820              : //
     821              : //      UG_LOG("strikte Inheritenz ist " << strictInherit << " und false ist " << false << std::endl);
     822              : 
     823            0 :         return true;
     824              : }
     825              : 
     826              : 
     827            0 : bool ArteExpandFracs3D::attachMarkers()
     828              : {
     829              :         // first part
     830              : 
     831              :         // attachment pair boundary is fracture, number fractures crossing
     832              : 
     833              :         m_aAdjMarkerVFP = AttVertFracProp();
     834              : 
     835              : //      support::VertexFracturePropertiesVol<IndexType> vfp0; // false, 0 );
     836              :         VertxFracPropts vfp0; // false, 0 );
     837              :         // default value: no boundary fracture, no fractures crossing
     838              : 
     839            0 :         m_grid.attach_to_vertices_dv( m_aAdjMarkerVFP, vfp0 );
     840            0 :         m_aaMarkVrtVFP = Grid::VertexAttachmentAccessor<AttVertFracProp> ( m_grid, m_aAdjMarkerVFP );
     841              : 
     842              :         //m_aAdjMarkerVFP = AttVertFracProp();
     843              :         m_grid.attach_to_edges_dv( m_aAdjMarkerVFP, vfp0 );
     844              : 
     845            0 :         m_aaMarkEdgeVFP = Grid::EdgeAttachmentAccessor<AttVertFracProp>( m_grid, m_aAdjMarkerVFP );
     846              : 
     847              :         m_aAdjMarkerFaceIsFracB = ABool(); // used to know if an face is frac face
     848              : 
     849            0 :         m_grid.attach_to_faces_dv( m_aAdjMarkerFaceIsFracB, false );
     850            0 :         m_aaMarkFaceIsFracB = Grid::FaceAttachmentAccessor<ABool>( m_grid, m_aAdjMarkerFaceIsFracB );
     851              : 
     852              : //      m_aAdjMarkerFaceHasUnclosedFracSideB = ABool();
     853              : //
     854              : //      m_grid.attach_to_faces_dv( m_aAdjMarkerFaceHasUnclosedFracSideB, false );
     855              : //      m_aaMarkFaceHasUnclosedFracSideB = Grid::FaceAttachmentAccessor<ABool>( m_grid, m_aAdjMarkerFaceHasUnclosedFracSideB );
     856              : //
     857              : //      m_aAdjMarkerVrtxHasUnclosedFracB = ABool();
     858              : //
     859              : //      m_grid.attach_to_vertices_dv( m_aAdjMarkerVrtxHasUnclosedFracB, false );
     860              : //      m_aaMarkVrtxHasUnclosedFracB = Grid::VertexAttachmentAccessor<ABool>( m_grid, m_aAdjMarkerVrtxHasUnclosedFracB );
     861              : //
     862              :         m_aAdjMarkerFaceWithEndingCrossingCleft = ABool();
     863              : 
     864            0 :         m_grid.attach_to_faces_dv( m_aAdjMarkerFaceWithEndingCrossingCleft, false );
     865              : 
     866            0 :         m_aaMarkFaceWithEndingCrossingCleft = Grid::FaceAttachmentAccessor<ABool>( m_grid, m_aAdjMarkerFaceWithEndingCrossingCleft );
     867              : 
     868              :         m_aAdjMarkerVrtxAtEndingCrossingCleft = ABool();
     869              : 
     870            0 :         m_grid.attach_to_vertices_dv( m_aAdjMarkerVrtxAtEndingCrossingCleft, false );
     871              : 
     872            0 :         m_aaMarkVrtxAtEndingCrossingCleft = Grid::VertexAttachmentAccessor<ABool>( m_grid, m_aAdjMarkerVrtxAtEndingCrossingCleft );
     873              : //
     874              : //      m_aAdjMarkerVrtx2AtInnerEndOfEndingCrossingFract = ABool();
     875              : //
     876              : //      m_grid.attach_to_vertices_dv( m_aAdjMarkerVrtx2AtInnerEndOfEndingCrossingFract, false );
     877              : //
     878              : //      m_aaMarkVrtx2AtInnerEndOfEndingCrossingFract = Grid::VertexAttachmentAccessor<ABool>( m_grid, m_aAdjMarkerVrtx2AtInnerEndOfEndingCrossingFract );
     879              : 
     880              :         // second part
     881              : 
     882              : //      m_grid.attach_to_volumes(m_attVrtVec);
     883              : //      m_aaVrtVecVol = Grid::VolumeAttachmentAccessor<AttVrtVec>( m_grid, m_attVrtVec);
     884              : 
     885              :         std::vector<Edge*> noEdge;
     886              :         std::vector<Face*> noFace;
     887              : //      std::vector<Volume*> noVol;
     888              : 
     889              :         m_aAdjInfoEdges = AttVecEdge();
     890              :         m_aAdjInfoFaces = AttVecFace();
     891              : //      m_aAdjInfoVols = AttVecVol();
     892              : 
     893            0 :         m_grid.attach_to_vertices_dv( m_aAdjInfoEdges, noEdge );
     894            0 :         m_aaVrtInfoAssoEdges = Grid::VertexAttachmentAccessor<AttVecEdge>( m_grid, m_aAdjInfoEdges );
     895              : 
     896            0 :         m_grid.attach_to_vertices_dv( m_aAdjInfoFaces, noFace );
     897            0 :         m_aaVrtInfoAssoFaces = Grid::VertexAttachmentAccessor<AttVecFace>( m_grid, m_aAdjInfoFaces );
     898              : 
     899              : //      m_grid.attach_to_vertices_dv( m_aAdjInfoVols, noVol );
     900              : //      m_aaVrtInfoAssoVols = Grid::VertexAttachmentAccessor<AttVecVol>( m_grid, m_aAdjInfoVols );
     901              : 
     902              : 
     903              :         //  TODO FIXME
     904              :         //  das fehlt hier , Analogon 2D Fall!!!!!!!!!!!!! der geht hier eigentlich weiter
     905              :         // die Vertizes, Faces und Edges, die mit einer Kluft zu tun haben
     906              :         //      using VertFracTrip = VertexFractureTriple<Edge*, Face*, vector3>;
     907              :         //      using VecVertFracTrip = std::vector<VertFracTrip>;
     908              :         //      VecVertFracTrip vertexNoInfo;
     909              : 
     910              :         // AttVecVertFracTrip m_aAdjInfoAVVFT;
     911              : 
     912              : //      VecVertFracTrip vertexNoInfo;
     913              : //
     914              : //      m_aAdjInfoAVVFT = AttVecVertFracTrip();
     915              : //
     916              : //      m_grid.attach_to_vertices_dv( m_aAdjInfoAVVFT, vertexNoInfo );
     917              : //
     918              : //      m_aaVrtInfoFraTri = Grid::VertexAttachmentAccessor<AttVecVertFracTrip>(m_grid,  m_aAdjInfoAVVFT );
     919              : 
     920              : 
     921              :         //      associate a vector of vertices for each volume adjacent to the frac.
     922              :         //      An entry later will contain the new vertex, if the
     923              :         //      corresponding vertex is an inner fracture vertex, and nullptr if not.
     924              : 
     925              :         m_attVrtVec = AttVrtVec();
     926              : 
     927            0 :         m_grid.attach_to_volumes(m_attVrtVec);
     928              : 
     929            0 :         m_aaVrtVecVol = Grid::VolumeAttachmentAccessor<AttVrtVec>(m_grid, m_attVrtVec);
     930              : 
     931              : 
     932              : //      VecAttachedVolumeElemInfo noVolInfo;
     933              : 
     934              : //      m_aAdjVolElmInfo = AttVecAttachedVolumeElemInfo();
     935              : //
     936              : //      m_grid.attach_to_vertices_dv(m_aAdjVolElmInfo,noVolInfo);
     937              : //
     938              : //      m_aaVolElmInfo = Grid::VertexAttachmentAccessor<AttVecAttachedVolumeElemInfo>(m_grid, m_aAdjVolElmInfo);
     939              : 
     940              : 
     941              :         VecSegmentVolElmInfo noSegmts;
     942              : 
     943              :         m_attAdjVecSegVolElmInfo = AttVecSegmentVolElmInfo();
     944              : 
     945            0 :         m_grid.attach_to_vertices_dv( m_attAdjVecSegVolElmInfo, noSegmts );
     946              : 
     947            0 :         m_accsAttVecSegVolElmInfo = Grid::VertexAttachmentAccessor<AttVecSegmentVolElmInfo>( m_grid, m_attAdjVecSegVolElmInfo );
     948              : 
     949              :         VecSegmentLimitingSides emptyVecSegmLimSid;
     950              : 
     951              :         AttVecSegmLimSid m_attVecSegmLimSid;
     952              : 
     953              :         m_grid.attach_to_vertices_dv( m_attVecSegmLimSid, emptyVecSegmLimSid );
     954              : 
     955            0 :         m_vrtxAttAccsVecSegmLimSid = Grid::VertexAttachmentAccessor<AttVecSegmLimSid>( m_grid, m_attVecSegmLimSid );
     956              : 
     957              :         VecEndingCrossingFractureSegmentInfo emptyVECFSI;
     958              : 
     959              :         m_attAtVrtxVecEndingCrossFractSegmInfo = AttVecEndingCrossingFractureSegmentInfo();
     960              : 
     961            0 :         m_grid.attach_to_vertices_dv( m_attAtVrtxVecEndingCrossFractSegmInfo, emptyVECFSI );
     962              : 
     963            0 :         m_vrtxAttAccsVecEndingCrossFractSegmInfo = Grid::VertexAttachmentAccessor<AttVecEndingCrossingFractureSegmentInfo>( m_grid, m_attAtVrtxVecEndingCrossFractSegmInfo );
     964              : 
     965              : //      m_attAtVrtxIfVrtxIsEndingCrossingCleftVrtx = ABool();
     966              : //
     967              : //      m_grid.attach_to_vertices_dv( m_attAtVrtxIfVrtxIsEndingCrossingCleftVrtx, false );
     968              : //
     969              : //      m_vrtxAttAccsVrtxIsEndingCrossingCleftVrtx = Grid::VertexAttachmentAccessor<ABool>( m_grid, m_attAtVrtxIfVrtxIsEndingCrossingCleftVrtx );
     970              : 
     971              :         m_attAtFaceIfFaceIsSegmLimFaceEndingCrossingCleft = ABool();
     972              : 
     973            0 :         m_grid.attach_to_faces_dv( m_attAtFaceIfFaceIsSegmLimFaceEndingCrossingCleft, false );
     974              : 
     975            0 :         m_facAttAccsIfFaceIsSegmLimFaceEndingCrossingCleft = Grid::FaceAttachmentAccessor<ABool>( m_grid, m_attAtFaceIfFaceIsSegmLimFaceEndingCrossingCleft );
     976              : 
     977              :         m_attAtVolIfVolTouchesEndingCrossingCleft = ABool();
     978              : 
     979            0 :         m_grid.attach_to_volumes_dv( m_attAtVolIfVolTouchesEndingCrossingCleft, false );
     980              : 
     981            0 :         m_volAttAccsVolTouchesEndingCrossingCleft = Grid::VolumeAttachmentAccessor<ABool>( m_grid, m_attAtVolIfVolTouchesEndingCrossingCleft );
     982              : 
     983              :         m_attAtVrtxIfVrtxArisesFromExpandedEndingCrossingCleft = ABool();
     984              : 
     985            0 :         m_grid.attach_to_vertices_dv( m_attAtVrtxIfVrtxArisesFromExpandedEndingCrossingCleft, false );
     986              : 
     987            0 :         m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft = Grid::VertexAttachmentAccessor<ABool>( m_grid, m_attAtVrtxIfVrtxArisesFromExpandedEndingCrossingCleft );
     988              : 
     989            0 :         return true;
     990            0 : }
     991              : 
     992              : 
     993            0 : bool ArteExpandFracs3D::detachMarkers()
     994              : {
     995            0 :         m_grid.detach_from_vertices( m_aAdjMarkerVFP );
     996            0 :         m_grid.detach_from_edges( m_aAdjMarkerVFP );
     997            0 :         m_grid.detach_from_faces( m_aAdjMarkerFaceIsFracB );
     998              : //      m_grid.detach_from_faces( m_aAdjMarkerFaceHasUnclosedFracSideB );
     999              : //
    1000              : //      m_grid.detach_from_vertices( m_aAdjMarkerVrtxHasUnclosedFracB );
    1001              : //
    1002            0 :         m_grid.detach_from_faces( m_aAdjMarkerFaceWithEndingCrossingCleft );
    1003            0 :         m_grid.detach_from_vertices( m_aAdjMarkerVrtxAtEndingCrossingCleft );
    1004              : //      m_grid.detach_from_vertices( m_aAdjMarkerVrtx2AtInnerEndOfEndingCrossingFract );
    1005              : 
    1006            0 :         m_grid.detach_from_vertices( m_aAdjInfoEdges );
    1007            0 :         m_grid.detach_from_vertices( m_aAdjInfoFaces );
    1008              : //      m_grid.detach_from_vertices( m_aAdjInfoVols );
    1009              : 
    1010              : //      m_grid.detach_from_vertices( m_aAdjInfoAVVFT  );
    1011              : 
    1012            0 :         m_grid.detach_from_volumes( m_attVrtVec );
    1013              : 
    1014              : //      m_grid.detach_from_vertices(m_aAdjVolElmInfo);
    1015              : 
    1016            0 :         m_grid.detach_from_vertices( m_attAdjVecSegVolElmInfo );
    1017              : 
    1018            0 :         m_grid.detach_from_vertices( m_attVecSegmLimSid );
    1019              : 
    1020            0 :         m_grid.detach_from_vertices( m_attAtVrtxVecEndingCrossFractSegmInfo );
    1021              : 
    1022              : //      m_grid.detach_from_vertices( m_attAtVrtxIfVrtxIsEndingCrossingCleftVrtx );
    1023              : 
    1024            0 :         m_grid.detach_from_faces( m_attAtFaceIfFaceIsSegmLimFaceEndingCrossingCleft );
    1025              : 
    1026            0 :         m_grid.detach_from_volumes( m_attAtVolIfVolTouchesEndingCrossingCleft );
    1027              : 
    1028            0 :         m_grid.detach_from_vertices( m_attAtVrtxIfVrtxArisesFromExpandedEndingCrossingCleft );
    1029              : 
    1030            0 :         return true;
    1031              : }
    1032              : 
    1033            0 : bool ArteExpandFracs3D::enableVolOptAutoGenFac()
    1034              : {
    1035              :         // brauchen wir das? für was? von SR irgendwie übernommen, wo dort was entfernt ähnliches gemacht wird....
    1036            0 :         if(! m_grid.option_is_enabled(VOLOPT_AUTOGENERATE_FACES) )
    1037              :         {
    1038              :                 UG_LOG("WARNING grid option VOLOPT_AUTOGENERATE_FACES autoenabled.\n");
    1039            0 :                 m_grid.enable_options(VOLOPT_AUTOGENERATE_FACES);
    1040            0 :                 return true;
    1041              :         }
    1042              : 
    1043              :         return false;
    1044              : 
    1045              : }
    1046              : 
    1047              : //////////////////////////////////////////////////////////////////
    1048              : 
    1049            0 : int ArteExpandFracs3D::splitInnerFreeFracEdgs()
    1050              : {
    1051              :         int splittedEdges = 0;
    1052              : 
    1053            0 :         for(size_t i_fi = 0; i_fi < m_fracInfos.size(); ++i_fi )
    1054              :         {
    1055            0 :                 int fracIndSudo = m_fracInfos[i_fi].subsetIndex;
    1056              : 
    1057            0 :                 UG_LOG("sudo ind " << fracIndSudo << std::endl);
    1058              : 
    1059              :                 AttVertFracProp func_aAdjMarkerVFP;
    1060              :                 VertxFracPropts vfp0;
    1061            0 :                 m_grid.attach_to_edges_dv( func_aAdjMarkerVFP, vfp0 );
    1062            0 :                 Grid::EdgeAttachmentAccessor<AttVertFracProp> func_aaMarkEdgeVFP( m_grid, func_aAdjMarkerVFP );
    1063              : 
    1064            0 :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); ++iter )
    1065              :                 {
    1066              :                         Face* fac = *iter;
    1067              : 
    1068              :                         std::vector<Edge*> facEdges;
    1069              : 
    1070            0 :                         CollectEdges( facEdges, m_grid, fac );
    1071              : 
    1072            0 :                         for( auto const & edg : facEdges )
    1073              :                         {
    1074            0 :                                 if( func_aaMarkEdgeVFP[edg].getNumberFracEdgesInVertex() != 0 )
    1075            0 :                                         UG_THROW("Attachment nicht auf default " << std::endl);
    1076              : //                              func_aaMarkEdgeVFP[edg].setNumberCrossingFracsInVertex(0);
    1077              :                         }
    1078            0 :                 }
    1079              : 
    1080              : 
    1081            0 :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); ++iter )
    1082              :                 {
    1083              :                         Face* fac = *iter;
    1084              : 
    1085              :                         std::vector<Edge*> facEdges;
    1086              : 
    1087            0 :                         CollectEdges( facEdges, m_grid, fac );
    1088              : 
    1089            0 :                         for( auto const & edg : facEdges )
    1090              :                         {
    1091            0 :                                 func_aaMarkEdgeVFP[edg]++;
    1092              :                         }
    1093            0 :                 }
    1094              : 
    1095              :                 std::vector<Edge *> edgesToBeSplitted;
    1096              : 
    1097            0 :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); ++iter )
    1098              :                 {
    1099              :                         Face* fac = *iter;
    1100              : 
    1101              :                         std::vector<Edge*> facEdges;
    1102              : 
    1103            0 :                         CollectEdges( facEdges, m_grid, fac );
    1104              : 
    1105              :                         IndexType openEdges = 0;
    1106              : 
    1107            0 :                         for( auto const & edg : facEdges )
    1108              :                         {
    1109            0 :                                 VertxFracPropts & edgeFracPrps = func_aaMarkEdgeVFP[edg];
    1110              : 
    1111              :                                 IndexType fracEdgesOverlap = edgeFracPrps.getNumberFracEdgesInVertex();
    1112              : 
    1113            0 :                                 if( fracEdgesOverlap == 1 )
    1114              :                                 {
    1115            0 :                                         openEdges++;
    1116              :                                 }
    1117            0 :                                 else if( fracEdgesOverlap == 2 )
    1118              :                                 {
    1119              :                                         ; // fine, inner edge of fracture
    1120              :                                 }
    1121              :                                 else
    1122              :                                 {
    1123            0 :                                         m_sh.assign_subset(edg, m_sh.num_subsets());
    1124              : 
    1125              :                                         UG_LOG("how many fractures at this edge " << fracEdgesOverlap << std::endl);
    1126            0 :                                         UG_LOG("sudo " << fracIndSudo << std::endl);
    1127            0 :                                         UG_THROW("how many fractures at this edge " << fracEdgesOverlap << std::endl);
    1128              :                                         UG_THROW("sudo " << fracIndSudo << std::endl);
    1129              : //                                      return splittedEdges;
    1130              : //                                      UG_THROW("how many fractures at this edge " << fracEdgesOverlap << std::endl);
    1131              :                                 }
    1132              :                         }
    1133              : 
    1134            0 :                         if( openEdges == 2 )
    1135              :                         {
    1136              :                                 // figure out that edge that is not open, this must be splitted
    1137              : 
    1138              :                                 IndexType innerEdges = 0;
    1139              : 
    1140            0 :                                 for( auto const & edg : facEdges )
    1141              :                                 {
    1142            0 :                                         VertxFracPropts & edgeFracPrps = func_aaMarkEdgeVFP[edg];
    1143              : 
    1144              :                                         IndexType fracEdgesOverlap = edgeFracPrps.getNumberFracEdgesInVertex();
    1145              : 
    1146            0 :                                         if( fracEdgesOverlap == 2 )
    1147              :                                         {
    1148            0 :                                                 edgesToBeSplitted.push_back(edg);
    1149            0 :                                                 innerEdges++;
    1150              :                                         }
    1151              :                                 }
    1152              : 
    1153            0 :                                 if( innerEdges != 1 )
    1154              :                                 {
    1155              :                                         UG_LOG("inner edge number strange " << innerEdges << std::endl);
    1156            0 :                                         UG_THROW("inner edge number strange " << innerEdges << std::endl);
    1157              :                                 }
    1158              : 
    1159              : 
    1160              :                         }
    1161            0 :                 }
    1162              : 
    1163            0 :                 for( Edge * edg : edgesToBeSplitted )
    1164              :                 {
    1165            0 :                         vector3 center = CalculateCenter(edg, m_aaPos);
    1166            0 :                         UG_LOG("splitting edge at " << center << std::endl);
    1167            0 :                         RegularVertex* vrt = SplitEdge<RegularVertex>(m_grid, edg, false);
    1168              :                         m_aaPos[vrt] = center;
    1169            0 :                         splittedEdges++;
    1170              :                 }
    1171              : 
    1172            0 :                 m_grid.detach_from_edges( func_aAdjMarkerVFP );
    1173            0 :         }
    1174              : 
    1175            0 :         return splittedEdges;
    1176              : }
    1177              : 
    1178              : #if 0
    1179              : int ArteExpandFracs3D::splitInnerFreeFracEdgs()
    1180              : {
    1181              :         int splittedEdges = 0;
    1182              : 
    1183              :         UG_LOG("search inner frac edges with two inner boundary edges" << std::endl);
    1184              : 
    1185              :         // TODO FIXME
    1186              : 
    1187              : 
    1188              :         for(size_t i_fi = 0; i_fi < m_fracInfos.size(); ++i_fi )
    1189              :         {
    1190              :                 int fracIndSudo = m_fracInfos[i_fi].subsetIndex;
    1191              : 
    1192              :                 UG_LOG("sudo ind " << fracIndSudo << std::endl);
    1193              : 
    1194              : //              std::vector<Edge *> edgesToBeSplitted;
    1195              : 
    1196              :                 std::vector<Face*> facesAtInnerBoundary;
    1197              : 
    1198              :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); ++iter )
    1199              :                 {
    1200              :                         Face* fac = *iter;
    1201              : 
    1202              : //                      std::vector<Vertex*> assoVrt;
    1203              : //
    1204              : //                      CollectVertices( assoVrt, m_grid, fac );
    1205              : //
    1206              : //                      // check number of edges which have only one fracture face around
    1207              : //
    1208              : //                      for( Vertex * vrt : assoVrt )
    1209              : //                      {
    1210              :                         std::vector<Edge*> assoEdg;
    1211              : 
    1212              :                         CollectEdges( assoEdg, m_grid, fac );
    1213              : 
    1214              :                         for( Edge * edg : assoEdg )
    1215              :                         {
    1216              :                                 // check if edge is inner boundary edge, i.e. if has at one side non-fracture face
    1217              :                                 // only check for those edges which have one fracture face on one side
    1218              : 
    1219              :                                 // split only inner edges at the moment in case of problems
    1220              :                                 if( IsBoundaryEdge3D(m_grid, edg) )
    1221              :                                 {
    1222              :                                         continue;
    1223              :                                 }
    1224              : 
    1225              :                                 std::vector<Face *> assoFac;
    1226              : 
    1227              :                                 CollectFaces( assoFac, m_grid, edg );
    1228              : 
    1229              :                                 IndexType numFacsFromFracSudo = 0;
    1230              : 
    1231              :                                 for( Face * testFac : assoFac )
    1232              :                                 {
    1233              :                                         IndexType testSudo = m_sh.get_subset_index(testFac);
    1234              : 
    1235              :                                         if( testSudo == fracIndSudo )
    1236              :                                                 numFacsFromFracSudo++;
    1237              :                                 }
    1238              : 
    1239              :                                 if( numFacsFromFracSudo == 0 )
    1240              :                                 {
    1241              : //                                      UG_LOG("no facs at edg " << std::endl );
    1242              :                                                 ; // nothing to do, belongs from an edge not relevant for the fracture
    1243              :                                 }
    1244              :                                 else if( numFacsFromFracSudo == 1 )
    1245              :                                 {
    1246              :                                         // relevant! edge needs to be split
    1247              : 
    1248              : //                                      UG_LOG("one fac at edg" << std::endl);
    1249              : 
    1250              :                                         addElem( facesAtInnerBoundary, fac );
    1251              :                                 }
    1252              :                                 else if( numFacsFromFracSudo == 2 )
    1253              :                                 {
    1254              : //                                              UG_LOG("two fac sides at edge " << std::endl);
    1255              :                                                 ; // nothing to do, edge at both sides surrounded by fracture face
    1256              :                                 }
    1257              :                                 else
    1258              :                                 {
    1259              :                                         UG_LOG("komische Ecke" << std::endl);
    1260              :                                         UG_THROW("komische Ecke" << std::endl);
    1261              :                                 }
    1262              :                         }
    1263              : 
    1264              :                 }
    1265              : 
    1266              :                 std::vector<Edge *> edgesToBeSplitted;
    1267              : 
    1268              :                 for( Face * fac : facesAtInnerBoundary )
    1269              :                 {
    1270              :                         std::vector<Vertex *> assoVrt;
    1271              : 
    1272              :                         CollectVertices(assoVrt, m_grid, fac);
    1273              : 
    1274              :                         // check if at a vertex of a frac face is associated with two inner boundary edges
    1275              : 
    1276              :                         for( Vertex * vrt : assoVrt )
    1277              :                         {
    1278              :                                 std::vector<Edge*> assoEdg;
    1279              : 
    1280              :                                 CollectEdges( assoEdg, m_grid, vrt );
    1281              : 
    1282              :                                 IndexType innerBoundaryEdges = 0;
    1283              : 
    1284              :                                 // count number of edges of the vertex which have one free side
    1285              : 
    1286              :                                 for( Edge * edg : assoEdg )
    1287              :                                 {
    1288              :                                         // check if edge is inner boundary edge, i.e. if has at one side non-fracture face
    1289              :                                         // only check for those edges which have one fracture face on one side
    1290              : 
    1291              :                                         // split only inner edges at the moment in case of problems
    1292              :                                         if( IsBoundaryEdge3D(m_grid, edg) )
    1293              :                                         {
    1294              :                                                 continue;
    1295              :                                         }
    1296              : 
    1297              :                                         std::vector<Face *> assoFac;
    1298              : 
    1299              :                                         CollectFaces( assoFac, m_grid, edg );
    1300              : 
    1301              :                                         IndexType numFacsFromFracSudo = 0;
    1302              : 
    1303              :                                         for( Face * testFac : assoFac )
    1304              :                                         {
    1305              :                                                 IndexType testSudo = m_sh.get_subset_index(testFac);
    1306              : 
    1307              :                                                 if( testSudo == fracIndSudo )
    1308              :                                                         numFacsFromFracSudo++;
    1309              :                                         }
    1310              : 
    1311              :                                         if( numFacsFromFracSudo == 0 )
    1312              :                                         {
    1313              : //                                              UG_LOG("no facs at edg " << std::endl );
    1314              :                                                 ; // nothing to do, belongs from an edge not relevant for the fracture
    1315              :                                         }
    1316              :                                         else if( numFacsFromFracSudo == 1 )
    1317              :                                         {
    1318              :                                                 // relevant! edge needs to be split
    1319              : 
    1320              : //                                              UG_LOG("one fac at edg" << std::endl);
    1321              : 
    1322              : //                                              addElemToSplit( edgesToBeSplitted, edg );
    1323              :                                                 innerBoundaryEdges++;
    1324              :                                         }
    1325              :                                         else if( numFacsFromFracSudo == 2 )
    1326              :                                         {
    1327              : //                                              UG_LOG("two fac sides at edge " << std::endl);
    1328              :                                                 ; // nothing to do, edge at both sides surrounded by fracture face
    1329              :                                         }
    1330              :                                         else
    1331              :                                         {
    1332              :                                                 UG_LOG("komische Ecke" << std::endl);
    1333              :                                                 UG_THROW("komische Ecke" << std::endl);
    1334              :                                         }
    1335              : 
    1336              :                                 }
    1337              : 
    1338              :                                 if( innerBoundaryEdges == 0  || 1 || 3 )
    1339              :                                 {
    1340              : //                                      UG_LOG("komische innere Grenze ohne Grenze " << std::endl);
    1341              : //                                      UG_THROW("komische innere Grenze ohne Grenze " << std::endl);
    1342              : //                                      ; // nothing to do
    1343              : //                              }
    1344              : //                              else if( innerBoundaryEdges == 1 )
    1345              : //                              {
    1346              :                                         ; // nothing to do, entire boundary edge with no problem, or external edge
    1347              :                                 }
    1348              :                                 else if( innerBoundaryEdges == 2 )
    1349              :                                 {
    1350              :                                         // figure out that edge that is NOT the boundary edge
    1351              : 
    1352              :                                         UG_LOG("we have two inner boundary edges" << std::endl);
    1353              : 
    1354              :                                         std::vector<Edge*> assoEdg;
    1355              : 
    1356              :                                         CollectEdges( assoEdg, m_grid, fac );
    1357              : 
    1358              :                                         for( Edge * edg : assoEdg )
    1359              :                                         {
    1360              :                                                 // check if edge is inner boundary edge, i.e. if has at one side non-fracture face
    1361              :                                                 // only check for those edges which have one fracture face on one side
    1362              : 
    1363              :                                                 // split only inner edges at the moment in case of problems
    1364              :                                                 if( IsBoundaryEdge3D(m_grid, edg) )
    1365              :                                                 {
    1366              :                                                         continue;
    1367              :                                                 }
    1368              : 
    1369              :                                                 std::vector<Face *> assoFac;
    1370              : 
    1371              :                                                 CollectFaces( assoFac, m_grid, edg );
    1372              : 
    1373              :                                                 IndexType numFacsFromFracSudo = 0;
    1374              : 
    1375              :                                                 for( Face * testFac : assoFac )
    1376              :                                                 {
    1377              :                                                         IndexType testSudo = m_sh.get_subset_index(testFac);
    1378              : 
    1379              :                                                         if( testSudo == fracIndSudo )
    1380              :                                                                 numFacsFromFracSudo++;
    1381              :                                                 }
    1382              : 
    1383              :                                                 if( numFacsFromFracSudo == 0 ||  numFacsFromFracSudo == 1 )
    1384              :                                                 {
    1385              :                                                         // relevant! edge needs to be split
    1386              : 
    1387              :                 //                                      UG_LOG("one fac at edg" << std::endl);
    1388              :                                                         ;
    1389              : //                                                      addElem( facesAtInnerBoundary, fac );
    1390              :                                                 }
    1391              :                                                 else if( numFacsFromFracSudo == 2 )
    1392              :                                                 {
    1393              :                 //                                              UG_LOG("two fac sides at edge " << std::endl);
    1394              :                                                                 ; // nothing to do, edge at both sides surrounded by fracture face
    1395              :                                                                 addElem(edgesToBeSplitted, edg);
    1396              :                                                 }
    1397              :                                                 else
    1398              :                                                 {
    1399              :                                                         UG_LOG("komische Ecke" << std::endl);
    1400              :                                                         UG_THROW("komische Ecke" << std::endl);
    1401              :                                                 }
    1402              :                                         }
    1403              : 
    1404              :                                 }
    1405              :                                 else
    1406              :                                 {
    1407              :                                         UG_LOG("how many inner boundary edges at a fracture face???" << std::endl) ;
    1408              :                                         UG_THROW("how many inner boundary edges at a fracture face???" << std::endl) ;
    1409              :                                 }
    1410              :                         }
    1411              : 
    1412              :                         // figure out that edge that needs to be splitted - it is that one which is in touch with the fracture on two sides
    1413              : 
    1414              : //                      for( Face * fac : facesAtInnerBoundary )
    1415              : 
    1416              : 
    1417              : 
    1418              :                 }
    1419              : 
    1420              :                 for( Edge * edg : edgesToBeSplitted )
    1421              :                 {
    1422              :                         vector3 center = CalculateCenter(edg, m_aaPos);
    1423              :                         UG_LOG("splitting edge at " << center << std::endl);
    1424              :                         RegularVertex* vrt = SplitEdge<RegularVertex>(m_grid, edg, false);
    1425              :                         m_aaPos[vrt] = center;
    1426              :                 }
    1427              : 
    1428              :         }
    1429              : 
    1430              : 
    1431              :         return splittedEdges;
    1432              : 
    1433              : }
    1434              : 
    1435              : #endif
    1436              : 
    1437              : //////////////////////////////////////////////////////////////////
    1438              : 
    1439              : template<typename ELEMTYP>
    1440              : bool ArteExpandFracs3D::addElem(std::vector<ELEMTYP> & knownElems, ELEMTYP elemToAdd )
    1441              : {
    1442            0 :         return support::addElem(knownElems, elemToAdd);
    1443              : 
    1444              : //      bool unknown = true;
    1445              : //
    1446              : //      for( ELEMTYP elmKnown : knownElems )
    1447              : //      {
    1448              : //              if( elemToAdd == elmKnown )
    1449              : //              {
    1450              : //                      unknown = false;
    1451              : //                      break;
    1452              : //              }
    1453              : //      }
    1454              : //
    1455              : //      if( unknown )
    1456              : //              knownElems.push_back(elemToAdd);
    1457              : //
    1458              : //      return unknown;
    1459              : 
    1460              : }
    1461              : 
    1462              : //////////////////////////////////////////////////////////////////
    1463              : 
    1464              : 
    1465            0 : bool ArteExpandFracs3D::countAndSelectFracBaseNums()
    1466              : {
    1467              :         UG_LOG("countandselect" << std::endl);
    1468              : 
    1469            0 :         for(size_t i_fi = 0; i_fi < m_fracInfos.size(); ++i_fi )
    1470              :         {
    1471            0 :                 int fracIndSudo = m_fracInfos[i_fi].subsetIndex;
    1472              : 
    1473            0 :                 UG_LOG("sudo ind " << fracIndSudo << std::endl);
    1474              : 
    1475            0 :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); ++iter )
    1476              :                 {
    1477              :                         Face* fac = *iter;
    1478              : 
    1479              : //                      UG_LOG("Gesicht " << m_aaPos[fac] << std::endl);
    1480              : 
    1481            0 :                         vector3 facCenter = CalculateCenter( fac, m_aaPos );
    1482            0 :                         UG_LOG("fac center " << facCenter << std::endl);
    1483              : 
    1484            0 :                         for( IndexType i = 0; i < fac->num_vertices(); i++ )
    1485            0 :                                 UG_LOG("Vertex " << i << " -> " << m_aaPos[fac->vertex(i)] << std::endl);
    1486              : 
    1487              :                         UG_LOG("alle Vertizes" << std::endl);
    1488              : 
    1489            0 :                         m_sel.select(fac);
    1490              : 
    1491              :                         UG_LOG("selektiert msel " << fac << std::endl);
    1492              : 
    1493              :                         m_aaMarkFaceIsFracB[fac] = true;
    1494              : 
    1495              :                         UG_LOG("mark bool " << fac << std::endl);
    1496              : 
    1497              : //                      return true;
    1498              : 
    1499              :                         std::vector<Edge*> facEdges;
    1500              : 
    1501              :                         UG_LOG("kollektiere ecken" << std::endl);
    1502              : 
    1503            0 :                         CollectEdges( facEdges, m_grid, fac );
    1504              : 
    1505            0 :                         IndexType d_anzahlEcken = facEdges.size();
    1506              : 
    1507            0 :                         if( d_anzahlEcken == 0 )
    1508              :                         {
    1509              :                                 UG_LOG("keine Ecken " << std::endl);
    1510              :                                 return true;
    1511              :                         }
    1512              : 
    1513              :                         UG_LOG("Anzahl Ecken " << d_anzahlEcken << std::endl);
    1514              : 
    1515            0 :                         for( auto const & edg : facEdges )
    1516              :                         {
    1517            0 :                                 m_aaMarkEdgeVFP[edg]++;
    1518              : 
    1519            0 :                                 if( IsBoundaryEdge3D( m_grid, edg ) )
    1520            0 :                                         m_aaMarkEdgeVFP[edg].setIsBndFracVertex();
    1521              : 
    1522            0 :                                 m_sel.select(edg);
    1523              :                         }
    1524              : 
    1525              :                         UG_LOG("Ecken gesammelt " << std::endl);
    1526              : 
    1527            0 :                         for(size_t i = 0; i < fac->num_vertices(); ++i)
    1528              :                         {
    1529            0 :                                 Vertex* vrt = fac->vertex(i);
    1530              :                                 m_sel.select(vrt);
    1531              :                                 // TODO FIXME hier anpassen, herausfinden ob fracture geschlossen
    1532              :                                 // oder inneres Ende, und Anzahl der umgebenden fractures bestimmen!!!
    1533              : 
    1534              :                                 auto & vrtxFracPrps = m_aaMarkVrtVFP[ vrt ];
    1535              : 
    1536              : //                              m_aaMarkVrtVFP[vrt]++;
    1537              :                                 vrtxFracPrps++;
    1538              :                                 // vielleicht auch in nachfolgendem Loop über alle selektierten Vertizes,
    1539              :                                 // wo dann die attached faces abgelaufen und dabei die Subdomain Nummer ermittelt wird
    1540              :                                 // kann eventuell sogar im Hauptloop gemacht werden, dann könnte man praktisch
    1541              :                                 // das alte vertex fracture properties von 2D weiter verwenden, noch zu klären
    1542              : 
    1543              : //                              m_aaMarkVrtVFP[vrt].addFractSudo(fracIndSudo);
    1544            0 :                                 vrtxFracPrps.addFractSudo(fracIndSudo);
    1545              : 
    1546            0 :                                 if( IsBoundaryVertex3D(m_grid, vrt) )
    1547              :                                 {
    1548              : //                                      m_aaMarkVrtVFP[vrt].setIsBndFracVertex();
    1549              :                                         vrtxFracPrps.setIsBndFracVertex();
    1550              :                                 }
    1551              : 
    1552              :                                 // nicht mehr notwendig
    1553              : //                              // die Ecken heraus filtern, die mit diesem Vertex assoziert sind
    1554              : //                              std::vector<Edge*> attEdg;
    1555              : //
    1556              : //                              for( auto const & ae: facEdges )
    1557              : //                              {
    1558              : //                                      if( EdgeContains(ae,vrt) )
    1559              : //                                              attEdg.push_back(ae);
    1560              : //                              }
    1561              : //
    1562              : //                              if( attEdg.size() == 2 )
    1563              : //                              {
    1564              : //                                      EdgePair edgPr( attEdg[0], attEdg[1] );
    1565              : //
    1566              : //                                      AttachedFractFaceEdgeSudo afes( fac, edgPr, fracIndSudo );
    1567              : //
    1568              : //                                      vrtxFracPrps.addAttachedFractElem(afes);
    1569              : //                              }
    1570              : //                              else
    1571              : //                              {
    1572              : //                                      UG_THROW("number of attached edges wrong " << std::endl);
    1573              : //                              }
    1574              : 
    1575              :                         }
    1576            0 :                 }
    1577              :         }
    1578              : 
    1579              : 
    1580              :         //      now make sure that no inner edge is associated with two
    1581              :         //      boundary vertices (referring to the selection)
    1582              : 
    1583              :         constexpr bool splitEdgesTwoBdryVrt = false;
    1584              : 
    1585              :         if( splitEdgesTwoBdryVrt )
    1586              :         {
    1587              :                 std::vector<Edge*> tmpEdges;
    1588              : 
    1589              :                 for(EdgeIterator iterEdg = m_sel.begin<Edge>(); iterEdg != m_sel.end<Edge>(); iterEdg++ )
    1590              :                 {
    1591              :                         Edge* edg = *iterEdg;
    1592              : 
    1593              :                         Vertex * vrtZer = edg->vertex(0);
    1594              :                         Vertex * vrtOne = edg->vertex(1);
    1595              : 
    1596              :                         VertxFracPropts & vrtxFracPrpsVrtZer = m_aaMarkVrtVFP[ vrtZer ];
    1597              :                         VertxFracPropts & vrtxFracPrpsVrtOne = m_aaMarkVrtVFP[ vrtOne ];
    1598              :                         VertxFracPropts & edgeFracPrps = m_aaMarkEdgeVFP[ edg ];
    1599              : 
    1600              :                         if(      vrtxFracPrpsVrtZer.getIsBndFracVertex()
    1601              :                                 &&   vrtxFracPrpsVrtOne.getIsBndFracVertex()
    1602              :                                 && ! edgeFracPrps.getIsBndFracVertex()
    1603              :                         )
    1604              :                         {
    1605              :                                 tmpEdges.push_back(edg);
    1606              :                         }
    1607              : 
    1608              :                 }
    1609              : 
    1610              :                 for( Edge * edg : tmpEdges )
    1611              :                 {
    1612              :                         vector3 center = CalculateCenter(edg, m_aaPos);
    1613              :                         RegularVertex* vrt = SplitEdge<RegularVertex>(m_grid, edg, false);
    1614              :                         m_aaPos[vrt] = center;
    1615              :                         m_sel.select(vrt);
    1616              :                         auto & vrtxFracPrps = m_aaMarkVrtVFP[ vrt ];
    1617              :                         vrtxFracPrps++;
    1618              : 
    1619              :                         vrtxFracPrps.setIsBndFracVertex(false);
    1620              : 
    1621              :                         //      assign adjacency values for associated selected edges (2 to each)
    1622              :                         for(Grid::AssociatedEdgeIterator iterEdg  = m_grid.associated_edges_begin(vrt);
    1623              :                                                                                          iterEdg != m_grid.associated_edges_end(vrt);
    1624              :                                                                                          iterEdg++
    1625              :                         )
    1626              :                         {
    1627              :                                 Edge * assoEdg = *iterEdg;
    1628              : 
    1629              :                                 if( m_sel.is_selected(assoEdg) )
    1630              :                                 {
    1631              :                                         auto & edgFracPrps = m_aaMarkEdgeVFP[assoEdg];
    1632              :                                         edgFracPrps.setIsBndFracVertex(false);
    1633              :                                 }
    1634              :                         }
    1635              :                 }
    1636              : 
    1637              :                 // TODO FIXME unsicher, ob das hier richtig übertragen von Prof. Reiter......
    1638              :         }
    1639              : 
    1640              : #if 0
    1641              : 
    1642              :         // TODO FIXME das ist was komisches, was von S. Reiter da ist, es werden edges gesplittet, für was?
    1643              : 
    1644              :         edges.clear();
    1645              :         for(EdgeIterator iter = sel.begin<Edge>();
    1646              :                 iter != sel.end<Edge>(); ++iter)
    1647              :         {
    1648              :                 Edge* e = *iter;
    1649              :                 if(aaMarkVRT[e->vertex(0)] != 2 &&
    1650              :                         aaMarkVRT[e->vertex(1)] != 2 &&
    1651              :                         aaMarkEDGE[e] > 1)
    1652              :                 {
    1653              :                         edges.push_back(e);
    1654              :                 }
    1655              :         }
    1656              : 
    1657              :         for(size_t i = 0; i < edges.size(); ++i){
    1658              :                 vector3 center = CalculateCenter(edges[i], aaPos);
    1659              :                 RegularVertex* v =      SplitEdge<RegularVertex>(grid, edges[i], false);
    1660              :                 aaPos[v] = center;
    1661              :                 aaMarkVRT[v] = 2;
    1662              :                 sel.select(v);
    1663              :         //      assign adjacency values for associated selected edges (2 to each)
    1664              :                 for(Grid::AssociatedEdgeIterator iter = grid.associated_edges_begin(v);
    1665              :                         iter != grid.associated_edges_end(v); ++iter)
    1666              :                 {
    1667              :                         if(sel.is_selected(*iter))
    1668              :                                 aaMarkEDGE[*iter] = 2;
    1669              :                 }
    1670              :         }
    1671              : 
    1672              : 
    1673              : #endif
    1674              : 
    1675              :         return true;
    1676              : 
    1677              : }
    1678              : 
    1679            0 : int ArteExpandFracs3D::prepareStasi( Vertex * const & vrt, AttachedVolumeElemInfo & attVolElmInfo )
    1680              : {
    1681              :         // NOTE returns number of boundary faces
    1682              : 
    1683              :         // Voraussetzung  FÜR StammiBene Aufrufung
    1684              :         // Stammi-Bene-Vorbereitung
    1685              : //      for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    1686              : //      {
    1687              : //              Vertex* vrt = *iter;
    1688              : 
    1689              : //              std::vector<Volume*> & attVol = m_aaVrtInfoAssoVols[vrt];
    1690              : 
    1691            0 :         auto & vrtxFracPrps = m_aaMarkVrtVFP[ vrt ];
    1692              : 
    1693              : //      bool isBndryVrtx = vrtxFracPrps.getIsBndFracVertex();
    1694              : 
    1695              :         IndexType numBndryFacs = 0;
    1696              : 
    1697              :                 // TODO FIXME das hier soll wegfallen, und an dieser Stelle direkt berechnet werden
    1698              :                 // damit es einheitlich für echte fracture faces und auch für boundary faces gilt,
    1699              :                 // die eine Art Fracture sind, an denen mit dem Durchmesser 0 der neue Vertex verschoben wird
    1700              : 
    1701              :                 // die erzeugen wir an Ort und Stelle neu und verteilen nicht alles auf hundert Plätze
    1702              : //              VecAttachedFractFaceEdgeSudo vecAttFacEdgSudo = vrtxFracPrps.getAllAttachedFractElems();
    1703              : 
    1704              : //              auto & vecVolElmInfo = m_aaVolElmInfo[vrt];
    1705              : 
    1706              :                 // TODO FIXME eigentlich eine Dummheit, das auf zu teilen in ein VolElemInfo und ein VrtInfoAssoVols
    1707              :                 // denn die InfoAssoVols haben als Info nur die Volumen, die VolElmInfos haben die Volumen
    1708              :                 // und noch viel mehr Infos zu den Faces und den Edges....
    1709              :                 // mittelfristig die m_aaVrtInfoAssoVols abschaffen und alles auf die AttachedFullDimElemInfo
    1710              :                 // übertragen, dann geht der folgende Loop gleich über den Vektor darüber, bzw. gleichbedeutend
    1711              :                 // über m_aaVolElmInfo
    1712              : //              for( auto & vol : attVol )
    1713              : //              for( AttachedVolumeElemInfo & attVolElmInfo : vecVolElmInfo )
    1714              : //              {
    1715              : //                      AttachedVolumeElemInfo attVolElmInfo( vol );
    1716            0 :         Volume * vol = attVolElmInfo.getFulldimElem();
    1717              : 
    1718              :                         // add those faces which are fracture faces
    1719              :                         // TODO FIXME hier müssen die fracture faces neu erzeugt und addiert werden, oder weiter unten.....
    1720              : //                      for( auto & afes : vecAttFacEdgSudo )
    1721              : //                      {
    1722              : //                              attVolElmInfo.addFractManifElem(afes, m_grid);
    1723              : //                      }
    1724              : 
    1725              :                         // add those faces which are NOT fracture faces, assign them arbitraryly subdomain  -1
    1726              :                         // to indicate that they are not from the manifold, independent of their subdomain
    1727              : 
    1728              :                         // collect all volume faces which incorporate the vertex
    1729              : 
    1730              :         std::vector<Face*> volFacesContainingVrtx;
    1731              : 
    1732            0 :         for( IndexType iFac = 0; iFac < vol->num_faces(); iFac++ )
    1733              :         {
    1734            0 :                 Face * fac = m_grid.get_face(vol,iFac);
    1735              : 
    1736            0 :                 if( FaceContains( fac, vrt ) )
    1737              :                 {
    1738            0 :                         volFacesContainingVrtx.push_back( fac );
    1739              :                 }
    1740              :         }
    1741              : 
    1742            0 :         for( auto const & fac : volFacesContainingVrtx )
    1743              :         {
    1744              :                                 // get the edges of the face connected to the vertex
    1745              : 
    1746              :                 std::vector<Edge*> vecEdgesFaceVrtx;
    1747              : 
    1748              :                                 // need to be two edges always, check
    1749              : 
    1750            0 :                 for( IndexType iEdge = 0; iEdge < fac->num_edges(); iEdge++ )
    1751              :                 {
    1752            0 :                         Edge * edg = m_grid.get_edge(fac,iEdge);
    1753              : 
    1754            0 :                         if( EdgeContains(edg,vrt) )
    1755              :                         {
    1756            0 :                                 vecEdgesFaceVrtx.push_back(edg);
    1757              :                         }
    1758              :                 }
    1759              : 
    1760            0 :                 if( vecEdgesFaceVrtx.size() != 2 )
    1761              :                 {
    1762              :                         UG_LOG("edge number Unsinn " << vecEdgesFaceVrtx.size() << std::endl);
    1763            0 :                         UG_THROW("edge number Unsinn " << vecEdgesFaceVrtx.size() << std::endl);
    1764              :                         return false;
    1765              :                 }
    1766              : 
    1767              :                 EdgePair edgesFaceVrtx( vecEdgesFaceVrtx[0], vecEdgesFaceVrtx[1] );
    1768              : 
    1769              :                                 // test the subdomain first, if from the subdomains of the cleft manifolds
    1770              : 
    1771            0 :                 IndexType sudoThisFace = m_sh.get_subset_index(fac);
    1772              : 
    1773              :                 std::vector<IndexType> const & sudoList = vrtxFracPrps.getSudoList();
    1774              : 
    1775              :                                 // test if sudo of face belongs to the fracture face subdom list
    1776              : 
    1777              :                 bool faceBelongsToFracSudo = false;
    1778              : 
    1779            0 :                 for( auto const & sudoFrac : sudoList )
    1780              :                 {
    1781            0 :                         if( sudoFrac == sudoThisFace )
    1782              :                         {
    1783              :                                 faceBelongsToFracSudo = true;
    1784              :                                 break;
    1785              :                         }
    1786              :                 }
    1787              : 
    1788              :                                 // TODO FIXME für Boundary faces und für Fracture faces soll die Normale berechnet werden ins VOlumen hinein
    1789              :                                 // hier die KuhVol-Prozedur
    1790              : 
    1791              :                 bool isBoundaryFace = false;
    1792              : 
    1793            0 :                 if( ! faceBelongsToFracSudo )
    1794              :                 {
    1795            0 :                         if( IsBoundaryFace3D( m_grid, fac ) )
    1796              :                         {
    1797              :                                 isBoundaryFace = true;
    1798              :                         }
    1799              :                 }
    1800              : 
    1801            0 :                 if( isBoundaryFace && faceBelongsToFracSudo )
    1802            0 :                         UG_THROW("not allowed to be fracture at boundary" << std::endl);
    1803              : 
    1804              :                 // will get a nonzero value in case that fracture face or boundary face
    1805              :                 NormalVectorFacIntoVol normalIntoVol(0,0,0);
    1806              : 
    1807            0 :                 if( isBoundaryFace || faceBelongsToFracSudo )
    1808              :                 {
    1809              :                                 // TODO FIXME compute normal into volume, needed to know!!!
    1810              :                                         // kuhVol Procedure
    1811            0 :                         if( ! computeNormalKuhVolProcedure(vol,fac,normalIntoVol) )
    1812              :                         {
    1813              :                                 UG_LOG("Kuh VOl schief gegangen " << std::endl);
    1814            0 :                                 UG_THROW("Kuh VOl schief gegangen " << std::endl);
    1815              :                                 return numBndryFacs;
    1816              :                         }
    1817              :                 }
    1818              : 
    1819            0 :                 if( faceBelongsToFracSudo )
    1820              :                 {
    1821              :                                         // if it belongs, construct it again and test if it already belongs to the fracture faces
    1822              :                                         // MUST be already part of the list, else major error appeared!
    1823              : 
    1824            0 :                         UG_LOG("Kuh Normale " << normalIntoVol << std::endl);
    1825              : 
    1826              :                         AttachedFractFaceEdgeSudo afesFract( fac, edgesFaceVrtx, sudoThisFace, normalIntoVol );
    1827              :                                         //  hier soll auch gleich die Normale relativ zum VOlumen dazu gespeichert werden!!
    1828              : 
    1829            0 :                         attVolElmInfo.addFractManifElem( afesFract, m_grid );
    1830              : 
    1831              :                                         // vorher soll es nicht mehr gespeichert werden, da die Infos vorher weg fallen sollen
    1832              : //                                      if( attVolElmInfo.addFractManifElem( afesFract, m_grid ) )
    1833              : //                                      {
    1834              : //                                              UG_LOG("manifold element already contained!" << std::endl);
    1835              : //                                              UG_THROW("manifold element already contained!" << std::endl);
    1836              : //                                              return false;
    1837              : //                                      }
    1838              : 
    1839              :                                         // nothing to do, already added before hoffentlich
    1840              : 
    1841              :                 }
    1842              :                 else
    1843              :                 {
    1844              :                                         // TODO FIXME hier muss entschieden werden, ob es eine boundary face ist
    1845              :                         // die kommt dann auch nochmal in ein anderes Konstrukt, was aber
    1846              :                                         // dem fracture face ähnelt
    1847              :                                         // am Ende müssen die Frac Faces, die nicht geschlossen sind, und doppelt in einem Segment
    1848              :                                         // in die general faces verschoben werden, da stören sie nicht, und sind egal
    1849              : 
    1850              :                                         // zeitweilig fehlten alle Faces, die keine fractures sind
    1851              :                                         // die müssen noch irgendwie als nicht-fracture-faces auch dazu gefügt werden
    1852              :                                         // die sind in den attached volumes schon enthalten,
    1853              :                                         // Frage: wie prüfen, dass die gar keine fractures sind, die Infos sollten bekannt sein.....
    1854              :                                         // wichtig auch, dass nur die faces dazu kommen, die den Vertex enthalten!!!
    1855              :                                         // irgendwas von der Art "nonFractureFaceInfos" oder sowas dazu hängen, mit Info
    1856              :                                         // ob schon getouched oder noch nicht.....
    1857              : 
    1858              : 
    1859              :                                         // we construct the attached manifold, given that it is NOT a fracture manifold
    1860              : 
    1861              :                                         // notwendig auch, dass es eine Markierungsmöglichkeit gibt dafür, ob
    1862              :                                         // ein face bei der nächsten weiter inneren Runde quasi äussere Begrenzung sein muss
    1863              :                                         // gilt sowohl für fracture faces, die können das in erster Runde auch sein am Ende
    1864              :                                         // der Runde, sowie danach nur noch für nicht-fracture-faces
    1865              : //                                      if( IsBoundaryFace3D( m_grid, fac ) )
    1866            0 :                         if( isBoundaryFace )
    1867              :                         {
    1868              :                                 AttachedBndryFaceEdgeSudo afesBndry( fac, edgesFaceVrtx, sudoThisFace, normalIntoVol );
    1869              : 
    1870            0 :                                 attVolElmInfo.addBndryManifElem( afesBndry, m_grid );
    1871              : 
    1872            0 :                                 UG_LOG("Boundary element added" << m_aaPos[vrt] << " -> " << normalIntoVol << std::endl);
    1873              : 
    1874            0 :                                 numBndryFacs++;
    1875              : 
    1876              : //                                                      UG_THROW("da ist es " << std::endl);
    1877              : 
    1878              :                                 // TODO FIXME sehr wichtig, die Boundary faces brauchen auch
    1879              :                                                 // noch ihre Normale in das Volumen hinein, analog zu den Fracture faces!!!
    1880              :                                                 // die haben die allerdings dummerweise in die boundary vertizes gesteckt
    1881              :                                                 // vielleicht boundaries wie fractures behandeln? keine gute Idee......
    1882              :                                                 // mithin steckt die Normale NICHT in diesen Informationen drin
    1883              :                                                 // sondern extra in den vertex fracture tripeln
    1884              :                                                 // vielleicht dort die boundaries irgendwie dazu würgen.....
    1885              : 
    1886              :                         }
    1887              :                         else // normal face, no fracture, no boundary
    1888              :                         {
    1889              :                                 AttachedGenerFaceEdgeSudo afesAdd( fac, edgesFaceVrtx );
    1890              : 
    1891            0 :                                 attVolElmInfo.addGenerManifElem( afesAdd, m_grid );
    1892              :                         }
    1893              : 
    1894              : 
    1895              :                 }
    1896              : 
    1897            0 :         }
    1898              : 
    1899              : //              }
    1900              : //      }
    1901              : 
    1902              : //      if( isBndryVrtx && numBndryFacs == 0 )
    1903              : //      {
    1904              : //              UG_LOG("boundary vertex but no boundary faces ")
    1905              : //      }
    1906              : 
    1907            0 :         return numBndryFacs;
    1908            0 : }
    1909              : 
    1910            0 : bool ArteExpandFracs3D::computeNormalKuhVolProcedure( Volume * const & kuhVol, Face * const & fac, NormalVectorFacIntoVol & normalIntoVol )
    1911              : {
    1912              :         IndexType numFd = 0;
    1913              : 
    1914            0 :         for( IndexType iSide = 0; iSide < kuhVol->num_sides(); iSide++ )
    1915              :         {
    1916            0 :                 Face * kuhFac = m_grid.get_side(kuhVol, iSide);
    1917              : 
    1918              : //                                      UG_LOG("Center Kuh Face " << CalculateCenter(kuhFac,m_aaPos) << std::endl);
    1919              : 
    1920              :                 //  eigentliches Ziel ist es, den face descriptor des Volumens zu finden,
    1921              :                 // das mit dem face übereinstimmt, alle anderen Seiten des Volumens sind egal
    1922              :                 // Funktion suchen, die ausgehend von einem Face, das ein Volumen begrenzt,
    1923              :                 // den zum Volumen passenden FaceDescriptor findet, also auch richtige Orientierung
    1924              :                 // der Vertices beinhaltet
    1925              :                 // FRAGE: ist ein face descriptor von der Orientierung zum Volumen abhängig
    1926              :                 // oder hängt der nur vom Face ab, das eine vorgegebene Oriertierung hat?
    1927              : 
    1928            0 :                 bool checkCoincide = checkIfFacesVerticesCoincide( kuhFac, fac );
    1929              : 
    1930            0 :                 if( checkCoincide )
    1931              :                 {
    1932            0 :                         numFd++;
    1933              : 
    1934            0 :                         if( kuhFac != fac )
    1935              :                                 UG_LOG("Kuh Fac ist nicht fac " << std::endl);
    1936              : 
    1937            0 :                         FaceDescriptor facDescr;
    1938              : 
    1939              :                         // testen, ob der Face Descriptor von der Orientierung abhängt
    1940              :                         // also testen, ob sich der face descriptor ändert, wenn das Volumen
    1941              :                         // auf der einen und auf der anderen Seite des faces hängt
    1942              :                         // deswegen auch die ganze Prozedur mit den kuhFacs, die hoffentlich
    1943              :                         // je nach Volumen anders orientiert sind als das eigentliche Face,
    1944              :                         // aber dieselben Vertices haben, also geometrisch gleich sind, aber anders orientiert!!!!
    1945              : 
    1946              :                         //  andere Hergehensweise vielleicht:
    1947              :                         // von m_aaVrtInfoAssoVols ausgehen, darüber loopen, oder die in einen Vektor stecken,
    1948              :                         // wo die Vertices dabei sind, dann kann man sich vielelicht ein paar Klimmzüge sparen,
    1949              :                         // vielleicht aber auch nicht.....
    1950              : 
    1951            0 :                         kuhVol->face_desc( iSide, facDescr );
    1952              : 
    1953              : //                      vector3 normal;
    1954              : 
    1955            0 :                         CalculateNormal( normalIntoVol, & facDescr, m_aaPos );
    1956              : 
    1957            0 :                         vector3 facCenter = CalculateCenter( kuhFac, m_aaPos );
    1958            0 :                         vector3 kuhCenter = CalculateCenter( fac, m_aaPos );
    1959            0 :                         vector3 kuhVolCenter = CalculateCenter( kuhVol, m_aaPos);
    1960              : 
    1961              : //                                              UG_LOG("Normale zum face descriptor " << normal << " , " << facCenter << std::endl);
    1962              : //                                              UG_LOG("Normale zum Kuhh descriptor " << normal << " , " << kuhCenter << std::endl);
    1963              : //                                              UG_LOG("Zentrum des Vol")
    1964              : 
    1965              : //                                              UG_LOG("fac " << fac << std::endl );
    1966              : //                                              UG_LOG("kuh " << kuhFac << std::endl );
    1967              : 
    1968            0 :                         UG_LOG("Normale ist " << normalIntoVol << " fac " << facCenter
    1969              :                                         << " vol " << kuhVolCenter << std::endl);
    1970              : 
    1971              : 
    1972              : //                                              VolNormPair normalsAwayVol( kuhVol, normal );
    1973              : //
    1974              : //                                              vecNormalsAwayVol.push_back( normalsAwayVol );
    1975              : 
    1976              :                 }
    1977              :         }
    1978              : 
    1979            0 :         if( numFd != 1 )
    1980              :         {
    1981            0 :                 UG_THROW("Kein Kuh Volumen gefunden" << std::endl);
    1982              :                 return false;
    1983              :         }
    1984              : 
    1985              : 
    1986              :         return true;
    1987              : }
    1988              : 
    1989              : //////////////////////////////////////////////////////////////////
    1990              : 
    1991            0 : bool ArteExpandFracs3D::distinguishSegments()
    1992              : {
    1993              : 
    1994              :         UG_LOG("neuer Beginn Segmente" << std::endl);
    1995              : //      return true;
    1996              : 
    1997              :         //      StammiBene Algorithmus erklärt und in Worten Plan erstellt
    1998              :         //      Search the adjacent merged manifold iteratively between each necessary element
    1999              :         // TODO FIXME hier Loop über alle selektierten Vertizes
    2000              :         // darin für jeden Vertex die adjungierten Volumen bestimmen ohne Vorbedingung
    2001              :         // dann den Loop zur Vorbereitung des StammiBene Algorithmus aufrufen
    2002              :         // für jeden Vertex wieder, der hat dann schon die Basisinfo von der
    2003              :         // VecAttachedVolumeElemInfo Klasse an jedem Vertex
    2004              :         // auf die aufbauend fügt er Fracture  Manifolds, general manifolds,
    2005              :         // und NEU auch boundary manifolds in einer eigenen Member dazu
    2006              :         // danach wird für jeden Vertex der StammiBene Algorithmus aufgerufen
    2007              :         // später werden Boundary Faces wie eine eigene Subdomain Ebene
    2008              :         // mit Expansion null behandelt
    2009              :         // was an Knicken aussen an boundary zu tun ist, noch zu überlegen
    2010              : 
    2011              :         UG_LOG("Stasi Algo alle Vrt Start << std::endl");
    2012              : 
    2013            0 :         for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    2014              :         {
    2015            0 :                 Vertex* vrt = *iter;
    2016              : 
    2017            0 :                 if( ! stasiAlgo( vrt ) )
    2018              :                 {
    2019              :                         UG_LOG("Stasi schief gegangen " << std::endl);
    2020            0 :                         UG_THROW("Stasi schief gegangen" << std::endl);
    2021              :                         return false;
    2022              :                 }
    2023              :         }
    2024              : 
    2025              :         UG_LOG("Stasi Algo alle Vrt End << std::endl");
    2026              : 
    2027              :         // TODO FIXME
    2028              :         // es müssen in den Segmenten noch die fracture faces zu generellen faces verschoben werden,
    2029              :         // die nicht abgeschlossen sind, und umgangen werden können, und so in die Landschaft ragen
    2030              :         // also die fracture faces, die für die Segmenteigenschaft unerheblich sind
    2031              : 
    2032            0 :         for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    2033              :         {
    2034            0 :                 Vertex* vrt = *iter;
    2035              : 
    2036            0 :                 IndexType shiFraFac = shiftUnclosedFracFacesToUnclosedFractFaces( vrt );
    2037              : 
    2038            0 :                 UG_LOG("shifted frac faces at " << m_aaPos[vrt] << shiFraFac << std::endl);
    2039              :         }
    2040              : 
    2041              : 
    2042              :         return true;
    2043              : 
    2044              : }
    2045              : 
    2046              : //////////////////////////////////////////////////////////////////
    2047              : 
    2048              : 
    2049            0 : bool ArteExpandFracs3D::detectEndingCrossingCleftsSegmBased()
    2050              : {
    2051              : 
    2052            0 :         m_vecEdgeDirectConnectingEndingCrossCleftVrtcs = std::vector<Edge*>();
    2053              : 
    2054              :         // TODO FIXME eigene Klasse erzeugen, die die ganzen Infos an endenden Klüften speichert, wo sich
    2055              :         // zwei Klüfte kreuzen
    2056              :         // Vertex, auslaufende faces, wo anders aufgeblasen werden muss,
    2057              :         // Edges der Kreuzung, die anhängenden faces der anderen Kluft, die
    2058              :         // die Basis sind für die Aufblasungen, die auch anders funktionieren
    2059              :         // von dieser Klasse dann ein attachment an die vertizes und vielleicht die faces,
    2060              :         // die problematisch sind
    2061              :         // (noch zu klären, ob vielleicht ein paar der auskommentierten attachments doch sinnvoll)
    2062              : 
    2063              :         IndexType numEndingCrossingClefts = 0;
    2064              : 
    2065              : //      std::vector<Face*> m_d_endingCrossingCleftFaces;
    2066              : //
    2067              : //      std::vector<Vertex*> m_d_endingCrossingCleftVrtcs;
    2068              : //
    2069              : //      std::vector<Edge*> m_d_cuttingEdges;
    2070              : //      std::vector<Face*> crossingNotEndingFaces;
    2071              : //
    2072              : //      std::vector<Edge*> otherEdgeOfCrossingNotEndingFace;
    2073              : //      std::vector<Face*> nextFaceOfCrossingNotEndingFaces;
    2074              : 
    2075            0 :         for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    2076              :         {
    2077            0 :                 Vertex* vrt = *iter;
    2078              : 
    2079              :                 VecSegmentLimitingSides & vecSegmLimSid = m_vrtxAttAccsVecSegmLimSid[vrt];
    2080              : 
    2081            0 :                 if(  vecSegmLimSid.size() == 0 )
    2082              :                 {
    2083              :                         UG_LOG("keine verschiedenen Segmente ECCV" << std::endl);
    2084              : //                      return true;
    2085              :                 }
    2086              : 
    2087            0 :                 if( vecSegmLimSid.size() == 1 )
    2088              :                 {
    2089              :                         UG_LOG("sonderbarer Fall von nur einem Segment ECCV" << std::endl );
    2090            0 :                         UG_THROW("sonderbarer Fall von nur einem Segment ECCV" << std::endl );
    2091            0 :                         return false;
    2092              :                 }
    2093              : 
    2094            0 :                 for( SegmentLimitingSides & segLimSids : vecSegmLimSid )
    2095              :                 {
    2096            0 :                         if( segLimSids.hasUnclosedFaces() )
    2097              :                         {
    2098              :                                 UG_LOG("im distinguisch ungeschlossene Gesichter " << std::endl );
    2099              : 
    2100            0 :                                 numEndingCrossingClefts++;
    2101              : 
    2102              :                                 std::vector<Volume*> volsOfUnclosedSegm;
    2103              : 
    2104            0 :                                 if( ! segLimSids.spuckVecFulldimElem(volsOfUnclosedSegm) )
    2105              :                                 {
    2106              :                                         UG_LOG("No volumes at segment with ending cleft" << std::endl);
    2107            0 :                                         UG_THROW("No volumes at segment with ending cleft" << std::endl);
    2108              :                                         return false;
    2109              :                                 }
    2110              : 
    2111            0 :                                 for( Volume * vol : volsOfUnclosedSegm )
    2112              :                                 {
    2113              :                                         m_volAttAccsVolTouchesEndingCrossingCleft[vol] = true;
    2114              :                                 }
    2115              : 
    2116              :                                 Vertex * endingCrossingCleftVrtx = segLimSids.spuckVertex();
    2117              : 
    2118            0 :                                 if( endingCrossingCleftVrtx != vrt )
    2119              :                                 {
    2120            0 :                                         UG_THROW("System von attachments und vektoren durcheinander " << std::endl);
    2121              :                                 }
    2122              : 
    2123              :                                 //  commented out the debug members:  m_d_endingCrossingCleftVrtcs.push_back( endingCrossingCleftVrtx );
    2124              : 
    2125              :                                 UG_LOG("vertex gefunden an ending crossing cleft " << std::endl);
    2126              : 
    2127              :                                 m_aaMarkVrtxAtEndingCrossingCleft[vrt] = true;
    2128              : 
    2129              :                                 // the unclosed ending crossing faces
    2130              :                                 VecSegLimSidesFractFace vecSegmLimSiFFUnclosed;
    2131              : 
    2132              :                                 if( ! segLimSids.spuckVecAttUnclosedFractElm( vecSegmLimSiFFUnclosed ) )
    2133              :                                         return false;
    2134              : 
    2135              :                                 // figure out the faces that are in touch with the ending faces, and the corresponding edges
    2136              : 
    2137              :                                 VecSegLimSidesFractFace vecSegmLimSiFFClosed;
    2138              : 
    2139              :                                 if( ! segLimSids.spuckVecAttFractElm( vecSegmLimSiFFClosed ) )
    2140              :                                         return false;
    2141              : 
    2142              :                                 UG_LOG("Faces suchen an ending crossing cleft " << std::endl);
    2143              : 
    2144              : //                              Face * endingFractManifCutting = nullptr;
    2145              : //                              Face * endingFractManifNotCutting = nullptr;
    2146              : //                              Edge * oldLowDimElCut = nullptr;
    2147              : //                              std::pair<Face*,Face*> pairNeighbouredFractClosedManifEl(nullptr,nullptr);
    2148              : //                              IndexType sudoFractEnding = std::numeric_limits<IndexType>::max();
    2149              : //                              IndexType sudoFractNotEnding = std::numeric_limits<IndexType>::max();
    2150              : 
    2151              :                                 std::vector<Face*> vecEndingFractFaceCutting; // must have size two after been filled but both same content
    2152              :                                 std::vector<Face*> vecEndingFractFaceNotCutting; // can contain an arbitrary number from zero to .....
    2153              :                                 std::vector<Face*> vecNeighbouredFacesClosedFract; // must have size 2
    2154              : 
    2155              :                                 std::vector<IndexType> vecSudoFractFacsEnding; // must be filled with same number
    2156              :                                 std::vector<IndexType> vecSudoFractFacsNotEnding; // must be filled with same number
    2157              : 
    2158              :                                 std::vector<Edge*> vecCuttingEdges; // must contain only same element, twice
    2159              : 
    2160              :                                 std::vector<Edge*> vecUncuttingEdge; // must get same element twice
    2161              : 
    2162              :                                 UG_LOG("size of vec segm unclos " << vecSegmLimSiFFUnclosed.size() << std::endl);
    2163              : 
    2164            0 :                                 for( SegLimSidesFractFace const & slsffUncl : vecSegmLimSiFFUnclosed )
    2165              :                                 {
    2166              :                                         bool isCuttingTheClosed = false;
    2167              : 
    2168            0 :                                         Face * facUncl = slsffUncl.getManifElm();
    2169              :                                         //  commented out the debug members:  m_d_endingCrossingCleftFaces.push_back(facUncl);
    2170              :                                         m_aaMarkFaceWithEndingCrossingCleft[facUncl] = true;
    2171              : 
    2172            0 :                                         IndexType sudoUncl = slsffUncl.getSudo();
    2173            0 :                                         vecSudoFractFacsEnding.push_back(sudoUncl);
    2174              : 
    2175              :                                         EdgePair const & epU = slsffUncl.getPairLowElm();
    2176              : 
    2177              :                                         //  commented out the debug members:  m_d_allContributingEdges.push_back(epU.first);
    2178              :                                         //  commented out the debug members:  m_d_allContributingEdges.push_back(epU.second);
    2179              : 
    2180              :                                         addElem( m_vecEdgeDirectConnectingEndingCrossCleftVrtcs, epU.first );
    2181              :                                         addElem( m_vecEdgeDirectConnectingEndingCrossCleftVrtcs, epU.second );
    2182              : 
    2183            0 :                                         for( SegLimSidesFractFace const & slsffClos : vecSegmLimSiFFClosed )
    2184              :                                         {
    2185              :                                                 // we need different subdoms, as want to have the not ending crossing fracture neighbours
    2186              :                                                 // that have a common edge
    2187            0 :                                                 Edge * commonEdge = nullptr;
    2188              : 
    2189            0 :                                                 if( fractFacesAreNeighboured<false>( slsffClos, slsffUncl, commonEdge ) )
    2190              :                                                 {
    2191              :                                                         isCuttingTheClosed = true;
    2192              : 
    2193            0 :                                                         Face * facClos = slsffClos.getManifElm();
    2194              :                                                         //  commented out the debug members:  m_d_crossingNeighboredNotEndingFaces.push_back( facClos );
    2195              : 
    2196            0 :                                                         if( commonEdge == nullptr )
    2197              :                                                         {
    2198              :                                                                 UG_LOG("NULL COMMON" << std::endl);
    2199            0 :                                                                 UG_THROW("NULL COMMON" << std::endl);
    2200              :                                                         }
    2201              : 
    2202              :                                                         //  commented out the debug members:  m_d_cuttingEdges.push_back(commonEdge);
    2203              :                                                         //  commented out the debug members:  m_d_crossingNeighboredNotEndingFacesCommEdg.push_back(facUncl);
    2204              : //                                                      // search the durchgehende fracture face which is neighboured to the durchgehende one
    2205              : //                                                      // same vertex, other edge
    2206              : 
    2207            0 :                                                         vecNeighbouredFacesClosedFract.push_back(facClos);
    2208            0 :                                                         vecCuttingEdges.push_back(commonEdge);
    2209            0 :                                                         vecEndingFractFaceCutting.push_back(facUncl);
    2210              : 
    2211            0 :                                                         Edge * uncuttingEdgeUnclosedFac = nullptr;
    2212              : 
    2213            0 :                                                         if( ! assignNotCuttingEdgeUnclosedCrossingCleft( slsffUncl, commonEdge, uncuttingEdgeUnclosedFac ) )
    2214              :                                                         {
    2215              :                                                                 UG_LOG("NO shift edge" << std::endl);
    2216            0 :                                                                 UG_THROW("NO shift edge" << std::endl);
    2217              :                                                         }
    2218              : 
    2219            0 :                                                         if( uncuttingEdgeUnclosedFac == nullptr )
    2220              :                                                         {
    2221              :                                                                 UG_LOG("NO shift edge Z" << std::endl);
    2222            0 :                                                                 UG_THROW("NO shift edge Z" << std::endl);
    2223              :                                                         }
    2224              : 
    2225            0 :                                                         vecUncuttingEdge.push_back(uncuttingEdgeUnclosedFac);
    2226              : 
    2227              :                                                         //                                                      EdgePair const & edgesClosedFracFace = slsffClos.getPairLowElm();
    2228              : //
    2229              : //                                                      Edge * notCommonEdgeOfNotEndingCleft = nullptr;
    2230              : //
    2231              : //                                                      if(  edgesClosedFracFace.first == commonEdge )
    2232              : //                                                      {
    2233              : //                                                              notCommonEdgeOfNotEndingCleft = edgesClosedFracFace.second;
    2234              : //                                                      }
    2235              : //                                                      else if( edgesClosedFracFace.second == commonEdge )
    2236              : //                                                      {
    2237              : //                                                              notCommonEdgeOfNotEndingCleft = edgesClosedFracFace.first;
    2238              : //                                                      }
    2239              : //
    2240              : //                                                      if( notCommonEdgeOfNotEndingCleft == nullptr )
    2241              : //                                                      {
    2242              : //                                                              UG_LOG("no not common edge?" << std::endl);
    2243              : //                                                              UG_THROW("no not common edge?" << std::endl);
    2244              : //                                                      }
    2245              : //
    2246              : ////                                                    otherEdgeOfCrossingNotEndingFace.push_back( notCommonEdgeOfNotEndingCleft );
    2247              : //
    2248              : //                                                      Edge * closedCommonEdge = nullptr;
    2249              : //
    2250              : //                                                      for( SegLimSidesFractFace const & slsffClosOther : vecSegmLimSiFFClosed )
    2251              : //                                                      {
    2252              : //                                                              if( fractFacesAreNeighboured<true>( slsffClos, slsffClosOther, closedCommonEdge ) )
    2253              : //                                                              {
    2254              : //
    2255              : //                                                                      if( closedCommonEdge == nullptr )
    2256              : //                                                                      {
    2257              : //                                                                              UG_LOG("NULL NOT COMMON" << std::endl);
    2258              : //                                                                              UG_THROW("NULL NOT COMMON" << std::endl);
    2259              : //                                                                      }
    2260              : //
    2261              : //                                                                      if( closedCommonEdge != notCommonEdgeOfNotEndingCleft )
    2262              : //                                                                      {
    2263              : //                                                                              UG_LOG("Ecke passt nicht " << CalculateCenter(closedCommonEdge, m_aaPos) << " - " << CalculateCenter( notCommonEdgeOfNotEndingCleft, m_aaPos) << std::endl);
    2264              : ////                                                                            UG_THROW("Ecke verloren " << std::endl);
    2265              : //                                                                      }
    2266              : //                                                                      else
    2267              : //                                                                      {
    2268              : //                                                                              Face * facClosOther = slsffClosOther.getManifElm();
    2269              : //
    2270              : //                                                                              nextFaceOfCrossingNotEndingFaces.push_back( facClosOther );
    2271              : //                                                                              otherEdgeOfCrossingNotEndingFace.push_back(notCommonEdgeOfNotEndingCleft);
    2272              : //                                                                      }
    2273              : //
    2274              : //
    2275              : //                                                              }
    2276              : //                                                      }
    2277              : 
    2278              : 
    2279              :                                                 }
    2280              :                                         }
    2281              : 
    2282            0 :                                         if( ! isCuttingTheClosed )
    2283              :                                         {
    2284            0 :                                                 vecEndingFractFaceNotCutting.push_back(facUncl);
    2285              :                                         }
    2286              : 
    2287              :                                 }
    2288              : 
    2289              : 
    2290              :                                 std::vector<Face*> vecClosedFracFacNoNeighbr;
    2291              : 
    2292            0 :                                 for( SegLimSidesFractFace const & slsffClos : vecSegmLimSiFFClosed )
    2293              :                                 {
    2294            0 :                                         Face * facClos = slsffClos.getManifElm();
    2295              : 
    2296              :                                         EdgePair const & epC = slsffClos.getPairLowElm();
    2297              : 
    2298              :                                         //  commented out the debug members:  m_d_allContributingEdges.push_back(epC.first);
    2299              :                                         //  commented out the debug members:  m_d_allContributingEdges.push_back(epC.second);
    2300              : 
    2301              :                                         addElem( m_vecEdgeDirectConnectingEndingCrossCleftVrtcs, epC.first );
    2302              :                                         addElem( m_vecEdgeDirectConnectingEndingCrossCleftVrtcs, epC.second );
    2303              : 
    2304              : 
    2305            0 :                                         IndexType sudoClos = slsffClos.getSudo();
    2306              : 
    2307            0 :                                         vecSudoFractFacsNotEnding.push_back(sudoClos);
    2308              : 
    2309              :                                         // valid for all closed faces
    2310              :                                         m_facAttAccsIfFaceIsSegmLimFaceEndingCrossingCleft[facClos] = true;
    2311              : 
    2312              :                                         bool facGiven = false;
    2313              : 
    2314              :                                         // ATTENTION hier ausgetauscht erst später, Gefahr von Fehler
    2315              :                                         // m_d_ Variable war Teil von echtem Algorithmus, gefährlich
    2316              :                                         // hoffentlich richtig getauscht
    2317              :                                         // im Falle von bugs hier nochmal testen, ob die m_d Variable
    2318              :                                         // richtig getauscht wurde!!!
    2319              : //                                      for( Face * facClosNoNei : m_d_crossingNeighboredNotEndingFaces )
    2320            0 :                                         for( Face * facClosNoNei : vecNeighbouredFacesClosedFract )
    2321              :                                         {
    2322            0 :                                                 if( facClosNoNei == facClos )
    2323              :                                                 {
    2324              :                                                         facGiven = true;
    2325              :                                                         break;
    2326              :                                                 }
    2327              :                                         }
    2328              : 
    2329            0 :                                         if( ! facGiven )
    2330              :                                         {
    2331              :                                                 //  commented out the debug members:  m_d_notEndingCrossingFacesNotNeighbour.push_back( facClos );
    2332            0 :                                                 vecClosedFracFacNoNeighbr.push_back( facClos );
    2333              :                                         }
    2334              :                                 }
    2335              : 
    2336              : 
    2337              :                                 UG_LOG("Faces vielleicht gefunden an ending crossing cleft " << std::endl);
    2338              : 
    2339              :                                 //                              Face * endingFractManifCutting = nullptr;
    2340              :                                 //                              Face * endingFractManifNotCutting = nullptr;
    2341              :                                 //                              Edge * oldLowDimElCut = nullptr;
    2342              :                                 //                              std::pair<Face*,Face*> pairNeighbouredFractClosedManifEl(nullptr,nullptr);
    2343              :                                 //                              IndexType sudoFractEnding = std::numeric_limits<IndexType>::max();
    2344              :                                 //                              IndexType sudoFractNotEnding = std::numeric_limits<IndexType>::max();
    2345              : 
    2346              :                                 std::vector<Face*> vecContEndingFractFaceCutting; // must have size two after been filled but both same content
    2347              :                                 std::vector<Face*> vecContEndingFractFaceNotCutting; // must have size maximum two same content both, or zero
    2348              :                                 std::vector<Face*> vecContNeighbouredFacesClosedFract; // must have size 2
    2349              : 
    2350              : 
    2351              :                                 std::vector<IndexType> vecContSudoFractFacsEnding; // must be filled with same number
    2352              :                                 std::vector<IndexType> vecContSudoFractFacsNotEnding; // must be filled with same number
    2353              : 
    2354            0 :                                 if( vecEndingFractFaceCutting.size() == 2 )
    2355              :                                 {
    2356            0 :                                         if( ! checkIfContentUnique( vecEndingFractFaceCutting, vecContEndingFractFaceCutting, 1 ) )
    2357              :                                         {
    2358            0 :                                                 for( Face * fac : vecEndingFractFaceCutting  )
    2359              :                                                 {
    2360            0 :                                                         m_sh.assign_subset( fac, m_sh.num_subsets());
    2361              : 
    2362            0 :                                                         UG_LOG("fract face cutting strange behaviour at " << CalculateCenter( fac, m_aaPos ) << std::endl);
    2363              :                                                 }
    2364              : 
    2365              :                                                 UG_LOG("Problem with cutting fac " << std::endl);
    2366              :                                                 return false;
    2367              :                                                 UG_THROW("Problem with cutting fac " << std::endl);
    2368              :                                         }
    2369              :                                 }
    2370              :                                 else
    2371              :                                 {
    2372            0 :                                         UG_THROW("Problem with cutting fac size " << std::endl);
    2373              : 
    2374              :                                 }
    2375              : 
    2376            0 :                                 Face * endingFractManifCutting = vecContEndingFractFaceCutting[0];
    2377              : //
    2378              : //                              std::vector<Face> endingFractManifNotCutting; // = nullptr;
    2379              : //
    2380              : //                              if( vecEndingFractFaceNotCutting.size() != 0 )
    2381              : //                              {
    2382              : //                                      if( vecEndingFractFaceNotCutting.size() == 1 )
    2383              : //                                      {
    2384              : //                                              if( ! checkIfContentUnique( vecEndingFractFaceNotCutting, vecContEndingFractFaceNotCutting, 1 ) )
    2385              : //                                              {
    2386              : //                                                      UG_THROW("Problem with not cutting fac " << std::endl);
    2387              : //                                              }
    2388              : //
    2389              : //                                              endingFractManifNotCutting = vecContEndingFractFaceNotCutting[0];
    2390              : //
    2391              : //                                      }
    2392              : //                                      else
    2393              : //                                      {
    2394              : //                                              for( Face * fac : vecEndingFractFaceNotCutting )
    2395              : //                                              {
    2396              : //                                                      m_sh.assign_subset( fac, m_sh.num_subsets() );
    2397              : //                                              }
    2398              : //
    2399              : //                                              UG_LOG("schief gegangen " << std::endl);
    2400              : //                                              UG_LOG("Problem with not cutting fac size " << vecEndingFractFaceNotCutting.size() << std::endl);
    2401              : //
    2402              : //                                              return false;
    2403              : //                                              UG_THROW("Problem with not cutting fac size " << vecEndingFractFaceNotCutting.size() << std::endl);
    2404              : //
    2405              : //                                      }
    2406              : //
    2407              : //                              }
    2408              : 
    2409              : 
    2410            0 :                                 if( vecNeighbouredFacesClosedFract.size() == 2  )
    2411              :                                 {
    2412            0 :                                         if( ! checkIfContentUnique( vecNeighbouredFacesClosedFract, vecContNeighbouredFacesClosedFract, 2 ) )
    2413              :                                         {
    2414            0 :                                                 UG_THROW("Problem with neigh clos fac " << std::endl);
    2415              :                                         }
    2416              : 
    2417              :                                 }
    2418              :                                 else
    2419              :                                 {
    2420            0 :                                         UG_THROW("Problem with neigh clos fac size " << std::endl);
    2421              :                                 }
    2422              : 
    2423              :                                 std::pair<Face*,Face*> pairNeighbouredFractClosedManifEl( vecContNeighbouredFacesClosedFract[0],
    2424              :                                                                                                                                                   vecContNeighbouredFacesClosedFract[1]
    2425              :                                                                                                                                                  );
    2426              : 
    2427              : 
    2428            0 :                                 if(  ! checkIfContentUnique( vecSudoFractFacsEnding, vecContSudoFractFacsEnding, 1 ) )
    2429              :                                 {
    2430            0 :                                         UG_THROW("Problem with sudo ending " << std::endl);
    2431              :                                 }
    2432              : 
    2433            0 :                                 IndexType sudoFractEnding = vecContSudoFractFacsEnding[0];
    2434              : 
    2435            0 :                                 if(  ! checkIfContentUnique( vecSudoFractFacsNotEnding, vecContSudoFractFacsNotEnding, 1 ) )
    2436              :                                 {
    2437            0 :                                         UG_THROW("Problem with sudo not ending " << std::endl);
    2438              :                                 }
    2439              : 
    2440              : 
    2441            0 :                                 IndexType sudoFractNotEnding = vecContSudoFractFacsNotEnding[0];
    2442              : 
    2443              :                                 std::vector<Edge*> vecContCuttingEdges; // must contain only same element, twice
    2444              : 
    2445            0 :                                 if( vecCuttingEdges.size() == 2 )
    2446              :                                 {
    2447            0 :                                         if(  ! checkIfContentUnique( vecCuttingEdges, vecContCuttingEdges, 1 ) )
    2448              :                                         {
    2449            0 :                                                 UG_THROW("Problem with edges unique " << std::endl);
    2450              :                                         }
    2451              : 
    2452              :                                 }
    2453              :                                 else
    2454              :                                 {
    2455            0 :                                         UG_THROW("Problem with edges unique size " << std::endl);
    2456              : 
    2457              :                                 }
    2458              : 
    2459            0 :                                 Edge * oldLowDimElCut = vecContCuttingEdges[0];
    2460              : 
    2461              :                                 UG_LOG("Pushing back Edge" << std::endl);
    2462              : 
    2463              :                                 std::vector<Edge*> vecContUncuttingEdge; // must get same elemes twice
    2464              : 
    2465            0 :                                 if( vecUncuttingEdge.size() == 2 )
    2466              :                                 {
    2467            0 :                                         if(  ! checkIfContentUnique( vecUncuttingEdge, vecContUncuttingEdge, 1 ) )
    2468              :                                         {
    2469            0 :                                                 UG_THROW("Problem with edges shift unique " << std::endl);
    2470              :                                         }
    2471              : 
    2472              :                                 }
    2473              :                                 else
    2474              :                                 {
    2475            0 :                                         UG_THROW("Problem with edges shift unique size " << std::endl);
    2476              : 
    2477              :                                 }
    2478              : 
    2479            0 :                                 Edge * uncuttingLowDimEl = vecContUncuttingEdge[0];
    2480              : 
    2481            0 :                                 Edge * shiftLowDimEl = nullptr;
    2482              : 
    2483              :                                 std::vector<Edge*> vecEdgsNotCutFaces;
    2484              : 
    2485            0 :                                 if( ! findShiftEdgeUncuttingCrossingCleft( vecSegmLimSiFFUnclosed,
    2486              : //                                                                                                                 endingFractManifCutting,
    2487              :                                                                                                                vecEndingFractFaceNotCutting,
    2488              :                                                                                                                    uncuttingLowDimEl,
    2489              :                                                                                                                    shiftLowDimEl,
    2490              :                                                                                                                    vecEdgsNotCutFaces
    2491              :                                                                                                                   )
    2492              :                                         )
    2493              :                                 {
    2494              :                                         UG_LOG("Kein shift Element gefunden" << std::endl);
    2495            0 :                                         UG_THROW("Kein shift Element gefunden" << std::endl);
    2496              :                                 }
    2497              : 
    2498            0 :                                 if( shiftLowDimEl == nullptr )
    2499              :                                 {
    2500              :                                         UG_LOG("SHift El null " << std::endl);
    2501            0 :                                         UG_THROW("SHift El null " << std::endl);
    2502              :                                 }
    2503              : 
    2504            0 :                                 if(  vecClosedFracFacNoNeighbr.size() + vecNeighbouredFacesClosedFract.size()
    2505              :                                         !=  vecSegmLimSiFFClosed.size()
    2506              :                                 )
    2507              :                                 {
    2508            0 :                                         UG_THROW("size sum clos not fit " << std::endl);
    2509              :                                 }
    2510              : 
    2511              :                                 EndingCrossingFractureSegmentInfo ecfsi( vrt,
    2512              :                                                                                                              endingFractManifCutting,
    2513              :                                                                                                              vecEndingFractFaceNotCutting,
    2514              :                                                                                                                  oldLowDimElCut,
    2515              :                                                                                                                  pairNeighbouredFractClosedManifEl,
    2516              :                                                                                                                  shiftLowDimEl,
    2517              :                                                                                                                  vecEdgsNotCutFaces,
    2518              :                                                                                                                  sudoFractEnding,
    2519              :                                                                                                                  sudoFractNotEnding
    2520            0 :                                                                                                             );
    2521              : 
    2522              :                                 ecfsi.schluckVecClosedFracManifElNoNeighbr( vecClosedFracFacNoNeighbr );
    2523              : 
    2524              :                                 ecfsi.schluckVecFulldimElm( volsOfUnclosedSegm );
    2525              : 
    2526            0 :                                 m_vrtxAttAccsVecEndingCrossFractSegmInfo[vrt].push_back( ecfsi );
    2527              : 
    2528            0 :                                 m_vecEndCrossFractSegmInfo.push_back( ecfsi );
    2529              : 
    2530              : 
    2531            0 :                                 segLimSids.schluckLowdimElmShiftDirectionIfUnclosedFractPresent(shiftLowDimEl);
    2532              : 
    2533              :                                 // schlechte Idee: die segment limiting sides müssen die ganze EndingCrossingFractureSegmentInfo zu wissen bekommen
    2534              :                                 // klar alternativ sollte die shift direction reichen, um die ending crossing fracture segment info rekonstruieren zu können
    2535              :                                 // wäre aber ein Umweg!!!
    2536              :                                 // besser aber der Umweg, ansonsten entsteht das Henne Ei Problem:
    2537              :                                 // wer ist von was der Ursprung? wer schluckt was,
    2538              :                                 // die Segment Seite die Ending crossing fracture segment info, oder umgekehrt?
    2539              :                                 // und wenn es dann als Kopie geschluckt wird, was passiert wenn was verändert wird,
    2540              :                                 // es müssten also Pointer sein, und es entsteht eine unsinnige Kaskade.....
    2541              : 
    2542            0 :                         }
    2543              :                 }
    2544              : 
    2545              :         }
    2546              : 
    2547              :         UG_LOG("detected ending crossing cleft faces " << numEndingCrossingClefts << std::endl);
    2548              : 
    2549              :         UG_LOG("EDGES number " << m_vecEdgeDirectConnectingEndingCrossCleftVrtcs.size() << std::endl);
    2550              : 
    2551              : //      if( m_d_endingCrossingCleftVrtcs.size() == 0 )
    2552              : //              return true;
    2553              : 
    2554            0 :         if( splitEdgesOfNeighboredEndingCrossingFracVrtcs() )
    2555              :         {
    2556              :                 UG_LOG("needed to split, please restart with this geometry" << std::endl);
    2557            0 :                 m_needToSplitEdgesConnectingNeighbrdEndingCrossCleftVrtx = true;
    2558            0 :                 return false;
    2559              :         }
    2560              :         else
    2561              :         {
    2562            0 :                 m_needToSplitEdgesConnectingNeighbrdEndingCrossCleftVrtx = false;
    2563              :         }
    2564              : 
    2565              : //      return true;
    2566              : 
    2567              : 
    2568            0 :         for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    2569              :         {
    2570              :                 Vertex* vrt = *iter;
    2571              : 
    2572              :                 VecSegmentLimitingSides & vecSegmLimSid = m_vrtxAttAccsVecSegmLimSid[vrt];
    2573              : 
    2574            0 :                 for( SegmentLimitingSides const & sls : vecSegmLimSid )
    2575              :                 {
    2576            0 :                         if( sls.hasUnclosedFaces())
    2577              :                                 UG_LOG("Hier nach detect hat das Gesicht noch ungeschlossene " << std::endl);
    2578              :                 }
    2579              : 
    2580              :         }
    2581              : 
    2582              :         if( numEndingCrossingClefts == 0 )
    2583              :                         return true;
    2584              : 
    2585              : //      assignDebugSubsets( true );
    2586              : //
    2587              : //      UG_LOG("problematic elements highlighted " << std::endl);
    2588              : 
    2589              :         return true;
    2590              : 
    2591              : 
    2592              : 
    2593              : //      if( numEndingCrossingClefts == 0 )
    2594              : //              return true;
    2595              : //
    2596              : //      // debug for ending crossing clefts
    2597              : //
    2598              : //      for( Face * fac : m_d_endingCrossingCleftFaces )
    2599              : //      {
    2600              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
    2601              : //
    2602              : //      }
    2603              : //
    2604              : //      for( Vertex * vrt : m_d_endingCrossingCleftVrtcs )
    2605              : //      {
    2606              : //              m_sh.assign_subset( vrt, m_sh.num_subsets());
    2607              : //      }
    2608              : //
    2609              : //      for( Edge * edg : m_d_cuttingEdges )
    2610              : //      {
    2611              : //              if( edg == nullptr )
    2612              : //              {
    2613              : //                      UG_LOG("NULL UNERLAUBT" << std::endl);
    2614              : //                      UG_THROW("NULL UNERLAUBT" << std::endl);
    2615              : //              }
    2616              : //
    2617              : //              m_sh.assign_subset( edg, m_sh.num_subsets());
    2618              : //
    2619              : //      }
    2620              : //
    2621              : //      for( Face * fac : crossingNotEndingFaces )
    2622              : //      {
    2623              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
    2624              : //      }
    2625              : //
    2626              : //      for( Edge * edg : otherEdgeOfCrossingNotEndingFace )
    2627              : //      {
    2628              : //              if( edg == nullptr )
    2629              : //              {
    2630              : //                      UG_LOG("NULL C UNERLAUBT" << std::endl);
    2631              : //                      UG_THROW("NULL C UNERLAUBT" << std::endl);
    2632              : //              }
    2633              : //
    2634              : //              m_sh.assign_subset( edg, m_sh.num_subsets());
    2635              : //
    2636              : //      }
    2637              : //
    2638              : //      for( Face * fac : nextFaceOfCrossingNotEndingFaces )
    2639              : //      {
    2640              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
    2641              : //      }
    2642              : //
    2643              : //
    2644              : //      return false;
    2645              : }
    2646              : 
    2647              : //////////////////////////////////////////////////////////////////
    2648              : 
    2649            0 : bool ArteExpandFracs3D::assignNotCuttingEdgeUnclosedCrossingCleft( SegLimSidesFractFace const & slsffUncl, Edge * const & commonEdge, Edge * & shiftEdge )
    2650              : {
    2651              :         EdgePair const & edgesFac = slsffUncl.getPairLowElm();
    2652              : 
    2653              :         Edge * edgeFrst = edgesFac.first;
    2654              :         Edge * edgeScnd = edgesFac.second;
    2655              : 
    2656            0 :         if( edgeFrst == commonEdge )
    2657              :         {
    2658            0 :                 shiftEdge = edgeScnd;
    2659              :         }
    2660            0 :         else if( edgeScnd == commonEdge )
    2661              :         {
    2662            0 :                 shiftEdge = edgeFrst;
    2663              :         }
    2664              :         else
    2665              :         {
    2666              :                 UG_LOG("common and shift edge different face " << std::endl);
    2667            0 :                 UG_THROW("common and shift edge different face " << std::endl);
    2668              :         }
    2669              : 
    2670            0 :         if( shiftEdge != nullptr )
    2671              :                 return true;
    2672              : 
    2673              :         UG_LOG("shift edge null" << std::endl);
    2674              : 
    2675              :         return false;
    2676              : 
    2677              : }
    2678              : 
    2679              : //////////////////////////////////////////////////////////////////
    2680              : 
    2681            0 : bool ArteExpandFracs3D::findShiftEdgeUncuttingCrossingCleft( VecSegLimSidesFractFace const & vecSegmLimSiFFUnclosed,
    2682              : //                                                                                                                       Face * const & endingFractManifCutting,
    2683              :                                                                                                                      std::vector<Face*> const & vecEndingFractManifNotCutting,
    2684              :                                                                                                                          Edge * const & uncuttingLowDimEl,
    2685              :                                                                                                                          Edge * & shiftLowDimEl,
    2686              :                                                                                                                          std::vector<Edge*> & vecEdgsNotCutFaces
    2687              :                                                                                                                         )
    2688              : {
    2689              : 
    2690            0 :         if( uncuttingLowDimEl == nullptr )
    2691              :         {
    2692              :                 UG_LOG("null uncut" << std::endl );
    2693            0 :                 UG_THROW("null uncut" << std::endl );
    2694              :         }
    2695              : 
    2696            0 :         if( vecEndingFractManifNotCutting.size() == 0 )
    2697              :         {
    2698            0 :                 shiftLowDimEl = uncuttingLowDimEl;
    2699            0 :                 return true;
    2700              :         }
    2701              : 
    2702              :         std::vector<Edge*> vecEdgsCollectMulti;
    2703              : 
    2704              :         std::vector<Edge*> vecEdgsCollectSingle;
    2705              : 
    2706            0 :         for( SegLimSidesFractFace const & slsffUncl : vecSegmLimSiFFUnclosed )
    2707              :         {
    2708              : 
    2709              :                 Face * facUncl = slsffUncl.getManifElm();
    2710              : 
    2711            0 :                 for( Face * facNotCut : vecEndingFractManifNotCutting )
    2712              :                 {
    2713            0 :                         if( facNotCut == facUncl )
    2714              :                         {
    2715              :                                 EdgePair const & epU = slsffUncl.getPairLowElm();
    2716              : 
    2717            0 :                                 Edge * edgeOne = epU.first;
    2718            0 :                                 Edge * edgeTwo = epU.second;
    2719              : 
    2720            0 :                                 if( edgeOne != uncuttingLowDimEl )
    2721              :                                 {
    2722            0 :                                         vecEdgsCollectMulti.push_back(edgeOne);
    2723              : 
    2724              :                                         addElem(vecEdgsCollectSingle, edgeOne);
    2725              :                                 }
    2726              : 
    2727            0 :                                 if( edgeTwo != uncuttingLowDimEl )
    2728              :                                 {
    2729            0 :                                         vecEdgsCollectMulti.push_back(edgeTwo);
    2730              : 
    2731              :                                         addElem(vecEdgsCollectSingle,edgeTwo);
    2732              :                                 }
    2733              :                         }
    2734              :                 }
    2735              :         }
    2736              : 
    2737            0 :         if(    ( vecEdgsCollectMulti.size() != vecEdgsCollectSingle.size() * 2 - 1  )
    2738            0 :                 || ( vecEdgsCollectMulti.size() != ( ( vecSegmLimSiFFUnclosed.size() - 1 ) * 2 ) - 1  )
    2739            0 :                 || ( vecEdgsCollectSingle.size() != vecSegmLimSiFFUnclosed.size() - 1 )
    2740              :           )
    2741              :         {
    2742              :                 UG_LOG("Konzept der wilden Ecken schief gegangen " << std::endl);
    2743              : 
    2744              :                 UG_LOG("multi " << vecEdgsCollectMulti.size() << std::endl );
    2745              :                 UG_LOG("single " << vecEdgsCollectSingle.size() << std::endl );
    2746              :                 UG_LOG("segm uncl " << vecSegmLimSiFFUnclosed.size() << std::endl );
    2747              : 
    2748            0 :                 UG_THROW("Konzept der wilden Ecken schief gegangen " << std::endl);
    2749              :         }
    2750              : 
    2751              :         IndexType numShiftEdgFnd = 0;
    2752              : 
    2753            0 :         for( Edge * eS : vecEdgsCollectSingle )
    2754              :         {
    2755              :                 IndexType singleFoundInMulti = 0;
    2756              : 
    2757            0 :                 for( Edge * eM : vecEdgsCollectMulti )
    2758              :                 {
    2759            0 :                         if( eS == eM )
    2760            0 :                                 singleFoundInMulti++;
    2761              :                 }
    2762              : 
    2763            0 :                 if( singleFoundInMulti == 1 )
    2764              :                 {
    2765              :                         numShiftEdgFnd++;
    2766              : 
    2767            0 :                         shiftLowDimEl = eS;
    2768              :                 }
    2769            0 :                 else if( singleFoundInMulti == 2 )
    2770              :                 {
    2771            0 :                         vecEdgsNotCutFaces.push_back( eS );
    2772              :                 }
    2773              :                 else
    2774              :                 {
    2775              :                         UG_LOG("Edge not in useful number " << singleFoundInMulti << std::endl);
    2776            0 :                         UG_THROW("Edge not in useful number " << singleFoundInMulti << std::endl);
    2777              :                 }
    2778              : 
    2779              :         }
    2780              : 
    2781              :         return true;
    2782              : 
    2783              : //      IndexType edgeWasFound = 0;
    2784              : 
    2785              : //      for( SegLimSidesFractFace const & slsffUncl : vecSegmLimSiFFUnclosed )
    2786              : //      {
    2787              : //
    2788              : //              Face * facUncl = slsffUncl.getManifElm();
    2789              : //
    2790              : //              if( facUncl == endingFractManifNotCutting )
    2791              : //              {
    2792              : //                      EdgePair const & epU = slsffUncl.getPairLowElm();
    2793              : //
    2794              : //                      Edge * edgeOne = epU.first;
    2795              : //                      Edge * edgeTwo = epU.second;
    2796              : //
    2797              : //                      if( edgeOne == uncuttingLowDimEl )
    2798              : //                      {
    2799              : //                              shiftLowDimEl = edgeTwo;
    2800              : //                      }
    2801              : //                      else if( edgeTwo == uncuttingLowDimEl )
    2802              : //                      {
    2803              : //                              shiftLowDimEl = edgeOne;
    2804              : //                      }
    2805              : //                      else
    2806              : //                      {
    2807              : //                              UG_LOG("No edge found uncutting shift?" << std::endl);
    2808              : //                              UG_THROW("No edge found uncutting shift?" << std::endl);
    2809              : //                      }
    2810              : //
    2811              : //                      edgeWasFound++;
    2812              : //
    2813              : //              }
    2814              : //      }
    2815              : //
    2816              : //      if( edgeWasFound == 0 )
    2817              : //      {
    2818              : //              UG_LOG("NO shift edge " << std::endl);
    2819              : //              return false;
    2820              : //      }
    2821              : //      else if( edgeWasFound == 1 )
    2822              : //      {
    2823              : //              return true;
    2824              : //      }
    2825              : //      if( edgeWasFound > 1 )
    2826              : //      {
    2827              : //              UG_LOG("Many shift edges " << edgeWasFound << std::endl);
    2828              : //              return false;
    2829              : //      }
    2830              : 
    2831              :         UG_LOG("Cannot come here at this edge" << std::endl);
    2832              : 
    2833              :         return false;
    2834              : 
    2835            0 : }
    2836              : 
    2837              : //////////////////////////////////////////////////////////////////
    2838              : 
    2839              : template<typename ELMTYP>
    2840            0 : bool ArteExpandFracs3D::checkIfContentUnique( std::vector<ELMTYP> const & vecTest, std::vector<ELMTYP> & content, IndexType mandatoryDifferentElems )
    2841              : {
    2842            0 :         if( vecTest.size() == 0 )
    2843              :         {
    2844              :                 UG_LOG("zero vector testing nonsense" << std::endl);
    2845            0 :                 UG_THROW("zero vector testing nonsense" << std::endl);
    2846              :         }
    2847              : 
    2848            0 :         std::vector<ELMTYP> vecTestCop = vecTest; // copy
    2849              : 
    2850            0 :         while( vecTestCop.size() != 0 )
    2851              :         {
    2852            0 :                 ELMTYP elmCont = vecTestCop[0];
    2853              : 
    2854            0 :                 content.push_back(elmCont);
    2855              : 
    2856            0 :                 for( typename std::vector<ELMTYP>::iterator itEl = vecTestCop.begin(); itEl != vecTestCop.end(); )
    2857              :                 {
    2858            0 :                         ELMTYP elmTest = *itEl;
    2859              : 
    2860            0 :                         if( elmCont == elmTest )
    2861              :                         {
    2862              :                                 itEl = vecTestCop.erase(itEl);
    2863              :                         }
    2864              :                         else
    2865              :                                 ++itEl;
    2866              :                 }
    2867              : 
    2868              :         }
    2869              : 
    2870            0 :         return ( mandatoryDifferentElems == content.size() );
    2871            0 : }
    2872              : 
    2873              : //////////////////////////////////////////////////////////////////
    2874              : 
    2875              : template< bool FACES_HAVE_SAME_SUDO >
    2876            0 : bool ArteExpandFracs3D::fractFacesAreNeighboured( SegLimSidesFractFace const & fractFaceOne,
    2877              :                                                                                                   SegLimSidesFractFace const & fractFaceTwo,
    2878              :                                                                                                   Edge * & commonEdge
    2879              :                                                                                                 )
    2880              : {
    2881            0 :         commonEdge = nullptr; // general case
    2882              : 
    2883              :         bool facesHaveSameSudo = FACES_HAVE_SAME_SUDO;
    2884              : 
    2885              :         // exclude that the elements are the same
    2886              : 
    2887              :         Face * facOne = fractFaceOne.getManifElm();
    2888              :         Face * facTwo = fractFaceTwo.getManifElm();
    2889              : 
    2890            0 :         if( facOne == facTwo )
    2891              :         {
    2892              :                 UG_LOG("Faces coincide" << std::endl);
    2893            0 :                 return false;
    2894              :         }
    2895              : 
    2896              :         EdgePair const & edgesFacOne = fractFaceOne.getPairLowElm();
    2897              :         EdgePair const & edgesFacTwo = fractFaceTwo.getPairLowElm();
    2898              : 
    2899              :         Edge * edgeOneFrst = edgesFacOne.first;
    2900              :         Edge * edgeOneScnd = edgesFacOne.second;
    2901              : 
    2902              :         Edge * edgeTwoFrst = edgesFacTwo.first;
    2903              :         Edge * edgeTwoScnd = edgesFacTwo.second;
    2904              : 
    2905            0 :         bool edgeCondA = ( edgeOneFrst == edgeTwoFrst );
    2906            0 :         bool edgeCondB = ( edgeOneFrst == edgeTwoScnd );
    2907            0 :         bool edgeCondC = ( edgeOneScnd == edgeTwoFrst );
    2908            0 :         bool edgeCondD = ( edgeOneScnd == edgeTwoScnd );
    2909              : 
    2910              : 
    2911              :         bool fractFacsNeighbr = (    edgeCondA
    2912            0 :                                                           || edgeCondB
    2913              :                                                           || edgeCondC
    2914            0 :                                                           || edgeCondD
    2915              :                                                         );
    2916              : 
    2917              :         IndexType sudoOne = fractFaceOne.getSudo();
    2918              :         IndexType sudoTwo = fractFaceTwo.getSudo();
    2919              : 
    2920              :         bool sudosCoincide = ( sudoOne == sudoTwo );
    2921              : 
    2922            0 :         bool necessarySudoProperty = ( facesHaveSameSudo == sudosCoincide );
    2923              : 
    2924            0 :         bool neighbrsWithRequestedSudo = ( fractFacsNeighbr && necessarySudoProperty );
    2925              : 
    2926            0 :         if( neighbrsWithRequestedSudo )
    2927              :         {
    2928            0 :                 if( edgeCondA || edgeCondB )
    2929              :                 {
    2930            0 :                         commonEdge = edgeOneFrst;
    2931              :                 }
    2932            0 :                 else if( edgeCondC || edgeCondD )
    2933              :                 {
    2934            0 :                         commonEdge = edgeOneScnd;
    2935              :                 }
    2936              : 
    2937            0 :                 if( commonEdge == nullptr )
    2938              :                 {
    2939              :                         UG_LOG("COMMON NULL " << std::endl);
    2940            0 :                         UG_THROW("COMMON NULL " << std::endl);
    2941              :                 }
    2942              :                 else
    2943              :                 {
    2944            0 :                         UG_LOG("COORDINATES NOT NULL " << CalculateCenter( commonEdge, m_aaPos ) << std::endl );
    2945              :                 }
    2946              :         }
    2947              : 
    2948              :         return neighbrsWithRequestedSudo;
    2949              : }
    2950              : 
    2951              : 
    2952              : //////////////////////////////////////////////////////////////////
    2953              : 
    2954              : 
    2955              : #if 0
    2956              : bool ArteExpandFracs3D::detectEndingCrossingClefts()
    2957              : {
    2958              : //      bool unclosedFracFacesPresent = false;
    2959              : //
    2960              : //      for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    2961              : //      {
    2962              : //              Vertex* vrt = *iter;
    2963              : //
    2964              : //              IndexType shiFraFac = shiftUnclosedFracFacesToUnclosedFractFaces( vrt );
    2965              : //
    2966              : //              UG_LOG("shifted frac faces at " << m_aaPos[vrt] << " -> " << shiFraFac << std::endl);
    2967              : //
    2968              : //              if( shiFraFac > 0 )
    2969              : //                      unclosedFracFacesPresent = true;
    2970              : //
    2971              : ////            constexpr bool d_highlightVrtcsWithShifts = false;
    2972              : ////
    2973              : ////            if( d_highlightVrtcsWithShifts )
    2974              : ////            {
    2975              : ////                    if( shiFraFac > 0 )
    2976              : ////                    {
    2977              : ////                            IndexType sudoNum = m_sh.num_subsets();
    2978              : ////
    2979              : ////                            m_sh.assign_subset(vrt, sudoNum );
    2980              : ////                    }
    2981              : ////            }
    2982              : //      }
    2983              : 
    2984              :         IndexType numEndingCrossingClefts = 0;
    2985              : 
    2986              :         std::vector<Face*> m_d_endingCrossingCleftFaces;
    2987              : 
    2988              :         std::vector<Vertex*> m_d_endingCrossingCleftVrtcs;
    2989              : 
    2990              : 
    2991              : //      for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    2992              : //      {
    2993              : //              Vertex* vrt = *iter;
    2994              : //
    2995              : //
    2996              : //
    2997              : //      }
    2998              : 
    2999              : 
    3000              : 
    3001              :         // TODO FIXME unterscheide Faces entlang der expandierten Kreuzungskluft,
    3002              :         // mit 2 Knoten an Kreuzungspunkten, ein Knoten voll expandiert für beide subsets
    3003              :         // von solchen, die in der Luft hängen am Ende der Kluft, wo nur die durchgehende Kluft expandiert
    3004              : 
    3005              :         // TODO FIXME need to detect attached faces from the durchgehende cleft which gets expanded
    3006              :         // as specific structures needed also there
    3007              : 
    3008              :         // TODO FIXME auch die Kante, die an dem auslaufenden Face entlang geht im Schnitt mit dem ausgedehnten,
    3009              :         // per edge attachment markieren! bool
    3010              :         // und die anhängenden faces der kreuzenden durchgehenden Kluft ebenso markieren irgendwie per face attachment bool
    3011              : 
    3012              : 
    3013              : 
    3014              : 
    3015              : #if 1
    3016              : 
    3017              :         IndexType unclosedFracFacesFound = 0;
    3018              : 
    3019              :         for(size_t i_fi = 0; i_fi < m_fracInfos.size(); ++i_fi )
    3020              :         {
    3021              : 
    3022              :                 int fracIndSudo = m_fracInfos[i_fi].subsetIndex;
    3023              : 
    3024              :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); ++iter )
    3025              :                 {
    3026              :                         Face* fac = *iter;
    3027              : 
    3028              :                         UG_LOG("Check for unclosed frac faces " << CalculateCenter(fac, m_aaPos) << std::endl);
    3029              : 
    3030              :                         if( m_aaMarkFaceHasUnclosedFracSideB[fac] )
    3031              :                         {
    3032              :                                 unclosedFracFacesFound++;
    3033              : 
    3034              : //                              m_sh.assign_subset( fac, m_sh.num_subsets());
    3035              :                         }
    3036              : 
    3037              :                 }
    3038              : 
    3039              :         }
    3040              : 
    3041              :         if( unclosedFracFacesFound > 0 ) // || unclosedFracFacesPresent )
    3042              :         {
    3043              :                 UG_LOG("unclosed Frac faces " << unclosedFracFacesFound << std::endl);
    3044              : //              return false;
    3045              :         }
    3046              : 
    3047              : //      return true;
    3048              : 
    3049              : 
    3050              :         //  wieso die ending crossing cleft faces nicht aus den Segmenten raus holen,
    3051              :         // und zwar aus den ungeschlossenen Faces, die im Segment liegen?
    3052              :         // müssen doch dieselben sein, dann sollte die komische Prozedur hier unnötig werden!!!
    3053              : 
    3054              : 
    3055              : //      UG_THROW("KÄSE" << std::endl);
    3056              : 
    3057              :         for(size_t i_fi = 0; i_fi < m_fracInfos.size(); ++i_fi )
    3058              :         {
    3059              :                 int fracIndSudo = m_fracInfos[i_fi].subsetIndex;
    3060              : 
    3061              :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); iter++ )
    3062              :                 {
    3063              :                         Face* fac = *iter;
    3064              : 
    3065              :                         UG_LOG("Detect for unclosed ending cleft frac faces " << CalculateCenter(fac, m_aaPos) << std::endl);
    3066              : 
    3067              :                         if( m_aaMarkFaceHasUnclosedFracSideB[fac] )
    3068              :                         {
    3069              : 
    3070              :                                 // figure out the vertice(s) where the face is unclosed
    3071              :                                 // check if at one of these vertices, two fractures are crossing and one ending
    3072              :                                 // by checking if there are at least two segments as precondition, else no matter
    3073              : 
    3074              :                                 std::vector<Vertex *> assoVrt;
    3075              : 
    3076              :                                 CollectVertices(assoVrt, m_grid, fac);
    3077              : 
    3078              :                                 for( Vertex * vrt : assoVrt )
    3079              :                                 {
    3080              :                                         if( m_aaMarkVrtxHasUnclosedFracB[vrt] )
    3081              :                                         {
    3082              :                                                 VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[vrt];
    3083              : 
    3084              :                                                 if( vecSegVolElmInf.size() > 1 ) // expansion takes place here
    3085              :                                                 {
    3086              : //                                                      m_sh.assign_subset(fac,m_sh.num_subsets());
    3087              :                                                         numEndingCrossingClefts++;
    3088              :                                                         m_d_endingCrossingCleftFaces.push_back(fac);
    3089              :                                                         m_d_endingCrossingCleftVrtcs.push_back(vrt);
    3090              :                                                         // TODO FIXME vielleicht eine Klasse, wo die Faces und Vertices einer
    3091              :                                                         // jeweiligen ending Crossing Cleft Stelle zusammengefasst werden?
    3092              :                                                         // statt unabhängige Listen? gemeinsame Liste?
    3093              :                                                 }
    3094              : 
    3095              :                                         }
    3096              :                                 }
    3097              : 
    3098              : 
    3099              :                         }
    3100              : 
    3101              :                 }
    3102              : 
    3103              :         }
    3104              : 
    3105              : 
    3106              :         UG_LOG("detected ending crossing cleft faces " << numEndingCrossingClefts << std::endl);
    3107              : 
    3108              :         if( numEndingCrossingClefts == 0 )
    3109              :                 return true;
    3110              : 
    3111              :         // debug for ending crossing clefts
    3112              : 
    3113              :         for( Face * fac : m_d_endingCrossingCleftFaces )
    3114              :         {
    3115              :                 m_sh.assign_subset( fac, m_sh.num_subsets());
    3116              : 
    3117              :         }
    3118              : 
    3119              :         for( Vertex * vrt : m_d_endingCrossingCleftVrtcs )
    3120              :         {
    3121              :                 m_sh.assign_subset( vrt, m_sh.num_subsets());
    3122              :         }
    3123              : 
    3124              : #endif
    3125              : 
    3126              : 
    3127              :         return false;
    3128              : 
    3129              : 
    3130              : 
    3131              : }
    3132              : 
    3133              : #endif
    3134              : 
    3135              : ////////////////////////////////////////////////////////////////////
    3136              : 
    3137              : #if 0
    3138              : bool ArteExpandFracs3D::detectEndingCrossingClefts()
    3139              : {
    3140              : 
    3141              :         //  wieso die ending crossing cleft faces nicht aus den Segmenten raus holen,
    3142              :         // und zwar aus den ungeschlossenen Faces, die im Segment liegen?
    3143              :         // müssen doch dieselben sein, dann sollte die komische Prozedur hier unnötig werden!!!
    3144              : 
    3145              :         IndexType numEndingCrossingClefts = 0;
    3146              : 
    3147              :         std::vector<Face*> m_d_endingCrossingCleftFaces;
    3148              : 
    3149              :         std::vector<Vertex*> m_d_endingCrossingCleftVrtcs;
    3150              : 
    3151              : //      UG_THROW("KÄSE" << std::endl);
    3152              : 
    3153              :         for(size_t i_fi = 0; i_fi < m_fracInfos.size(); ++i_fi )
    3154              :         {
    3155              :                 int fracIndSudo = m_fracInfos[i_fi].subsetIndex;
    3156              : 
    3157              :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); iter++ )
    3158              :                 {
    3159              :                         Face* fac = *iter;
    3160              : 
    3161              :                         UG_LOG("Detect for unclosed ending cleft frac faces " << CalculateCenter(fac, m_aaPos) << std::endl);
    3162              : 
    3163              :                         if( m_aaMarkFaceHasUnclosedFracSideB[fac] )
    3164              :                         {
    3165              : 
    3166              :                                 // figure out the vertice(s) where the face is unclosed
    3167              :                                 // check if at one of these vertices, two fractures are crossing and one ending
    3168              :                                 // by checking if there are at least two segments as precondition, else no matter
    3169              : 
    3170              :                                 std::vector<Vertex *> assoVrt;
    3171              : 
    3172              :                                 CollectVertices(assoVrt, m_grid, fac);
    3173              : 
    3174              :                                 for( Vertex * vrt : assoVrt )
    3175              :                                 {
    3176              :                                         if( m_aaMarkVrtxHasUnclosedFracB[vrt] )
    3177              :                                         {
    3178              :                                                 VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[vrt];
    3179              : 
    3180              :                                                 if( vecSegVolElmInf.size() > 1 ) // expansion takes place here
    3181              :                                                 {
    3182              : //                                                      m_sh.assign_subset(fac,m_sh.num_subsets());
    3183              :                                                         numEndingCrossingClefts++;
    3184              :                                                         m_d_endingCrossingCleftFaces.push_back(fac);
    3185              :                                                         m_d_endingCrossingCleftVrtcs.push_back(vrt);
    3186              :                                                         // TODO FIXME vielleicht eine Klasse, wo die Faces und Vertices einer
    3187              :                                                         // jeweiligen ending Crossing Cleft Stelle zusammengefasst werden?
    3188              :                                                         // statt unabhängige Listen? gemeinsame Liste?
    3189              :                                                 }
    3190              : 
    3191              :                                         }
    3192              :                                 }
    3193              : 
    3194              : 
    3195              :                         }
    3196              : 
    3197              :                 }
    3198              : 
    3199              :         }
    3200              : 
    3201              :         // TODO FIXME m_d_endingCrossingCleftVrtcs      m_d_endingCrossingCleftFaces globale member vielleicht?
    3202              : 
    3203              : #if 0
    3204              : //      for( VertexIterator iterV = m_sel.begin<Vertex>(); iterV != m_sel.end<Vertex>(); iterV++ )
    3205              :         for( Vertex * vrt : m_d_endingCrossingCleftVrtcs )
    3206              :         {
    3207              : //              Vertex * vrt = *iterV;
    3208              : 
    3209              :                 // search neigbours of ending crossing cleft faces
    3210              : 
    3211              :                 if( m_aaMarkVrtxHasUnclosedFracB[vrt] )
    3212              :                 {
    3213              :                         VecSegmentVolElmInfo const & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[vrt];
    3214              : 
    3215              :                         for( SegmentVolElmInfo const & svei : vecSegVolElmInf )
    3216              :                         {
    3217              :                                 for( AttachedVolumeElemInfo const & attVolEI : svei )
    3218              :                                 {
    3219              :                                         VecAttachedFractFaceEdgeSudo vecAttFracFace = attVolEI.getVecFractManifElem();
    3220              :                                         // die sind alle von den echten das Segment begrenzenden Faces
    3221              : 
    3222              :                                         for( AttachedFractFaceEdgeSudo & afes : vecAttFracFace )
    3223              :                                         {
    3224              :                                                 Face * faceSegmLim = afes.getManifElm();
    3225              : 
    3226              :                                                 IndexType sudoSegmLim = afes.getSudo();
    3227              : 
    3228              :                                                 std::pair<Edge*,Edge*> const & edgePair = afes.getPairLowElm();
    3229              : 
    3230              :                                                 // figure out neighbours of ending crossing cleft faces at ending node
    3231              : 
    3232              :                                                 // rule out free edge
    3233              : 
    3234              :                                                 Edge * freeEdge = nullptr;
    3235              :                                                 Edge * boundedEdge = nullptr;
    3236              : 
    3237              :                                                 for( Face * eccf : m_d_endingCrossingCleftFaces )
    3238              :                                                 {
    3239              :                                                         if( FaceContains( eccf, vrt ) )
    3240              :                                                         {
    3241              :                                                                 if( eccf != fac )
    3242              :                                                                 {
    3243              :                                                                         if( FaceContains( eccf, edgePair.first ) || FaceContains( eccf, edgePair.second ) )
    3244              :                                                                         {
    3245              : 
    3246              :                                                                         }
    3247              :                                                                 }
    3248              :                                                         }
    3249              :                                                 }
    3250              : //                                              if( )
    3251              :                                         }
    3252              : 
    3253              :                                 }
    3254              : 
    3255              : 
    3256              :                         }
    3257              :                 }
    3258              :                 else
    3259              :                 {
    3260              :                         UG_LOG("only ending crossing cleft vertices allowed here" << std::endl);
    3261              :                         UG_THROW("only ending crossing cleft vertices allowed here" << std::endl);
    3262              :                         return false;
    3263              :                 }
    3264              : 
    3265              :         }
    3266              : 
    3267              : #endif
    3268              : 
    3269              : 
    3270              :         UG_LOG("detected ending crossing cleft faces " << numEndingCrossingClefts << std::endl);
    3271              : 
    3272              :         if( numEndingCrossingClefts == 0 )
    3273              :                 return true;
    3274              : 
    3275              :         // debug for ending crossing clefts
    3276              : 
    3277              :         for( Face * fac : m_d_endingCrossingCleftFaces )
    3278              :         {
    3279              :                 m_sh.assign_subset( fac, m_sh.num_subsets());
    3280              : 
    3281              :         }
    3282              : 
    3283              :         for( Vertex * vrt : m_d_endingCrossingCleftVrtcs )
    3284              :         {
    3285              :                 m_sh.assign_subset( vrt, m_sh.num_subsets());
    3286              :         }
    3287              : 
    3288              :         // TODO FIXME unterscheide Faces entlang der expandierten Kreuzungskluft,
    3289              :         // mit 2 Knoten an Kreuzungspunkten, ein Knoten voll expandiert für beide subsets
    3290              :         // von solchen, die in der Luft hängen am Ende der Kluft, wo nur die durchgehende Kluft expandiert
    3291              : 
    3292              :         // TODO FIXME need to detect attached faces from the durchgehende cleft which gets expanded
    3293              :         // as specific structures needed also there
    3294              : 
    3295              :         // TODO FIXME auch die Kante, die an dem auslaufenden Face entlang geht im Schnitt mit dem ausgedehnten,
    3296              :         // per edge attachment markieren! bool
    3297              :         // und die anhängenden faces der kreuzenden durchgehenden Kluft ebenso markieren irgendwie per face attachment bool
    3298              : 
    3299              :         return false;
    3300              : }
    3301              : 
    3302              : #endif
    3303              : 
    3304              : //////////////////////////////////////////////////////////////////
    3305              : 
    3306              : // TODO FIXME diese Funktion macht nur in Teilen das richtige
    3307              : // die ungeschlossenen Faces zeigen an, dass eine Kluft hier endet
    3308              : // wird bisher nicht berücksichtigt
    3309              : // irgendwie muss das markiert werden, damit die Kluft, die zu Ende geht.
    3310              : // im Durchstich trotzdem berücksichtigt wird
    3311            0 : ArteExpandFracs3D::IndexType ArteExpandFracs3D::shiftUnclosedFracFacesToUnclosedFractFaces( Vertex * const & vrt )
    3312              : {
    3313              :         IndexType shiftedFracFaces = 0;
    3314              : 
    3315              :         // TODO FIXME still to be implemented - shift those fracture faces which appear
    3316              :         // twice in the segment volumes, i.e. which are part of two volumes of the
    3317              :         // segment, i.e. which touch each other, but are not closed,
    3318              :         // shift them to the general faces, to avoid that they are taken into account
    3319              :         // for the creation of new vertices, they must not have any influence
    3320              : 
    3321              :         UG_LOG("SHIFT FRAC 2 GENER" << std::endl);
    3322              : 
    3323            0 :         VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[vrt];
    3324              : 
    3325              :         IndexType segmentNumber = 0;
    3326              : 
    3327              : 
    3328              : 
    3329            0 :         for( SegmentVolElmInfo & svei : vecSegVolElmInf )
    3330              :         {
    3331              : //              VecAttachedFractFaceEdgeSudo vecAttFractList;
    3332              : 
    3333            0 :                 for( AttachedVolumeElemInfo & attVolEIOne : svei )
    3334              :                 {
    3335              :                         VecAttachedFractFaceEdgeSudo vecAttFracFaceOne = attVolEIOne.getVecFractManifElem();
    3336              : 
    3337            0 :                         for( AttachedVolumeElemInfo & attVolEITwo : svei )
    3338              :                         {
    3339            0 :                                 if( ! attVolEIOne.hasSameFulldimElem( attVolEITwo ) )
    3340              :                                 {
    3341              :                                         VecAttachedFractFaceEdgeSudo vecAttFracFaceTwo = attVolEITwo.getVecFractManifElem();
    3342              : 
    3343            0 :                                         for( AttachedFractFaceEdgeSudo & afesOne : vecAttFracFaceOne )
    3344              :                                         {
    3345            0 :                                                 for( AttachedFractFaceEdgeSudo & afesTwo : vecAttFracFaceTwo )
    3346              :                                                 {
    3347              :                                                         if( afesOne.testIfEquals( afesTwo ) )
    3348              :                                                         {
    3349              :                                                                 // beide in die generellen Faces verschieben!
    3350              : 
    3351            0 :                                                                 if( ! attVolEIOne.searchFractManifElem( afesOne, true ) )
    3352              :                                                                 {
    3353            0 :                                                                         UG_THROW("im einen nicht gefunden "<< std::endl);
    3354              :                                                                 }
    3355              : 
    3356            0 :                                                                 if( ! attVolEITwo.searchFractManifElem( afesTwo, true ) )
    3357              :                                                                 {
    3358            0 :                                                                         UG_THROW("im anderen nicht gefunden "<< std::endl);
    3359              :                                                                 }
    3360              : 
    3361            0 :                                                                 shiftedFracFaces++;
    3362              : 
    3363              : //                                                              Face * unclosedFace = afesOne.getManifElm();
    3364              : //                                                              // tested if same as that one from afesTwo
    3365              : //
    3366              : ////                                                            m_aaMarkFaceHasUnclosedFracSideB[ unclosedFace ] = true;
    3367              : //
    3368              : //                                                              UG_LOG("unclosed face " << CalculateCenter( unclosedFace, m_aaPos ) << std::endl);
    3369              : 
    3370              : //                                                              m_sh.assign_subset( unclosedFace, m_sh.num_subsets());
    3371              : 
    3372              : //                                                              m_aaMarkVrtxHasUnclosedFracB[vrt] = true;
    3373              : 
    3374              :                                                                 //  added vertex attachment that knows if at vertex there is an unclosed fracture
    3375              : 
    3376              : 
    3377              :                                                         }
    3378              :                                                 }
    3379              :                                         }
    3380            0 :                                 }
    3381              :                         }
    3382              : 
    3383              : 
    3384              : //                      for( AttachedFractFaceEdgeSudo & affe : nextVolFacs )
    3385              : //                      {
    3386              : //                              vecAttFractList.push_back( affe );
    3387              : //                      }
    3388              :                         // create a full chain of all fracture faces, and if one appears twice, shift it for both
    3389              :                         // volumes where it is in to the general faces, i.e. count after establishing, and when twice,
    3390              :                         // then shift
    3391            0 :                 }
    3392              :         }
    3393              : 
    3394              :         UG_LOG("SHIFT FRAC 2 GENER" << std::endl);
    3395              : 
    3396              : 
    3397              : 
    3398            0 :         return shiftedFracFaces;
    3399              : }
    3400              : 
    3401              : //////////////////////////////////////////////////////////////////
    3402              : 
    3403              : 
    3404              : 
    3405            0 : bool ArteExpandFracs3D::seletForSegmented()
    3406              : {
    3407            0 :         for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    3408              :         {
    3409              :                 Vertex* vrt = *iter;
    3410              : 
    3411              : #if 0
    3412              : 
    3413              :                 bool wahl = true;
    3414              : 
    3415              :                 // TODO FIXME
    3416              :                 // hier den Stammi-bene Algorithmus einfügen
    3417              :                 // Search the merged manifold interatively between each basic element
    3418              :                 // dazu noch für boundary faces ein eigenes member einführen,
    3419              :                 // das vom Typ General statt fracture manifold ist, aber sonst wie general
    3420              :                 // später wirken die boundary faces wie eine fracture, die aber
    3421              :                 // um den Wert null nur verschoben wird
    3422              :                 // die Anzahl der Segmente bestimmt, ob der Vertex gewählt wird
    3423              :                 // damit er gewählt wird, muss mehr als ein Segment vorhanden sein
    3424              : 
    3425              :                 auto & vrtxFracPrps = m_aaMarkVrtVFP[ vrt ];
    3426              : 
    3427              : //              bool isBnd = m_aaMarkVrtVFP[ vrt ].getIsBndFracVertex();
    3428              :                 bool isBnd = vrtxFracPrps.getIsBndFracVertex();
    3429              : //              auto numCrosFrac = m_aaMarkVrtVFP[ vrt ].getNumberFracEdgesInVertex();
    3430              : 
    3431              :                 VertxFracPropts::VrtxFracStatus vfpStatus =  vrtxFracPrps.getVrtxFracStatus();
    3432              : 
    3433              :                 if( vfpStatus == VertxFracPropts::noFracSuDoAtt )
    3434              :                         UG_THROW("vertex selected and no frac " << std::endl);
    3435              : 
    3436              :                 // TODO FIXME das ist richtig für den 2D Fall, aber passt das auch im 3D Fall???? nein, da SudoFrac Zahl nötig
    3437              : //              if( ! isBnd && numCrosFrac == 1 )
    3438              : //              if( ! isBnd && vfpStatus == VertxFracPropts::oneFracSuDoAtt && )
    3439              :                 // TODO FIXME was, wenn ein Teil geschlossen ist der fractures, und ein anderer nicht???
    3440              :                 //static_assert(false);
    3441              : 
    3442              : 
    3443              :                 // bestimmen, ob die vertizes der fracture vertizes von ihrer subdomain komplett umzingelt werden
    3444              :                 // muss vor  hier geklärt werden!!!
    3445              : 
    3446              : //              VecPairSudoBool sudoIsSourrounded;
    3447              : 
    3448              : 
    3449              : 
    3450              :                 bool allClosed = false;
    3451              : 
    3452              :                 allClosed = isVrtxSurroundedByFracFaces( vrt, vrtxFracPrps ); //, sudoIsSourrounded );
    3453              : //                      // case boundary: figure out if the vertex is surrounded by frac faces of which two end in
    3454              : //                      // boundary edges, similar the case when the boundary face has itself two
    3455              : //                      // boundary edges, where the vertex is connected to both of them, then it is easy
    3456              : 
    3457              : //              if( ! allClosed )
    3458              : //                      return false;
    3459              : 
    3460              : //              return true;
    3461              : 
    3462              : //              if( ! isBnd )
    3463              : //              {
    3464              : //                      UG_LOG("test if closed" << std::endl);
    3465              : //
    3466              : ////                    m_sh.assign_subset(vrt,m_sh.num_subsets());
    3467              : //
    3468              : ////                    UG_LOG("test if closed assign" << std::endl);
    3469              : //
    3470              : //
    3471              : //              }
    3472              : //              else
    3473              : //              {
    3474              : //
    3475              : //
    3476              : //
    3477              : ////                    allClosed =
    3478              : //              }
    3479              : //              // TODO FIXME auch bei einer boundary muss das gemacht werden!
    3480              : 
    3481              :                 UG_LOG("getestet if closed " << m_aaPos[vrt] << std::endl);
    3482              : 
    3483              : 
    3484              : //              return true;
    3485              : 
    3486              :                 if( allClosed == vrtxFracPrps.getInfoAllFracturesSameClosedState<false>() )
    3487              :                         UG_THROW("da ist was schief gegangen " << std::endl);
    3488              : 
    3489              :                 // TODO FIXME ist das so richtig? kann sein, dass das zu vereinfacht ist!!!!!
    3490              :                 // sudo is suourrounded muss übertragen werden TODO FIXME
    3491              : //              if( ! isBnd && vrtxFracPrps.getInfoAllFracturesSameClosedState<false>() )
    3492              :                 // das !isBnd im 2D Fall wichtig, hier bestimmt auch, wie verallgemeinern?
    3493              :                 // bei mehreren subdoms eventuell komplizierter, kommt aber hoffentlich am Rand nicht vor......
    3494              :                 if( vrtxFracPrps.getInfoAllFracturesSameClosedState<false>() )
    3495              :                 {
    3496              :                         wahl = false;
    3497              :                 }
    3498              : 
    3499              : #else
    3500              : 
    3501              :                 VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[vrt];
    3502              : 
    3503              :                 auto & vrtxFracPrps = m_aaMarkVrtVFP[ vrt ];
    3504              : 
    3505              : //              bool isBnd = m_aaMarkVrtVFP[ vrt ].getIsBndFracVertex();
    3506              :                 bool isBnd = vrtxFracPrps.getIsBndFracVertex();
    3507              : 
    3508              : //              bool wahl = ( vecSegVolElmInf.size() > 1 );
    3509              : //              bool wahl = ( vecSegVolElmInf.size() > 1 && ! isBnd );
    3510            0 :                 bool wahl = ( vecSegVolElmInf.size() > 1 );
    3511              :                 // TODO FIXME danach vielleicht auch fuer boundary wieder selektieren
    3512              :                 // sobald die Boundary Behandlung wie Pseudo Fracture mit Expansion null
    3513              :                 // aber solange die bounaries nicht behandelt werden, führt
    3514              :                 // die Selektion der Boundary Vertizes zu Problemen
    3515              : 
    3516              : #endif
    3517              : 
    3518              : 
    3519              : //              UG_LOG("SELEKTIERE " << m_aaPos[vrt] << " -> " << vrtxFracPrps.getInfoAllFracturesSameClosedState<false>() << std::endl);
    3520              : 
    3521            0 :                 UG_LOG("SELEKTIERE " << m_aaPos[vrt] << " -> " << wahl << std::endl);
    3522              : 
    3523              : 
    3524              :                 // was, wenn numCrossFrac == 0 ist?
    3525              :                 // wieso werden die boundary vrt ausgeschlossen, oder sollen die nicht ausgeschlossen werden?
    3526              :                 // schon im 2D Fall unklar, hier noch wirrer!!! TODO FIXME
    3527              : 
    3528            0 :                 if( wahl )
    3529              : //              if( m_aaMarkVrtVFP[vrt].getNumberFracEdgesInVertex() > 1 ) // TODO FIXME stimmt das so?
    3530              :                 {
    3531              :                         //      select all associated edges, faces and volumes
    3532            0 :                         m_sel.select( m_grid.associated_edges_begin(vrt), m_grid.associated_edges_end(vrt) );
    3533            0 :                         m_sel.select( m_grid.associated_faces_begin(vrt), m_grid.associated_faces_end(vrt) );
    3534            0 :                         m_sel.select( m_grid.associated_volumes_begin(vrt), m_grid.associated_volumes_end(vrt) );
    3535              : 
    3536              :                         std::vector<Edge*> assoEdg;
    3537              :                         std::vector<Face*> assoFac;
    3538              : //                      std::vector<Volume*> assoVol;
    3539              : //                      VecAttachedVolumeElemInfo assoVolElemInfo;
    3540              : 
    3541            0 :                         for( std::vector<Edge *>::iterator iterEdg = m_grid.associated_edges_begin(vrt);
    3542            0 :                                                                                            iterEdg != m_grid.associated_edges_end(vrt);
    3543              :                                                                                            iterEdg++ )
    3544              :                         {
    3545            0 :                                 assoEdg.push_back(*iterEdg);
    3546              :                         }
    3547              : 
    3548            0 :                         for( std::vector<Face *>::iterator iterFac = m_grid.associated_faces_begin(vrt);
    3549            0 :                                                                                            iterFac != m_grid.associated_faces_end(vrt);
    3550              :                                                                                            iterFac++ )
    3551              :                         {
    3552            0 :                                 assoFac.push_back(*iterFac);
    3553              :                         }
    3554              : 
    3555              :                         // TODO FIXME das nach oben verschieben, wo der Stammi Bene Algo sein soll
    3556              :                         // die asso edges und faces brauchen wir vielleicht gar nicht
    3557              :                         // bzw asso edges und asso faces können hier bleiben wo gewählt wird
    3558              :                         // die assoVolElemInfo wird schon oben erzeugt vor der Wahl
    3559              :                         // und dann wird die danach folgende Loop Info
    3560              : //                      for( std::vector<Volume *>::iterator iterVol = m_grid.associated_volumes_begin(vrt);
    3561              : //                                                                                               iterVol != m_grid.associated_volumes_end(vrt);
    3562              : //                                                                                               iterVol++ )
    3563              : //                      {
    3564              : //                              assoVol.push_back(*iterVol);
    3565              : //
    3566              : //                              AttachedVolumeElemInfo avei(*iterVol);
    3567              : //
    3568              : //                              assoVolElemInfo.push_back(avei);
    3569              : //                      }
    3570              : 
    3571            0 :                         m_aaVrtInfoAssoEdges[vrt] = assoEdg;
    3572            0 :                         m_aaVrtInfoAssoFaces[vrt] = assoFac;
    3573              : //                      m_aaVrtInfoAssoVols[vrt] = assoVol;
    3574              : //                      m_aaVolElmInfo[vrt] = assoVolElemInfo;
    3575              : 
    3576            0 :                 }
    3577              :         }
    3578              : 
    3579              :         UG_LOG("vertex Infos Runde eins fertig " << std::endl);
    3580              : 
    3581              : #if 0
    3582              :         // Voraussetzung  FÜR StammiBene Aufrufung
    3583              :         // Stammi-Bene-Vorbereitung
    3584              :         for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    3585              :         {
    3586              :                 Vertex* vrt = *iter;
    3587              : 
    3588              : //              std::vector<Volume*> & attVol = m_aaVrtInfoAssoVols[vrt];
    3589              : 
    3590              :                 auto & vrtxFracPrps = m_aaMarkVrtVFP[ vrt ];
    3591              : 
    3592              :                 VecAttachedFractFaceEdgeSudo vecAttFacEdgSudo = vrtxFracPrps.getAllAttachedFractElems();
    3593              : 
    3594              :                 auto & vecVolElmInfo = m_aaVolElmInfo[vrt];
    3595              : 
    3596              :                 // TODO FIXME eigentlich eine Dummheit, das auf zu teilen in ein VolElemInfo und ein VrtInfoAssoVols
    3597              :                 // denn die InfoAssoVols haben als Info nur die Volumen, die VolElmInfos haben die Volumen
    3598              :                 // und noch viel mehr Infos zu den Faces und den Edges....
    3599              :                 // mittelfristig die m_aaVrtInfoAssoVols abschaffen und alles auf die AttachedFullDimElemInfo
    3600              :                 // übertragen, dann geht der folgende Loop gleich über den Vektor darüber, bzw. gleichbedeutend
    3601              :                 // über m_aaVolElmInfo
    3602              : //              for( auto & vol : attVol )
    3603              :                 for( AttachedVolumeElemInfo & attVolElmInfo : vecVolElmInfo )
    3604              :                 {
    3605              : //                      AttachedVolumeElemInfo attVolElmInfo( vol );
    3606              :                         Volume * vol = attVolElmInfo.getFulldimElem();
    3607              : 
    3608              :                         // add those faces which are fracture faces
    3609              :                         for( auto & afes : vecAttFacEdgSudo )
    3610              :                         {
    3611              :                                 attVolElmInfo.addFractManifElem(afes, m_grid);
    3612              :                         }
    3613              : 
    3614              :                         // add those faces which are NOT fracture faces, assign them arbitraryly subdomain  -1
    3615              :                         // to indicate that they are not from the manifold, independent of their subdomain
    3616              : 
    3617              :                         // collect all volume faces which incorporate the vertex
    3618              : 
    3619              :                         std::vector<Face*> volFacesContainingVrtx;
    3620              : 
    3621              :                         for( IndexType iFac = 0; iFac < vol->num_faces(); iFac++ )
    3622              :                         {
    3623              :                                 Face * fac = m_grid.get_face(vol,iFac);
    3624              : 
    3625              :                                 if( FaceContains( fac, vrt ) )
    3626              :                                 {
    3627              :                                         volFacesContainingVrtx.push_back( fac );
    3628              :                                 }
    3629              :                         }
    3630              : 
    3631              :                         for( auto const & fac : volFacesContainingVrtx )
    3632              :                         {
    3633              :                                 // get the edges of the face connected to the vertex
    3634              : 
    3635              :                                 std::vector<Edge*> vecEdgesFaceVrtx;
    3636              : 
    3637              :                                 // need to be two edges always, check
    3638              : 
    3639              :                                 for( IndexType iEdge = 0; iEdge < fac->num_edges(); iEdge++ )
    3640              :                                 {
    3641              :                                         Edge * edg = m_grid.get_edge(fac,iEdge);
    3642              : 
    3643              :                                         if( EdgeContains(edg,vrt) )
    3644              :                                         {
    3645              :                                                 vecEdgesFaceVrtx.push_back(edg);
    3646              :                                         }
    3647              :                                 }
    3648              : 
    3649              :                                 if( vecEdgesFaceVrtx.size() != 2 )
    3650              :                                 {
    3651              :                                         UG_LOG("edge number Unsinn " << vecEdgesFaceVrtx.size() << std::endl);
    3652              :                                         UG_THROW("edge number Unsinn " << vecEdgesFaceVrtx.size() << std::endl);
    3653              :                                         return false;
    3654              :                                 }
    3655              : 
    3656              :                                 EdgePair edgesFaceVrtx( vecEdgesFaceVrtx[0], vecEdgesFaceVrtx[1] );
    3657              : 
    3658              :                                 // test the subdomain first, if from the subdomains of the cleft manifolds
    3659              : 
    3660              :                                 IndexType sudoThisFace = m_sh.get_subset_index(fac);
    3661              : 
    3662              :                                 std::vector<IndexType> const & sudoList = vrtxFracPrps.getSudoList();
    3663              : 
    3664              :                                 // test if sudo of face belongs to the fracture face subdom list
    3665              : 
    3666              :                                 bool belongsToFracFaceSudo = false;
    3667              : 
    3668              :                                 for( auto const & sudoFrac : sudoList )
    3669              :                                 {
    3670              :                                         if( sudoFrac == sudoThisFace )
    3671              :                                         {
    3672              :                                                 belongsToFracFaceSudo = true;
    3673              :                                                 break;
    3674              :                                         }
    3675              :                                 }
    3676              : 
    3677              : 
    3678              :                                 if( belongsToFracFaceSudo )
    3679              :                                 {
    3680              :                                         // if it belongs, construct it again and test if it already belongs to the fracture faces
    3681              :                                         // MUST be already part of the list, else major error appeared!
    3682              : 
    3683              :                                         AttachedFractFaceEdgeSudo afesTest( fac, edgesFaceVrtx, sudoThisFace );
    3684              : 
    3685              :                                         if( attVolElmInfo.addFractManifElem( afesTest, m_grid ) )
    3686              :                                         {
    3687              :                                                 UG_LOG("manifold element already contained!" << std::endl);
    3688              :                                                 UG_THROW("manifold element already contained!" << std::endl);
    3689              :                                                 return false;
    3690              :                                         }
    3691              : 
    3692              :                                         // nothing to do, already added before hoffentlich
    3693              : 
    3694              :                                 }
    3695              :                                 else
    3696              :                                 {
    3697              :                                         // zeitweilig fehlten alle Faces, die keine fractures sind
    3698              :                                         // die müssen noch irgendwie als nicht-fracture-faces auch dazu gefügt werden
    3699              :                                         // die sind in den attached volumes schon enthalten,
    3700              :                                         // Frage: wie prüfen, dass die gar keine fractures sind, die Infos sollten bekannt sein.....
    3701              :                                         // wichtig auch, dass nur die faces dazu kommen, die den Vertex enthalten!!!
    3702              :                                         // irgendwas von der Art "nonFractureFaceInfos" oder sowas dazu hängen, mit Info
    3703              :                                         // ob schon getouched oder noch nicht.....
    3704              : 
    3705              : 
    3706              :                                         // we construct the attached manifold, given that it is NOT a fracture manifold
    3707              : 
    3708              :                                         // notwendig auch, dass es eine Markierungsmöglichkeit gibt dafür, ob
    3709              :                                         // ein face bei der nächsten weiter inneren Runde quasi äussere Begrenzung sein muss
    3710              :                                         // gilt sowohl für fracture faces, die können das in erster Runde auch sein am Ende
    3711              :                                         // der Runde, sowie danach nur noch für nicht-fracture-faces
    3712              : 
    3713              :                                         AttachedGenerFaceEdgeSudo afesAdd( fac, edgesFaceVrtx );
    3714              : 
    3715              :                                         attVolElmInfo.addGenerManifElem( afesAdd, m_grid );
    3716              : 
    3717              :                                 }
    3718              : 
    3719              :                         }
    3720              : 
    3721              :                 }
    3722              :         }
    3723              : #endif
    3724              : 
    3725              :         UG_LOG("vertex Infos Runde eins fertig Volumen auch" << std::endl);
    3726              : 
    3727            0 :         return true;
    3728              : }
    3729              : 
    3730            0 : bool ArteExpandFracs3D::stasiAlgo( Vertex * const & oldVrt )
    3731              : {
    3732              : 
    3733            0 :         UG_LOG("Stasi start " << m_aaPos[oldVrt] << std::endl);
    3734              :         // TODO FIXME übernehmen von loop2EstablishNewVertices und establishNewVertices
    3735              :         // plus Boundary faces ähnlich Fracture
    3736              :         // am Ende die in Segment verbundenen offenen Fracture Faces verschwinden lassen
    3737              :         // Segmente erstellen Ziel hier, aber auch raus finden, ob es mehr als eines gibt
    3738              :         // oder ob es offen ist, wegen wahl
    3739              : 
    3740            0 :         vector3 posOldVrt = m_aaPos[oldVrt];
    3741              : 
    3742            0 :         UG_LOG("vertex at " << posOldVrt << std::endl);
    3743              : 
    3744            0 :         VecSegmentVolElmInfo & vecSegVolElmInfo = m_accsAttVecSegVolElmInfo[oldVrt];
    3745              : 
    3746              :         auto & vrtxFracPrps = m_aaMarkVrtVFP[ oldVrt ];
    3747              : 
    3748              :         bool isBndryVrtx = vrtxFracPrps.getIsBndFracVertex();
    3749              : 
    3750              :         UG_LOG("under construction Tetrahedra limited Stasi Algo" << std::endl);
    3751              : 
    3752              : //      VecVertFracTrip const & vecVertFracTrip = m_aaVrtInfoFraTri[oldVrt];
    3753              : 
    3754              :         VecAttachedVolumeElemInfo assoVolElemInfo;
    3755              : 
    3756              :         int bndryFacsFnd = 0;
    3757              : 
    3758            0 :         for( std::vector<Volume *>::iterator iterVol = m_grid.associated_volumes_begin(oldVrt);
    3759            0 :                                                                                  iterVol != m_grid.associated_volumes_end(oldVrt);
    3760              :                                                                                  iterVol++ )
    3761              :         {
    3762            0 :                 Volume * vol = *iterVol;
    3763              : 
    3764              :                 AttachedVolumeElemInfo avei(vol);
    3765              : 
    3766            0 :                 bndryFacsFnd += prepareStasi(oldVrt, avei);
    3767              : 
    3768            0 :                 assoVolElemInfo.push_back(avei);
    3769            0 :         }
    3770              : 
    3771            0 :         if( isBndryVrtx && bndryFacsFnd == 0 )
    3772              :         {
    3773              :                 UG_LOG("Boundary vertex with no boundary faces adjoint" << std::endl);
    3774            0 :                 UG_THROW("Boundary vertex with no boundary faces adjoint" << std::endl);
    3775              :                 return false;
    3776              :         }
    3777              : 
    3778              : 
    3779              : //      if( vrtxFracPrps.getIsBndFracVertex() )
    3780              : //      {
    3781              : //              for( AttachedVolumeElemInfo ave : assoVolElemInfo )
    3782              : //              {
    3783              : //                      UG_LOG("BONDVERT " << m_aaPos[oldVrt] << " -> " << ave.getVecBndryManifElem().size()  << std::endl);
    3784              : //                      if(  ave.getVecBndryManifElem().size() == 0 )
    3785              : //                      {
    3786              : //                              UG_THROW("VERLUST" << std::endl);
    3787              : //                      }
    3788              : //              }
    3789              : //      }
    3790              : 
    3791              :         // von copy und paste angepasst, die unsinnige Verdopplung von vecAttVolElemInfo und assoVolElemInfo
    3792              :         // vielleicht noch entfernen
    3793              :         VecAttachedVolumeElemInfo const & vecAttVolElemInfo = assoVolElemInfo; // m_aaVolElmInfo[oldVrt];
    3794              : 
    3795            0 :         VecAttachedVolumeElemInfo vecAttVolElemInfoCop = vecAttVolElemInfo; // echte KOPIE
    3796              : 
    3797              :         VecAttachedVolumeElemInfo reconstructedVecAttVolElmInf;
    3798              : 
    3799              :                 /*
    3800              :                  * While Schleifen aufbauen für den
    3801              :                  * Search the adjacent surface interatively - Algorithmus
    3802              :                  * (Stasi Algorithmus)
    3803              :                  *
    3804              :                  */
    3805              : 
    3806              :         IndexType d_segmenteErledigt = 0;
    3807              : 
    3808            0 :         while( vecAttVolElemInfoCop.size() != 0 )
    3809              :         {
    3810              :                 SegmentVolElmInfo segmentAVEI;
    3811              : 
    3812              :                 AttachedVolumeElemInfo & startVolInfoThisSegment = vecAttVolElemInfoCop[0];
    3813              : 
    3814              :                 startVolInfoThisSegment.markIt();
    3815              : 
    3816              :                 Volume * volSta = startVolInfoThisSegment.getFulldimElem();
    3817              : 
    3818              :                 vector3 center;
    3819              : 
    3820            0 :                 if( volSta != nullptr )
    3821            0 :                         center = CalculateCenter(volSta,m_aaPos);
    3822              : 
    3823              : //              UG_LOG("volume center " << center << std::endl );
    3824              : 
    3825              :                 int d_loopsDone = 0;
    3826              : 
    3827            0 :                 while( vecAttVolElemInfoCop.size() != 0 )
    3828              :                 {
    3829              :                         // count number of marked elements
    3830              :                         IndexType numMarkedElems = 0;
    3831              :                         IndexType markPoint = 0;
    3832              : 
    3833              : //                      IndexType lastMarkPt = 0;
    3834              :                         IndexType startIndexInner = 0;
    3835              : 
    3836            0 :                         for( AttachedVolumeElemInfo const & volElInfCop : vecAttVolElemInfoCop )
    3837              :                         {
    3838            0 :                                 if( volElInfCop.isMarked() )
    3839              :                                 {
    3840              :                                         Volume * vol = volElInfCop.getFulldimElem();
    3841              : //                                      m_sh.assign_subset(vol, m_sh.num_subsets());
    3842              : 
    3843            0 :                                         vector3 center = CalculateCenter(vol,m_aaPos);
    3844              : 
    3845              : //                                      UG_LOG("DAS ZENTRUM " << numMarkedElems << " -> " << center << std::endl);
    3846              : 
    3847              :                                         startIndexInner = markPoint;
    3848            0 :                                         numMarkedElems++;
    3849              : 
    3850              :                                 }
    3851              : 
    3852            0 :                                 markPoint++;
    3853              :                         }
    3854              : 
    3855              :                         UG_LOG("LOOPS DONE " << numMarkedElems << std::endl);
    3856              : 
    3857            0 :                         if( numMarkedElems == 0 )
    3858              :                                 break;
    3859              : 
    3860              : //                      int startIndexInner = -1;
    3861              : //
    3862              : //                      for( int i = 0; i < vecAttVolElemInfoCop.size(); i++ )
    3863              : //                      {
    3864              : //                              AttachedVolumeElemInfo vi = vecAttVolElemInfoCop[i];
    3865              : //
    3866              : //                              Volume * vo = vi.getFulldimElem();
    3867              : //
    3868              : //                              vector3 center = CalculateCenter(vo,m_aaPos);
    3869              : //
    3870              : //                              UG_LOG("DAS ZENTRUM ZAHL VOR " << i << " -> " <<  center << std::endl);
    3871              : //
    3872              : //                              if( vi.isMarked() )
    3873              : //                                      startIndexInner = i;
    3874              : //                      }
    3875              : //
    3876              : //                      if( startIndexInner < 0 )
    3877              : //                      {
    3878              : //                              UG_THROW("kein Anfang gefunden " << std::endl);
    3879              : //                      }
    3880              : //
    3881              : //#if 0
    3882              : //                      IndexType startIndexInner = markPoint - 1;
    3883              : //#endif
    3884            0 :                         AttachedVolumeElemInfo startVolInfoMarkLoop = vecAttVolElemInfoCop[startIndexInner];
    3885              : 
    3886              :                         Volume * stattVoll = startVolInfoMarkLoop.getFulldimElem();
    3887              : 
    3888            0 :                         vector3 centerX = CalculateCenter(stattVoll,m_aaPos);
    3889              : 
    3890            0 :                         UG_LOG("DAS ZENTRUM DANACH STASI" << startIndexInner << " -> " <<  centerX << std::endl);
    3891              : 
    3892              : //                      m_sh.assign_subset(stattVoll, m_sh.num_subsets());
    3893              : #if 0
    3894              :                         for( int i = 0; i < vecAttVolElemInfoCop.size(); i++ )
    3895              :                         {
    3896              :                                 AttachedVolumeElemInfo vi = vecAttVolElemInfoCop[i];
    3897              : 
    3898              :                                 Volume * vo = vi.getFulldimElem();
    3899              : 
    3900              :                                 vector3 center = CalculateCenter(vo,m_aaPos);
    3901              : 
    3902              :                                 UG_LOG("DAS ZENTRUM ZAHL " << i << " -> " <<  center << std::endl);
    3903              : 
    3904              :                         }
    3905              : #endif
    3906            0 :                         for( AttachedVolumeElemInfo const & possibleOrigVolInfo : vecAttVolElemInfo )
    3907              :                         {
    3908            0 :                                 if( possibleOrigVolInfo.hasSameFulldimElem( startVolInfoMarkLoop ) )
    3909              :                                 {
    3910            0 :                                         segmentAVEI.push_back(possibleOrigVolInfo);
    3911            0 :                                         reconstructedVecAttVolElmInf.push_back(possibleOrigVolInfo);
    3912              :                                         break;
    3913              :                                 }
    3914              :                         }
    3915              : 
    3916              :                         vecAttVolElemInfoCop.erase( vecAttVolElemInfoCop.begin() + startIndexInner );
    3917              : 
    3918              : //                      if( d_loopsDone == 1 )
    3919              : //                              return false;
    3920              : 
    3921            0 :                         for( VecAttachedVolumeElemInfo::iterator aveiIt = vecAttVolElemInfoCop.begin();
    3922            0 :                                                                                                          aveiIt < vecAttVolElemInfoCop.end();
    3923              :                                                                                                          aveiIt++
    3924              :                         )
    3925              :                         {
    3926              :                                 AttachedVolumeElemInfo & possibleNeighbour = *aveiIt;
    3927              : 
    3928            0 :                                 if( possibleNeighbour.hasSameFulldimElem( startVolInfoMarkLoop ) )
    3929              :                                 {
    3930            0 :                                         continue;
    3931              :                                 }
    3932              :                                 else
    3933              :                                 {
    3934            0 :                                         bool neighbourFound = possibleNeighbour.testFullDimElmNeighbour( startVolInfoMarkLoop );
    3935              : 
    3936              :                                         if( neighbourFound )
    3937              :                                         {
    3938              :                                                 Volume * vol = possibleNeighbour.getFulldimElem();
    3939              : 
    3940              : //                                              m_sh.assign_subset(vol, m_sh.num_subsets());
    3941              : 
    3942              :                                         }
    3943              :                                 }
    3944              :                         }
    3945              : 
    3946              : 
    3947              :                         d_loopsDone++;
    3948              : 
    3949              : 
    3950            0 :                 }
    3951              : 
    3952            0 :                 vecSegVolElmInfo.push_back(segmentAVEI);
    3953              : 
    3954              : //              d_segmenteErledigt++;
    3955              : //
    3956              : //              if( d_segmenteErledigt == 1 )
    3957              : //              return false;
    3958            0 :         }
    3959              : 
    3960            0 :         if( reconstructedVecAttVolElmInf.size() != vecAttVolElemInfo.size() )
    3961              :         {
    3962              :                 UG_LOG("Rekonstruktion schief gegangen " << std::endl);
    3963            0 :                 UG_THROW("Rekonstruktion schief gegangen " << std::endl);
    3964              :                 return false;
    3965              :         }
    3966              : 
    3967              : // for debug purposes
    3968              : 
    3969              :         constexpr bool d_assignSudos2Segments = false;
    3970              : 
    3971              :         if( d_assignSudos2Segments )
    3972              :         {
    3973              :                 if( vecSegVolElmInfo.size() > 1 )
    3974              :                 {
    3975              :                         for( SegmentVolElmInfo const & svei : vecSegVolElmInfo )
    3976              :                         {
    3977              :                                 // TODO FIXME das hier wieder entfernen, die Subdomain Zuweisung, nur für debug Zwecke
    3978              :                                 IndexType sudoMax = m_sh.num_subsets();
    3979              : 
    3980              :                                 for( AttachedVolumeElemInfo const & vei : svei )
    3981              :                                 {
    3982              :                                         Volume * vol = vei.getFulldimElem();
    3983              : 
    3984              :                                         m_sh.assign_subset( vol, sudoMax );
    3985              :                                 }
    3986              :                         }
    3987              :                 }
    3988              :         }
    3989              : 
    3990            0 :         UG_LOG("Stasi END " << m_aaPos[oldVrt] << std::endl);
    3991              : 
    3992              :         return true;
    3993            0 : }
    3994              : 
    3995              : #if 0
    3996              : // Deprecated due to Stasi Algo
    3997              : // herausfinden für Sudo der frac, ob bezüglich dieser sudo die faces geschlossen sind, oder ob ein Fracture End vorliegt
    3998              : bool ArteExpandFracs3D::isVrtxSurroundedByFracFaces( Vertex * const & vrt, VertxFracPropts & vrtxFracPrps )
    3999              : //, VecPairSudoBool & sudoSurrounded )
    4000              : {
    4001              :         // TODO FIXME wenn an Boundary, dann auch auf closed open unterscheiden - sowohl wenn nur edge an
    4002              :         // boundary, aber auch wenn ein ganzes face dort, noch unklar, was das bedeutet
    4003              : 
    4004              :         // ganz ähnlich wie im 2D Fall, Loopen, im Kreis drehen, kucken, ob wir vom Anfang ans Ende kommen,
    4005              :         // und ob das Ende der edges wieder der Anfang der edges ist, da wir uns auf faces drehen
    4006              : 
    4007              :         // case boundary: figure out if the vertex is surrounded by frac faces of which two end in
    4008              :         // boundary edges, similar the case when the boundary face has itself two
    4009              :         // boundary edges, where the vertex is connected to both of them, then it is easy
    4010              : 
    4011              : 
    4012              :         VecAttachedFractFaceEdgeSudo vafes = vrtxFracPrps.getAllAttachedFractElems();
    4013              : 
    4014              :         std::vector<IndexType> sudoList = vrtxFracPrps.getSudoList();
    4015              : 
    4016              : //      for( auto const & sudo : sudoList )
    4017              : //      {
    4018              : //              std::vector<Face*> tmpFaces;
    4019              : //
    4020              : //              CollectFaces( tmpFace, m_grid, vrt );
    4021              : //
    4022              : //      }
    4023              : 
    4024              :         // first compare sudo list, if equal
    4025              : 
    4026              :         std::vector<IndexType> sudosTestList;
    4027              : 
    4028              :         std::vector<bool> sudoFound( sudoList.size(), false );
    4029              : 
    4030              :         UG_LOG("sudo list size " << sudoList.size() << std::endl );
    4031              : 
    4032              :         UG_LOG("vafes list size VA " << vafes.size() << std::endl );
    4033              : 
    4034              : 
    4035              :         for( auto const & af : vafes )
    4036              :         {
    4037              :                 bool found = false;
    4038              : 
    4039              :                 IndexType sudo = af.getSudo();
    4040              : 
    4041              :                 UG_LOG("sudo af " << sudo << std::endl);
    4042              : 
    4043              :                 for( IndexType i = 0; i < sudoList.size(); i++ )
    4044              :                 {
    4045              :                         UG_LOG("sudo list dusso is " << sudoList[i] << std::endl);
    4046              : 
    4047              :                         if( sudo == sudoList[i] )
    4048              :                         {
    4049              :                                 sudoFound[i] = true;
    4050              :                                 found = true;
    4051              :                         }
    4052              :                 }
    4053              : 
    4054              : 
    4055              :                 if( ! found )
    4056              :                         UG_THROW("sudo nicht gefunden muss aber da sein " << std::endl);
    4057              :         }
    4058              : 
    4059              :         UG_LOG("alles gefunden " << std::endl);
    4060              : 
    4061              : 
    4062              :         for( auto const & sf: sudoFound )
    4063              :         {
    4064              :                 if( sf == false )
    4065              :                 {
    4066              :                         UG_LOG("Falsch" << std::endl);
    4067              :                         UG_THROW("sudo not found but must be there " << std::endl);
    4068              :                 }
    4069              :         }
    4070              : 
    4071              :         UG_LOG("alles gefunden Test " << std::endl);
    4072              : 
    4073              : 
    4074              :         // sort faces with respect to subdomain - macht das wirklich Sinn, wie umständlich das gemacht wird jetzt?
    4075              : 
    4076              :         // if we arrive here, all sudos found, the entire circle closing can start
    4077              : 
    4078              :         VecPairSudoBool sudoSurrounded;
    4079              : 
    4080              :         for( auto const & sudo : sudoList )
    4081              :         {
    4082              :                 VecAttachedFractFaceEdgeSudo vecAttFacSudo;
    4083              : 
    4084              :                 for( auto const & attFac : vafes )
    4085              :                 {
    4086              :                         if( sudo == attFac.getSudo() )
    4087              :                         {
    4088              :                                 UG_LOG("die sudo gefunden " << sudo << std::endl);
    4089              :                                 vecAttFacSudo.push_back(attFac);
    4090              :                         }
    4091              :                 }
    4092              : 
    4093              :                 VecAttachedFractFaceEdgeSudo vecAttFacSudoSort;
    4094              : 
    4095              : 
    4096              : 
    4097              :                 bool isClosed = false;
    4098              : 
    4099              :                 bool isBndVrtx = IsBoundaryVertex3D(m_grid,vrt);
    4100              : 
    4101              :                 if( ! isBndVrtx )
    4102              :                 {
    4103              :                         UG_LOG("No boundary vertex test closed " << m_aaPos[vrt] << std::endl);
    4104              : 
    4105              :                         if( vecAttFacSudo.size() == 1 )
    4106              :                         {
    4107              :                                 // no need for further investigations for inner faces
    4108              :                                 isClosed = false;
    4109              :                                 vecAttFacSudoSort = vecAttFacSudo;
    4110              :                         }
    4111              :                         else
    4112              :                         {
    4113              :                                 isClosed = sortElemCircleIsClosed( vecAttFacSudo, vecAttFacSudoSort );
    4114              :                         }
    4115              : 
    4116              :                 }
    4117              :                 else // different treatment boundary vertex
    4118              :                 {
    4119              :                         // figure out start face with a boundary edge, and figure out an eventual additional boundary edge
    4120              :                         // if only one face, then check if two attached boundary edges, then true, else false
    4121              : 
    4122              :                         if( vecAttFacSudo.size() == 1 )
    4123              :                         {
    4124              :                                 AttachedFractFaceEdgeSudo & singleEntry = vecAttFacSudo[0];
    4125              : 
    4126              :                                 EdgePair faceEdgs = singleEntry.getPairLowElm();
    4127              : 
    4128              :                                 if( IsBoundaryEdge3D(m_grid, faceEdgs.first) && IsBoundaryEdge3D(m_grid, faceEdgs.second ) )
    4129              :                                         isClosed = true;
    4130              : 
    4131              :                                 // very simple
    4132              :                                 vecAttFacSudoSort = vecAttFacSudo;
    4133              : 
    4134              :                         }
    4135              :                         else
    4136              :                         {
    4137              :                                 // figure out a begin face with a boundary edge and figure out another face with a boundary edge
    4138              : 
    4139              :                                 Edge * beginEdge = nullptr;
    4140              :                                 Edge * endEdge = nullptr;
    4141              : 
    4142              :                                 IndexType startFaceIndx = 0;
    4143              :                                 IndexType endFaceIndx = 0;
    4144              : 
    4145              :                                 for( auto const & afs : vecAttFacSudo )
    4146              :                                 {
    4147              :                                         Face * fac = afs.getManifElm();
    4148              : 
    4149              :                                         EdgePair edgs = afs.getPairLowElm();
    4150              : 
    4151              :                                         Edge * edgOne = edgs.first;
    4152              :                                         Edge * edgTwo = edgs.second;
    4153              : 
    4154              :                                         if( beginEdge == nullptr )
    4155              :                                         {
    4156              :                                                 if( IsBoundaryEdge3D(m_grid, edgOne) )
    4157              :                                                 {
    4158              :                                                         beginEdge = edgTwo;
    4159              :                                                 }
    4160              :                                                 else if( IsBoundaryEdge3D(m_grid, edgTwo) )
    4161              :                                                 {
    4162              :                                                         beginEdge = edgOne;
    4163              :                                                 }
    4164              :                                                 else
    4165              :                                                 {
    4166              :                                                         startFaceIndx++;
    4167              :                                                 }
    4168              :                                         }
    4169              :                                         else
    4170              :                                         {
    4171              :                                                 if( IsBoundaryEdge3D(m_grid, edgOne) )
    4172              :                                                 {
    4173              :                                                         endEdge = edgOne;
    4174              :                                                 }
    4175              :                                                 else if( IsBoundaryEdge3D(m_grid, edgTwo) )
    4176              :                                                 {
    4177              :                                                         endEdge = edgTwo;
    4178              :                                                 }
    4179              :                                         }
    4180              : 
    4181              :                                         if( endEdge != nullptr )
    4182              :                                                 break;
    4183              : 
    4184              :                                         endFaceIndx++;
    4185              :                                 }
    4186              : 
    4187              :                                 if( beginEdge == nullptr && endFaceIndx == vecAttFacSudo.size() )
    4188              : //                                      || beginEdge == nullptr || endEdge == nullptr )
    4189              :                                 {
    4190              :                                         UG_LOG("keine boundary edges" << std::endl);
    4191              : 
    4192              :                                         startFaceIndx = -1;
    4193              : 
    4194              :                                         if( endEdge != nullptr )
    4195              :                                                 UG_THROW("Ende nicht null, Anfang null " << std::endl);
    4196              :                                 }
    4197              : 
    4198              :                                 UG_LOG("Boundary vertex test closed " << m_aaPos[vrt] << std::endl);
    4199              : 
    4200              : //                              int d_num = 0;
    4201              : //                              for( auto const & afs : vecAttFacSudo )
    4202              : //                              {
    4203              : //                                      d_num++;
    4204              : //                                      Face * fac = afs.getManifElm();
    4205              : //                                      m_sh.assign_subset(fac, m_sh.num_subsets());
    4206              : //                              }
    4207              : //                              UG_LOG("number of surr faces " << d_num << std::endl );
    4208              : 
    4209              : //                              m_sh.assign_subset(beginEdge,m_sh.num_subsets());
    4210              : //                              m_sh.assign_subset(endEdge,m_sh.num_subsets());
    4211              : //                              m_sh.assign_subset(vecAttFacSudo[startFaceIndx].getManifElm(),m_sh.num_subsets());
    4212              : 
    4213              :                                 isClosed = sortElemCircleIsClosed( vecAttFacSudo, vecAttFacSudoSort, startFaceIndx, beginEdge, endEdge );
    4214              : 
    4215              :                         }
    4216              :                 }
    4217              : 
    4218              :                 UG_LOG("-------------------------------" << std::endl);
    4219              :                 UG_LOG("is closed " << isClosed << " at " << m_aaPos[vrt] << std::endl);
    4220              :                 UG_LOG("-------------------------------" << std::endl);
    4221              : 
    4222              : //              if( isClosed )
    4223              : //              {
    4224              : //                      m_sh.assign_subset(vrt,3);
    4225              : //              }
    4226              : //              else
    4227              : //              {
    4228              : //                      m_sh.assign_subset(vrt,4);
    4229              : //              }
    4230              : 
    4231              :                 if( vecAttFacSudo.size() != vecAttFacSudoSort.size() )
    4232              :                 {
    4233              : //                      return false;
    4234              : 
    4235              :                         UG_THROW("Die Sortierung ist komplett schief gegangen " << std::endl);
    4236              :                 }
    4237              : 
    4238              :                 // DEBUG Zeug, später entfernen!!!!!!
    4239              : //              for( auto const & afss : vecAttFacSudoSort )
    4240              : //              {
    4241              : //                      Face * fac = afss.getManifElm();
    4242              : //
    4243              : //                      m_sh.assign_subset(fac, m_sh.num_subsets());
    4244              : //              }
    4245              : 
    4246              :                 PairSudoBool ic( sudo, isClosed );
    4247              : 
    4248              :                 sudoSurrounded.push_back( ic );
    4249              : 
    4250              :         }
    4251              : 
    4252              :         vrtxFracPrps.setInfoAllFractureSudosIfClosed(sudoSurrounded);
    4253              : 
    4254              :         bool allClosed = true;
    4255              : 
    4256              :         for( auto const & ic : sudoSurrounded )
    4257              :         {
    4258              :                 if( ! ic.second )
    4259              :                         allClosed = false;
    4260              :         }
    4261              : 
    4262              :         return allClosed;
    4263              : }
    4264              : 
    4265              : bool ArteExpandFracs3D::sortElemCircleIsClosed( VecAttachedFractFaceEdgeSudo const & vecAttFac,
    4266              :                                                                                                 VecAttachedFractFaceEdgeSudo & vecSortedFac,
    4267              :                                                                                                 int startFacIndexUser,
    4268              : //                                                                                              int endFacIndexUser,
    4269              : //                                                                                              IndexType startEdgeIndexUser,
    4270              : //                                                                                              IndexType endEdgeIndexUser
    4271              : //                                                                                              Face * const & startFacUser,
    4272              : //                                                                                              Face * const & endFacUser,
    4273              :                                                                                                 Edge * const & startEdgUser,
    4274              :                                                                                                 Edge * const & endEdgUser
    4275              :                                                                                                 )
    4276              : {
    4277              : 
    4278              :         UG_LOG("Schliesstest" << std::endl);
    4279              : 
    4280              :         IndexType originalSize = vecAttFac.size();
    4281              : 
    4282              :         if( originalSize == 0 )
    4283              :         {
    4284              :                 UG_THROW("zu klein zum sortieren " << std::endl);
    4285              :                 return false;
    4286              :         }
    4287              :         else if ( originalSize == 1 )
    4288              :         {
    4289              :                 UG_THROW("should not happen size 1, should have been mentioned before " << std::endl);
    4290              :         }
    4291              : 
    4292              :         UG_LOG("Kopieren zwecks sortieren " << std::endl);
    4293              : 
    4294              :         for( auto const & af : vecAttFac )
    4295              :         {
    4296              :                 UG_LOG("die sudos innen sind " << af.getSudo() << std::endl);
    4297              :         }
    4298              : 
    4299              :         VecAttachedFractFaceEdgeSudo copyVecAttFac = vecAttFac;
    4300              : 
    4301              :         for( auto const & af : copyVecAttFac )
    4302              :         {
    4303              :                 UG_LOG("die sudos kopiert sind " << af.getSudo() << std::endl);
    4304              :         }
    4305              : 
    4306              :         IndexType beginIndx = 0;
    4307              : 
    4308              :         UG_LOG("begin Index " << beginIndx << std::endl);
    4309              : 
    4310              :         bool simpleConnectionTest = false;
    4311              : 
    4312              :         Edge * startEdgeForced = nullptr;
    4313              : 
    4314              :         if( startFacIndexUser >= 0 )
    4315              :         {
    4316              :                 UG_LOG("Veränderung " << startFacIndexUser << std::endl);
    4317              :                 beginIndx = startFacIndexUser;
    4318              :                 simpleConnectionTest = true; // user hopefully did it
    4319              :         }
    4320              :         else
    4321              :         {
    4322              :                 // we need to ensure to start at a fracture which is not in between, in case that circle not closed
    4323              :                 // so ensure that all fracture faces have a fracture face at both edges as neighbour,
    4324              :                 // in principle this is already sufficient to answer the question which we want to know
    4325              :                 // all the rest here is useless playing in principle
    4326              : 
    4327              :                 bool broken = false;
    4328              : 
    4329              :                 for( IndexType i = 0; i < vecAttFac.size(); i++ )
    4330              :                 {
    4331              :                         IndexType firstSideConnected = 0;
    4332              :                         IndexType secondSideConnected = 0;
    4333              : 
    4334              :                         AttachedFractFaceEdgeSudo afBase = vecAttFac[i];
    4335              : 
    4336              :                         Face * faceBase = afBase.getManifElm();
    4337              :                         EdgePair edgPairBase = afBase.getPairLowElm();
    4338              : 
    4339              :                         Edge * edgeBaseOne = edgPairBase.first;
    4340              :                         Edge * edgeBaseTwo = edgPairBase.second;
    4341              : 
    4342              :                         for( IndexType j = 0; j < vecAttFac.size(); j++ )
    4343              :                         {
    4344              :                                 if( i != j )
    4345              :                                 {
    4346              :                                         AttachedFractFaceEdgeSudo afCompr = vecAttFac[j];
    4347              : 
    4348              :                                         Face * faceCompr = afCompr.getManifElm();
    4349              :                                         EdgePair edgPairCompr = afCompr.getPairLowElm();
    4350              : 
    4351              :                                         Edge * edgeComprOne = edgPairCompr.first;
    4352              :                                         Edge * edgeComprTwo = edgPairCompr.second;
    4353              : 
    4354              :                                         if( edgeComprOne == edgeBaseOne || edgeComprTwo == edgeBaseOne )
    4355              :                                                 firstSideConnected++;
    4356              : 
    4357              :                                         if( edgeComprOne == edgeBaseTwo || edgeComprTwo == edgeBaseTwo )
    4358              :                                                 secondSideConnected++;
    4359              :                                 }
    4360              : 
    4361              :                         }
    4362              : 
    4363              :                         if( vecAttFac.size() > 2 && ( firstSideConnected > 1 || secondSideConnected > 1 ) )
    4364              :                         {
    4365              :                                 UG_THROW("zu oft verbunden " << std::endl );
    4366              :                         }
    4367              :                         else if( vecAttFac.size() == 2 && ( firstSideConnected > 2 || secondSideConnected > 2 ) )
    4368              :                         {
    4369              :                                 UG_THROW("zu oft verbunden " << std::endl );
    4370              :                         }
    4371              :                         else if( firstSideConnected == 0 )
    4372              :                         {
    4373              :                                 // face is open into one direction, already clear that not closed!!
    4374              : 
    4375              :                                 beginIndx = i;
    4376              :                                 simpleConnectionTest = false;
    4377              :                                 startEdgeForced = edgeBaseTwo;
    4378              :                                 UG_LOG("forcieren 1 " << std::endl);
    4379              :                                 broken = true;
    4380              :                                 break;
    4381              :                         }
    4382              :                         else if( secondSideConnected == 0 )
    4383              :                         {
    4384              :                                 // face is open into one direction, already clear that not closed!!
    4385              : 
    4386              :                                 beginIndx = i;
    4387              :                                 simpleConnectionTest = false;
    4388              :                                 startEdgeForced = edgeBaseOne;
    4389              :                                 UG_LOG("forcieren 2 " << std::endl);
    4390              :                                 broken = true;
    4391              :                                 break;
    4392              :                         }
    4393              :                         else if( firstSideConnected == 1 && secondSideConnected == 1 )
    4394              :                         {
    4395              :                                 simpleConnectionTest = true; // as long as a look
    4396              :                         }
    4397              :                         else
    4398              :                         {
    4399              :                                 UG_THROW("komischer Verbindungsfall " << std::endl);
    4400              :                         }
    4401              : 
    4402              :                         if( broken )
    4403              :                                 break;
    4404              : 
    4405              :                 }
    4406              :         }
    4407              : 
    4408              :         UG_LOG("begin Index X " << beginIndx << std::endl);
    4409              : 
    4410              : 
    4411              : //      AttachedFractFaceEdgeSudo initialAFES = *(copyAttFac.begin());
    4412              :         AttachedFractFaceEdgeSudo initialAFES = copyVecAttFac[beginIndx];
    4413              : 
    4414              :         IndexType sudo = initialAFES.getSudo();
    4415              : 
    4416              :         UG_LOG("sudo " << beginIndx << " ist " << sudo << std::endl);
    4417              : 
    4418              :         Face * beginFacLoop = initialAFES.getManifElm();
    4419              : 
    4420              :         // TODO FIXME wird das irgendwo verwendet? wieso nicht?
    4421              : //      Face * endFacLoop = nullptr;
    4422              : 
    4423              : //      if( endFacIndexUser != -1 )
    4424              : //      {
    4425              : //              endFacLoop = copyVecAttFac[endFacIndexUser].getManifElm();
    4426              : //      }
    4427              : 
    4428              :         EdgePair beginEdges = initialAFES.getPairLowElm();
    4429              : 
    4430              :         Edge * beginEdgeLoop = beginEdges.second;
    4431              :         Edge * targetedEndEdgeLoop = beginEdges.first; // should be closed! should end at same edge as it begins!
    4432              : 
    4433              : //
    4434              : //      return true;
    4435              : 
    4436              : //      if( startEdgeIndexUser != -1 )
    4437              : //      {
    4438              : //              beginEdgeLoop =
    4439              : //      }
    4440              : 
    4441              : //      if( startFacUser != nullptr )
    4442              : //      {
    4443              : //              beginFacLoop = startFacUser;
    4444              : //
    4445              : //      }
    4446              : //
    4447              : 
    4448              : //      if( ! FaceContains(beginFacLoop,beginEdgeLoop->vertex(0)) )
    4449              : //              UG_THROW("Sortierung Gesicht hat nicht die gewünschte Ecke " << std::endl);
    4450              : //
    4451              : //      if( endFacUser != nullptr )
    4452              : //      {
    4453              : //              endFacLoop = endFacUser;
    4454              : //      }
    4455              : //
    4456              : 
    4457              :         if( startEdgUser != nullptr )
    4458              :         {
    4459              :                 beginEdgeLoop = startEdgUser;
    4460              : 
    4461              :                 // check if part of the begin face!
    4462              : 
    4463              :                 if( ! FaceContains( beginFacLoop, beginEdgeLoop ) )
    4464              :                         UG_THROW("Anfangsgesicht hat keine Anfangsecke " << std::endl);
    4465              : 
    4466              :         }
    4467              : 
    4468              :         if( startEdgeForced != nullptr )
    4469              :         {
    4470              :                 beginEdgeLoop = startEdgeForced;
    4471              : 
    4472              :                 // check if part of the begin face!
    4473              : 
    4474              :                 if( ! FaceContains( beginFacLoop, beginEdgeLoop ) )
    4475              :                         UG_THROW("Anfangsgesicht hat keine Anfangsecke forced " << std::endl);
    4476              : 
    4477              : //              m_sh.assign_subset(startEdgeForced, m_sh.num_subsets());
    4478              :                 UG_LOG("forciert " << std::endl);
    4479              : 
    4480              : //              return false;
    4481              : 
    4482              :         }
    4483              : 
    4484              : 
    4485              :         if( endEdgUser != nullptr )
    4486              :         {
    4487              :                 // check if part of end face at end of loop somehow
    4488              :                 targetedEndEdgeLoop = endEdgUser;
    4489              : 
    4490              :                 if( startEdgeForced != nullptr )
    4491              :                         UG_THROW("das muss schief gehen, Chaos " << std::endl);
    4492              : 
    4493              : //              if( endFacLoop != nullptr )
    4494              : //              {
    4495              : //                      if( ! FaceContains( endFacLoop, targetedEndEdgeLoop ) )
    4496              : //                              UG_THROW("Endgesicht hat keine Endecke " << std::endl);
    4497              : //              }
    4498              :         }
    4499              : //
    4500              : 
    4501              :         // DEBUG
    4502              : //      m_sh.assign_subset(beginFacLoop, m_sh.num_subsets());
    4503              : //      m_sh.assign_subset(beginEdgeLoop, m_sh.num_subsets());
    4504              : //      m_sh.assign_subset(targetedEndEdgeLoop, m_sh.num_subsets());
    4505              : 
    4506              : 
    4507              :         // Du musst sortieren. Du musst einen Zeitplan machen. Das kann man lernen. Du kannst das selber machen.
    4508              : 
    4509              :         IndexType countedCrossedFaces = 1;
    4510              : 
    4511              :         vecSortedFac.push_back( initialAFES );
    4512              : 
    4513              :         copyVecAttFac.erase( copyVecAttFac.begin() + beginIndx );
    4514              : 
    4515              : //      Face * face2Append = beginFacLoop;
    4516              :         Edge * startEdge2Append = beginEdgeLoop;
    4517              : 
    4518              : //      m_sh.assign_subset(startEdge2Append,m_sh.num_subsets());
    4519              : 
    4520              :         UG_LOG("while loop anfangen " << std::endl);
    4521              : 
    4522              :         IndexType d_whi = 0;
    4523              : 
    4524              :         while( copyVecAttFac.size() != 0 )
    4525              :         {
    4526              : 
    4527              :                 UG_LOG("in while loop " << d_whi << std::endl);
    4528              :                 d_whi++;
    4529              : 
    4530              :                 IndexType foundCommEdg = 0;
    4531              : 
    4532              :                 Edge * nextEdge = nullptr;
    4533              : 
    4534              : //              for( auto const & caf : copyVecAttFac )
    4535              :                 for( VecAttachedFractFaceEdgeSudo::iterator itAttFES  = copyVecAttFac.begin();
    4536              :                                                                                            itAttFES != copyVecAttFac.end();
    4537              :                                                                                            itAttFES++
    4538              :                 )
    4539              :                 {
    4540              :                         AttachedFractFaceEdgeSudo caf = *itAttFES;
    4541              : 
    4542              :                         Face * d_Fac = caf.getManifElm();
    4543              : 
    4544              : //                      m_sh.assign_subset(d_Fac,m_sh.num_subsets());
    4545              : 
    4546              :                         EdgePair edgPr = caf.getPairLowElm();
    4547              : 
    4548              :                         Edge * edgOne = edgPr.first;
    4549              :                         Edge * edgTwo = edgPr.second;
    4550              : 
    4551              : //                      m_sh.assign_subset(edgOne,m_sh.num_subsets());
    4552              : //                      m_sh.assign_subset(edgTwo,m_sh.num_subsets());
    4553              : 
    4554              : //                      return true;
    4555              : 
    4556              :                         IndexType hasEdge = 0;
    4557              : 
    4558              :                         Edge * overNextEdge = nullptr;
    4559              : 
    4560              :                         if( edgOne == startEdge2Append )
    4561              :                         {
    4562              :                                 nextEdge = edgOne;
    4563              :                                 overNextEdge = edgTwo;
    4564              :                                 hasEdge++;
    4565              :                         }
    4566              : 
    4567              :                         if( edgTwo == startEdge2Append )
    4568              :                         {
    4569              :                                 nextEdge = edgTwo;
    4570              :                                 overNextEdge = edgOne;
    4571              :                                 hasEdge++;
    4572              :                         }
    4573              : 
    4574              :                         if( hasEdge > 1 )
    4575              :                                 UG_THROW("zu viele Ecken und Kanten " << std::endl);
    4576              : 
    4577              :                         if( hasEdge == 1 )
    4578              :                         {
    4579              :                                 Face * fac2App = caf.getManifElm();
    4580              : //                              m_sh.assign_subset(fac2App,m_sh.num_subsets());
    4581              :                                 EdgePair edgesNextFace( edgOne, edgTwo );
    4582              :                                 AttachedFractFaceEdgeSudo nextAttFES( fac2App, edgesNextFace, sudo );
    4583              : 
    4584              :                                 vecSortedFac.push_back(nextAttFES);
    4585              : 
    4586              :                                 copyVecAttFac.erase(itAttFES);
    4587              :                                 foundCommEdg++;
    4588              :                                 startEdge2Append = overNextEdge;
    4589              : 
    4590              :                                 break;
    4591              :                         }
    4592              : 
    4593              : 
    4594              :                 }
    4595              : 
    4596              :                 if( foundCommEdg > 1 )
    4597              :                         UG_THROW("Kein Anschluss unter dieser Nummer " << std::endl);
    4598              : 
    4599              :                 if( foundCommEdg == 0 )
    4600              :                 {
    4601              :                         UG_LOG("Kreislauf nicht geschlossen " << std::endl);
    4602              : 
    4603              :                         if( nextEdge != nullptr )
    4604              :                                 UG_THROW("nicht konsistent, null und null " << std::endl);
    4605              : 
    4606              :                         break;
    4607              :                 }
    4608              : 
    4609              :                 if( nextEdge == nullptr )
    4610              :                 {
    4611              :                         if( foundCommEdg != 0 )
    4612              :                                 UG_THROW("nicht konsistent, null und null v2 " << foundCommEdg << " -> " << nextEdge << std::endl);
    4613              : 
    4614              :         //                      return false;
    4615              :                 }
    4616              : 
    4617              :         }
    4618              : 
    4619              :         if( originalSize != vecSortedFac.size() )
    4620              :         {
    4621              :                 UG_THROW("Sortierung hat nicht funktioniert " << std::endl);
    4622              :                 return false;
    4623              :         }
    4624              : 
    4625              :         if( startEdge2Append != targetedEndEdgeLoop )
    4626              :         {
    4627              :                 if( simpleConnectionTest )
    4628              :                         UG_THROW("obwohl offen oder vorgegeben trotzdem Ziel nicht erreicht?" << std::endl);
    4629              : 
    4630              :                 UG_LOG("Ende nicht erreicht, Kreis nicht geschlossen, innerer Rand vermutlich" << std::endl);
    4631              :                 return false;
    4632              :         }
    4633              : 
    4634              : 
    4635              :         UG_LOG("Kreislauf Faces 3D Test ob Knoten umrandet geschlossen " << std::endl);
    4636              : 
    4637              :         return true;
    4638              : }
    4639              : 
    4640              : #endif
    4641              : 
    4642            0 : bool ArteExpandFracs3D::assignOrigFracInfos()
    4643              : {
    4644              :         m_originalFractureFaces.clear();
    4645              : 
    4646            0 :         for( FaceIterator iter = m_sel.begin<Face>(); iter != m_sel.end<Face>(); ++iter)
    4647              :         {
    4648            0 :                 if( m_aaMarkFaceIsFracB[*iter] == true )
    4649            0 :                         m_originalFractureFaces.push_back(*iter);
    4650              :         }
    4651              : 
    4652            0 :         m_fracInfosBySubset = std::vector<FractureInfo>( m_sh.num_subsets(), FractureInfo(-1, -1, 0) );
    4653              : 
    4654            0 :         for(size_t i = 0; i < m_fracInfos.size(); ++i)
    4655              :         {
    4656            0 :                 if( m_fracInfos[i].subsetIndex >= m_sh.num_subsets())
    4657              :                 {
    4658            0 :                         throw(UGError("Bad subsetIndex in given fracInfos."));
    4659              :                 }
    4660              : 
    4661            0 :                 m_fracInfosBySubset[ m_fracInfos[i].subsetIndex ] = m_fracInfos[i];
    4662              :         }
    4663              : 
    4664              : //      disable selection inheritance to avoid infinite recursion.
    4665            0 :         m_sel.enable_selection_inheritance(false);
    4666              : 
    4667            0 :         return true;
    4668              : }
    4669              : 
    4670            0 : bool ArteExpandFracs3D::establishNewVrtBase()
    4671              : {
    4672              :         //      iterate over all surrounding volumes to enable shifted vertices, this loop taken from SR but shortened
    4673              : 
    4674            0 :         for( VolumeIterator iterSurrVol = m_sel.volumes_begin(); iterSurrVol != m_sel.volumes_end(); ++ iterSurrVol )
    4675              :         {
    4676              :                 Volume* sv = *iterSurrVol;
    4677              : 
    4678              :                 std::vector<Vertex*> & newVrts = m_aaVrtVecVol[sv];
    4679            0 :                 newVrts.resize(sv->num_vertices());
    4680              : 
    4681            0 :                 for(size_t iVrt = 0; iVrt < sv->num_vertices(); ++ iVrt )
    4682              :                 {
    4683            0 :                         newVrts[iVrt] = nullptr;
    4684              :                 }
    4685              : 
    4686              :                 // erstmal so tun, als ob keine neuen Vertizes erzeugt werden an den alten Vertizes
    4687              : 
    4688              :         }
    4689              : 
    4690            0 :         return true;
    4691              : }
    4692              : 
    4693              : #if 0
    4694              : // Analogon zu VertrexFractureInfo in 2D, wo jeder Vertex eine Liste bekommt, wo alle die ihm angehängten
    4695              : // Ecken, Faces und Volumen gespeichert werden; dazu die Normalen, und vielleicht noch weitere Infos
    4696              : bool ArteExpandFracs3D::generateVertexInfos()
    4697              : {
    4698              :         UG_LOG("Starte Generierung" << std::endl);
    4699              : 
    4700              :         // TODO FIXME das wird benötigt
    4701              : 
    4702              :         // sowas von der Art als attachement bei den attachments, und dann mit Leben füllen für jeden Vertex
    4703              :         // in dieser Funktion;
    4704              :         // vielleicht braucht es auch Edge Infos, oder nur Edge Infos?
    4705              : //      VecVertFracTrip vertexNoInfo;
    4706              : //      using AttVecVertFracTrip = Attachment<VecVertFracTrip>;
    4707              : //      AttVecVertFracTrip aAdjInfoAVVFT;
    4708              : //      grid.attach_to_vertices_dv( aAdjInfoAVVFT, vertexNoInfo );
    4709              : //      Grid::VertexAttachmentAccessor<AttVecVertFracTrip> aaVrtInfoFraTri(grid,  aAdjInfoAVVFT );
    4710              : 
    4711              :         // Lebendigmachung in:
    4712              :         //      for( auto & fsfpmv : fracSubdom_facePerpendMinVal ) .....
    4713              :         // von dort lernen!!!!!
    4714              : 
    4715              :         // notwendig: face, normal, volume, edge
    4716              : 
    4717              :         // TODO FIXME das wollen wir nicht, sondern das alte Vertex Fracture Triple
    4718              : //      m_vrtxFractrQuadrplVec = VrtxFractrQuadrplArte3DVec();
    4719              :         // TODO FIXME diese Einträge erzeugen
    4720              : 
    4721              :         // TODO FIXME kann vielleicht vereinfacht werden durch einen Loop über alle Vertizes,
    4722              :         // und das Abfragen der dort schon gespeicherten vertex property Geschichten, sonst
    4723              :         // wird manches doppelt gemoppelt
    4724              :         
    4725              :         for( auto const & fracInf : m_fracInfos )
    4726              :         {
    4727              :                 IndexType fracSudo = fracInf.subsetIndex;
    4728              : 
    4729              : 
    4730              : //              for(EdgeIterator iterEdg = m_sh.begin<Edge>(fracIndSudo); iterEdg != m_sh.end<Edge>(fracIndSudo); iterEdg++ )
    4731              : //
    4732              :                 for( FaceIterator iterFac = m_sh.begin<Face>(fracSudo); iterFac != m_sh.end<Face>(fracSudo); iterFac++ )
    4733              :                 {
    4734              : 
    4735              : //                      VrtxFractrQuadrplArte3D vrtxFractrQuadrpl;
    4736              :                         
    4737              :                         // TODO FIXME die Innereien dieses Loops irgendwie für boundary faces hinbiegen,
    4738              :                         // vermutlich nicht viel verändern, dafür eigene Routine, die dann für jeweils ein face den
    4739              :                         // Müll umsetzt
    4740              : 
    4741              :                         Face* fac = *iterFac;
    4742              :                         
    4743              :                         auto sudoFacInnerLoop = m_sh.get_subset_index(fac);
    4744              :                         
    4745              :                         if( sudoFacInnerLoop != fracSudo )
    4746              :                                 UG_THROW("Subdomain Index Fehler 3D " << std::endl);
    4747              : 
    4748              : //                      std::vector<Vertex*> verticesFac;
    4749              : //
    4750              : //                      for( IndexType i = 0; i < fac->num_vertices(); i++ )
    4751              : //                      {
    4752              : //                              verticesFac.push_back( fac->vertex(i) );
    4753              : //                      }
    4754              : 
    4755              : 
    4756              :                         std::vector<Volume*> assoVols;
    4757              : 
    4758              :                         // wo kam denn der Käse her?
    4759              : //                      if( ! m_grid.option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES) )
    4760              : //                              UG_THROW("How to collect asso vols?" << std::endl);
    4761              : 
    4762              :                         // brauchen wir das? für was? von SR irgendwie übernommen, wo dort was entfernt ähnliches gemacht wird....
    4763              :                         if(! m_grid.option_is_enabled(VOLOPT_AUTOGENERATE_FACES) )
    4764              :                         {
    4765              :                                 UG_LOG("WARNING grid option VOLOPT_AUTOGENERATE_FACES autoenabled.\n");
    4766              :                                 m_grid.enable_options(VOLOPT_AUTOGENERATE_FACES);
    4767              :                         }
    4768              : 
    4769              : 
    4770              : //                      for( Grid::AssociatedVolumeIterator volIt  = m_grid.associated_volumes_begin(fac);
    4771              : //                                                                                              volIt != m_grid.associated_volumes_end(fac);
    4772              : //                                                                                              volIt++
    4773              : //                      )
    4774              : //                      {
    4775              : //                              assoVols.push_back(*volIt);
    4776              : //                      }
    4777              : 
    4778              :                         CollectVolumes(assoVols, m_grid, fac );
    4779              : //
    4780              : //                      for( auto const & av : assoVols )
    4781              : //                      {
    4782              : //                              m_sh.assign_subset(av, m_sh.num_subsets());
    4783              : //                      }
    4784              : //
    4785              : //                      return true;
    4786              : 
    4787              : //                      using VolNormPair = std::pair< Volume*, vector3 >;
    4788              : //
    4789              : //                      using VecVolNormPair = std::vector<VolNormPair>;
    4790              : //
    4791              : //                      VecVolNormPair vecNormalsAwayVol;
    4792              : 
    4793              : //                      UG_LOG("Center Face " << CalculateCenter(fac,m_aaPos) << std::endl);
    4794              : 
    4795              :                         for( auto const & kuhVol : assoVols )
    4796              :                         {
    4797              :                                 bool facFound = false;
    4798              :                                 IndexType numFd = 0;
    4799              : 
    4800              :                                 for( IndexType iSide = 0; iSide < kuhVol->num_sides(); iSide++ )
    4801              :                                 {
    4802              :                                         Face * kuhFac = m_grid.get_side(kuhVol, iSide);
    4803              : 
    4804              : //                                      UG_LOG("Center Kuh Face " << CalculateCenter(kuhFac,m_aaPos) << std::endl);
    4805              : 
    4806              :                                         // TODO FIXME eigentliches Ziel ist es, den face descriptor des Volumens zu finden,
    4807              :                                         // das mit dem face übereinstimmt, alle anderen Seiten des Volumens sind egal
    4808              :                                         // Funktion suchen, die ausgehend von einem Face, das ein Volumen begrenzt,
    4809              :                                         // den zum Volumen passenden FaceDescriptor findet, also auch richtige Orientierung
    4810              :                                         // der Vertices beinhaltet
    4811              :                                         // FRAGE TODO FIXME ist ein face descriptor von der Orientierung zum Volumen abhängig
    4812              :                                         // oder hängt der nur vom Face ab, das eine vorgegebene Oriertierung hat?
    4813              : 
    4814              :                                         bool checkCoincide = checkIfFacesVerticesCoincide( kuhFac, fac );
    4815              : 
    4816              :                                         if( checkCoincide )
    4817              :                                         {
    4818              :                                                 facFound = true;
    4819              :                                                 numFd++;
    4820              : 
    4821              :                                                 if( kuhFac != fac )
    4822              :                                                         UG_LOG("Kuh Fac ist nicht fac " << std::endl);
    4823              : 
    4824              :                                                 FaceDescriptor facDescr;
    4825              : 
    4826              :                                                 // TODO FIXME testen, ob der Face Descriptor von der Orientierung abhängt
    4827              :                                                 // also testen, ob sich der face descriptor ändert, wenn das Volumen
    4828              :                                                 // auf der einen und auf der anderen Seite des faces hängt
    4829              :                                                 // deswegen auch die ganze Prozedur mit den kuhFacs, die hoffentlich
    4830              :                                                 // je nach Volumen anders orientiert sind als das eigentliche Face,
    4831              :                                                 // aber dieselben Vertices haben, also geometrisch gleich sind, aber anders orientiert!!!!
    4832              : 
    4833              :                                                 // TODO FIXME andere Hergehensweise vielleicht:
    4834              :                                                 // von m_aaVrtInfoAssoVols ausgehen, darüber loopen, oder die in einen Vektor stecken,
    4835              :                                                 // wo die Vertices dabei sind, dann kann man sich vielelicht ein paar Klimmzüge sparen,
    4836              :                                                 // vielleicht aber auch nicht.....
    4837              : 
    4838              :                                                 kuhVol->face_desc( iSide, facDescr );
    4839              : 
    4840              :                                                 vector3 normal;
    4841              : 
    4842              :                                                 CalculateNormal( normal, & facDescr, m_aaPos );
    4843              : 
    4844              :                                                 vector3 facCenter = CalculateCenter( kuhFac, m_aaPos );
    4845              :                                                 vector3 kuhCenter = CalculateCenter( fac, m_aaPos );
    4846              :                                                 vector3 kuhVolCenter = CalculateCenter( kuhVol, m_aaPos);
    4847              : 
    4848              : //                                              UG_LOG("Normale zum face descriptor " << normal << " , " << facCenter << std::endl);
    4849              : //                                              UG_LOG("Normale zum Kuhh descriptor " << normal << " , " << kuhCenter << std::endl);
    4850              : //                                              UG_LOG("Zentrum des Vol")
    4851              : 
    4852              : //                                              UG_LOG("fac " << fac << std::endl );
    4853              : //                                              UG_LOG("kuh " << kuhFac << std::endl );
    4854              : 
    4855              :                                                 UG_LOG("Normale ist " << normal << " fac " << facCenter
    4856              :                                                                 << " vol " << kuhVolCenter << std::endl);
    4857              : 
    4858              : 
    4859              : //                                              VolNormPair normalsAwayVol( kuhVol, normal );
    4860              : //
    4861              : //                                              vecNormalsAwayVol.push_back( normalsAwayVol );
    4862              : 
    4863              :                                                 std::vector<Edge*> facEdgs;
    4864              : 
    4865              :                                                 CollectEdges( facEdgs, m_grid, fac);
    4866              : 
    4867              :                                                 for( IndexType iF = 0; iF < fac->num_vertices(); iF++ )
    4868              :                                                 {
    4869              :                                                         Vertex * vrt = fac->vertex(iF);
    4870              : 
    4871              :                         //                              verticesFac.push_back(vrt);
    4872              : 
    4873              :                                                         std::vector<Edge*> edgOfVrtx;
    4874              : 
    4875              :                                                         for( auto const & edg : facEdgs )
    4876              :                                                         {
    4877              :                                                                 if( EdgeContains(edg, vrt) )
    4878              :                                                                 {
    4879              :                                                                         edgOfVrtx.push_back(edg);
    4880              :                                                                 }
    4881              :                                                         }
    4882              : 
    4883              :                                                         if( edgOfVrtx.size() == 2 )
    4884              :                                                         {
    4885              :                                                                 EdgePair commonEdges(edgOfVrtx[0], edgOfVrtx[1]); //  fill values
    4886              :                                                                 // edges commun between face and volume, with the vertex included as well, i.e. two possibilities
    4887              : 
    4888              :                                                                 // TODO FIXME diese Info muss woanders hin, in der AttachedFractFaceEdgeSudo Klasse speichern!
    4889              :                                                                 VertFracTrip infoVerticesThisFace( fac, fracSudo, kuhVol, normal, commonEdges );
    4890              : 
    4891              :                                                                 // TODO FIXME hier irgendwie graphische Ausgabe von irgendwas
    4892              : 
    4893              :                                                                 m_aaVrtInfoFraTri[vrt].push_back( infoVerticesThisFace );
    4894              : 
    4895              :                                                                 // DEBUG OUTPUT; REMOVE LATER
    4896              : //                                                              m_sh.assign_subset(kuhVol,m_sh.num_subsets());
    4897              :                                                         }
    4898              :                                                         else
    4899              :                                                         {
    4900              :                                                                 UG_THROW("Mein Face das hat keine Ecken, keine Ecken hat mein Face" << std::endl);
    4901              :                                                         }
    4902              :                                                 }
    4903              : 
    4904              :                                         }
    4905              :                                 }
    4906              : 
    4907              :                                 if( ! facFound || numFd != 1 )
    4908              :                                 {
    4909              :                                         UG_THROW("Kein Kuh Volumen gefunden" << std::endl);
    4910              :                                         return false;
    4911              :                                 }
    4912              : 
    4913              :                         }
    4914              : 
    4915              :                 }
    4916              : 
    4917              : 
    4918              :         }
    4919              : 
    4920              :         UG_LOG("GEnerierung gelungen " << std::endl);
    4921              : 
    4922              :         return true;
    4923              : }
    4924              : #endif
    4925              : 
    4926            0 : bool ArteExpandFracs3D::checkIfFacesVerticesCoincide( Face * const & facOne, Face * const & facTwo )
    4927              : {
    4928              : 
    4929            0 :         if( facOne->size() != facTwo->size() )
    4930              :                 return false;
    4931              : 
    4932              :         std::vector<Vertex* > facOneVrtcs, facTwoVrtcs;
    4933              : 
    4934            0 :         collectFaceVertices( facOneVrtcs, facOne );
    4935            0 :         collectFaceVertices( facTwoVrtcs, facTwo );
    4936              : 
    4937            0 :         for( auto const & vrtOne : facOneVrtcs )
    4938              :         {
    4939              :                 bool found = false;
    4940              : 
    4941              :                 IndexType numFd = 0;
    4942              : 
    4943            0 :                 for( auto const & vrtTwo : facTwoVrtcs )
    4944              :                 {
    4945            0 :                         if( vrtOne == vrtTwo )
    4946              :                         {
    4947              :                                 found = true;
    4948            0 :                                 numFd++;
    4949              :                         }
    4950              :                 }
    4951              : 
    4952            0 :                 if( ! found || numFd != 1 )
    4953              :                         return false;
    4954              :         }
    4955              : 
    4956              :         return true;
    4957            0 : }
    4958              : 
    4959            0 : bool ArteExpandFracs3D::collectFaceVertices( std::vector<Vertex*> & facVrt, Face * const & fac )
    4960              : {
    4961            0 :         if( fac == nullptr )
    4962              :                 return false;
    4963              : 
    4964              :         facVrt.clear();
    4965              : 
    4966            0 :         for( IndexType iF = 0; iF < fac->num_vertices(); iF++ )
    4967              :         {
    4968            0 :                 Vertex * vrt = fac->vertex(iF);
    4969              : 
    4970            0 :                 facVrt.push_back( vrt );
    4971              :         }
    4972              : 
    4973              :         return true;
    4974              : }
    4975              : 
    4976              : 
    4977              : 
    4978              : 
    4979              : // major function of new grid generation, in Keil Style, but functional grid, only the diamonds have to be
    4980              : // established in additional functionalities independent of this function
    4981            0 : bool ArteExpandFracs3D::loop2EstablishNewVertices()
    4982              : {
    4983            0 :         m_vecCrossVrtInf = std::vector<CrossVertInf>();
    4984              : 
    4985              : 
    4986              :         // TODO FIXME sowas von der Art wird nötig sein als Vorbereitung für die Diamanten,
    4987              :         // Infos darin speichern, vielleicht auch noch notwendig, die Kanten zu speichern oder die faces,
    4988              :         // zu klären im Laufe der Implementation
    4989              :         // std::vector<CrossVertInf > vecCrossVrtInf;
    4990              : 
    4991              :         // zentraler Loop
    4992              : 
    4993              :         // TODO FIXME vorher noch den attVrtVec und den aaVrtVecFac analog implementieren, das fehlt noch!!!
    4994              :         // ebenso seine Befüllung, braucht noch eine Funktion dazwischen, die attachments selber in die
    4995              :         // attach Funktion natürlich
    4996              :         
    4997              :         int untilVrt = 0;
    4998              : 
    4999            0 :         for( VertexIterator iterV = m_sel.begin<Vertex>(); iterV != m_sel.end<Vertex>(); ++ iterV )
    5000              :         {
    5001            0 :                 Vertex * oldVrt = *iterV;
    5002              : 
    5003              :                 // Position dieses Vertex
    5004              :                 vector3 posOldVrt = m_aaPos[oldVrt];
    5005              : 
    5006              :                 // TODO FIXME diese Funktion mit Leben und Analytischer Geometrie 13. Klasse füllen
    5007              : 
    5008              : //              VecVertFracTrip & vecVertFracTrip = m_aaVrtInfoFraTri[oldVrt];
    5009              : //
    5010              : //              std::vector<Edge*> & allAssoEdges = m_aaVrtInfoAssoEdges[oldVrt];
    5011              : //              std::vector<Face*> & allAssoFaces = m_aaVrtInfoAssoFaces[oldVrt];
    5012              : //              std::vector<Volume*> & allAssoVolumes = m_aaVrtInfoAssoVols[oldVrt];
    5013              : 
    5014            0 :                 UG_LOG("vertex at " << posOldVrt << std::endl);
    5015              : 
    5016            0 :                 VecSegmentLimitingSides & vecSegmLimSid = m_vrtxAttAccsVecSegmLimSid[oldVrt];
    5017              : 
    5018            0 :                 for( SegmentLimitingSides const & sls : vecSegmLimSid )
    5019              :                 {
    5020            0 :                         if( sls.hasUnclosedFaces())
    5021              :                                 UG_LOG("Hier hat das Gesicht noch ungeschlossene " << std::endl);
    5022              :                 }
    5023              : 
    5024              : //              if( ! vrtxIsBndVrt )
    5025              : //              {
    5026            0 :                 if( ! establishNewVertizesStasiBased(oldVrt) )
    5027              :                 {
    5028              :                         UG_LOG("Vertex Erzeugung schief gegangen " << std::endl);
    5029            0 :                         return false;
    5030              :                 }
    5031              : 
    5032              : //              }
    5033              : 
    5034              : 
    5035              :                 
    5036              : 
    5037              :         }
    5038              : 
    5039              :         // for debugging
    5040              : //      return false;
    5041              : 
    5042            0 :         return true;
    5043              : }
    5044              : 
    5045              : ////////////////////////////////////////////////////////////////////
    5046              : 
    5047              : #if 0
    5048              : bool ArteExpandFracs3D::establishNewVertizesStasiBased( Vertex * const & oldVrt)
    5049              : {
    5050              :         // anfangs nur für innere Vertizes mit einer fracture
    5051              : 
    5052              :         VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[oldVrt];
    5053              : 
    5054              :         if( vecSegVolElmInf.size() < 2 )
    5055              :         {
    5056              :                 UG_LOG("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5057              : //              UG_THROW("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5058              : //              return false;
    5059              :                 return true;
    5060              :         }
    5061              : 
    5062              :         for( SegmentVolElmInfo const & svei : vecSegVolElmInf )
    5063              :         {
    5064              :                 // count the number of the fracture subdomains surrounding the segment
    5065              :                 // in case of boundary vertex, also count the number of boundary subdomains
    5066              : 
    5067              :                 std::vector<IndexType> sudosInSegment;
    5068              : 
    5069              :                 if( ! extracFractSudosOfSegment( svei, sudosInSegment ) )
    5070              :                 {
    5071              :                         UG_LOG("kann sudos nicht extrahieren " << std::endl);
    5072              :                         UG_THROW("kann sudos nicht extrahieren " << std::endl);
    5073              :                         return false;
    5074              :                 }
    5075              : 
    5076              :                 IndexType sudoNumInSeg = sudosInSegment.size();
    5077              : 
    5078              :                 // check if is boundary vertex
    5079              : 
    5080              :                 auto & vrtxFracPrps = m_aaMarkVrtVFP[ oldVrt ];
    5081              : 
    5082              :                 bool vrtxIsBndVrt = vrtxFracPrps.getIsBndFracVertex();
    5083              : 
    5084              :                 UG_LOG("is bndry " << vrtxIsBndVrt << std::endl);
    5085              : 
    5086              :                 if( ! vrtxIsBndVrt )
    5087              :                 {
    5088              :                         // count number of fracture subdomains in the Segment, should have been done before......
    5089              : 
    5090              :                         // TODO FIXME ersetze das altmodische VrtxFracProptsStatus durch ein Zählen
    5091              :                         // der subdomains, die pro Segment wirklich vorkommen, nachdem die
    5092              :                         // auslaufenden fracture faces den generellen Faces zugeschlagen worden sind
    5093              :                         // diese Zählweise ist die erste Folgeaufgabe, damit der komische vrtxFractureProperties Status
    5094              :                         // weg geworfen werden kann, der ist nämlich nutzlos inzwischen, da er auch auslaufende
    5095              :                         // fracture faces zählt, was Unsinn ist.......
    5096              :                         // später folgt auch die Verallgemeinerung auf boundary vertizes, dann muss deren Wahl
    5097              :                         // vielleicht wieder dazu genommen werden.....
    5098              : 
    5099              :                         //Vorbereitung Ersetzung VertexFractureProperties Status
    5100              :                         // durch Zählen der Fracture Subdomains von jedem Segment
    5101              :                         // die Zählerei kann dann gemacht werden, wenn die doppelten offenen fracture faces
    5102              :                         // in die allgemeinen faces verschoben werden, dann geht das in einem Abwasch,
    5103              :                         // gehe dazu in die entsprechende Funktion
    5104              : 
    5105              : //                      if( vrtxFracPrps.getVrtxFracStatus() == VrtxFracProptsStatus::oneFracSuDoAtt )
    5106              :                         if( sudoNumInSeg == 1 )
    5107              :                         {
    5108              :                                 // standard case, one fracture
    5109              :                                 if( ! expandWithinTheSegment<1,false>( oldVrt, svei ) )
    5110              :                                 {
    5111              :                                         UG_LOG("Expandierung einfachster Fall schief gegangen " << std::endl);
    5112              :                                         return false;
    5113              :                                 }
    5114              :                         }
    5115              :                         else // unterscheiden zwei und drei vermutlich..... aber wichtiger Segmentzahl..... und dann kommt es darauf an, wieviele subdoms im einzelnen Segment sind
    5116              :                         {
    5117              : 
    5118              :                         }
    5119              : 
    5120              :                 }
    5121              :                 else
    5122              :                 {
    5123              :                         // boundary faces counted as fracture faces, but no expansion
    5124              :                         // zuerst aber die inneren Schnittvertizes, weil bei denen die Nicht-Null Expansion
    5125              :                         // gelernt werden kann, dann anzuwenden auf Null-Expansion senkrecht zu den boundaries......
    5126              :                 }
    5127              : 
    5128              :         }
    5129              : 
    5130              :         return true;
    5131              : }
    5132              : #endif
    5133              : 
    5134              : ///////////////////////////////////////////////////////////////////
    5135              : 
    5136            0 : bool ArteExpandFracs3D::establishSegmentLimitingSidesInfo()
    5137              : {
    5138              : 
    5139              :         UG_LOG("ESTABLISH SGEMENT LIM SIDE INFO" << std::endl );
    5140              : 
    5141            0 :         for( VertexIterator iterV = m_sel.begin<Vertex>(); iterV != m_sel.end<Vertex>(); ++ iterV )
    5142              :         {
    5143              :                 Vertex * oldVrt = *iterV;
    5144              : 
    5145            0 :                 UG_LOG("establish segm lim sides for " << m_aaPos[oldVrt] << std::endl);
    5146              : 
    5147              :                 VecSegmentLimitingSides & vecSegmLimSid = m_vrtxAttAccsVecSegmLimSid[oldVrt];
    5148              : 
    5149              :                 UG_LOG("Segment limiting sides got " << std::endl);
    5150              : 
    5151              :                 auto & vrtxFracPrps = m_aaMarkVrtVFP[ oldVrt ];
    5152              : 
    5153              :                 bool vrtxIsBndVrt = vrtxFracPrps.getIsBndFracVertex();
    5154              : 
    5155              :                 UG_LOG("is bndry " << vrtxIsBndVrt << std::endl);
    5156              : 
    5157              :                 VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[oldVrt];
    5158              : 
    5159              :                 UG_LOG("CHECK SIZE" << std::endl);
    5160              : 
    5161            0 :                 if( vecSegVolElmInf.size() < 2 )
    5162              :                 {
    5163              :                         UG_LOG("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5164              :         //              UG_THROW("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5165              :         //              return false;
    5166              : //                      return true;
    5167              :                         continue;
    5168              :                 }
    5169              : 
    5170              :                 UG_LOG("CONTINUED" << std::endl);
    5171              : 
    5172            0 :                 for( SegmentVolElmInfo const & segVolsElInf : vecSegVolElmInf )
    5173              :                 {
    5174              :                         // count the number of the fracture subdomains surrounding the segment
    5175              :                         // in case of boundary vertex, also count the number of boundary subdomains
    5176              : 
    5177              :         //              std::vector<IndexType> sudosInSegment;
    5178              : 
    5179              :                         // hier die neue Klasse und ihr averaing einführen, oder im Hauptloop der neuen Elemente.....
    5180              :                         // SegmentSides<....> in .h file für die richtigen template parameter Kurznamen geben und hier
    5181              :                         // Objekt erstellen und je nach ob mit oder ohne Bndry entsprechend aufladen und averagen.....
    5182              :                         // und zwar für jedes Segment einzeln, und abhängig von boundary oder nicht die boundary Geschichten
    5183              :                         // dazu oder auch nicht...... also einen VecSegmentSides erstellen auch, das einzelne Objekt
    5184              :                         // weiss dann, ob es eine Boundary ist..... vielleicht noch den Vektor dazu als übergebener Parameter
    5185              :                         // damit man den da drin weiter reichen kann?
    5186              :                         // wenn jedes Objekt des Vektors von SegmentSIdes sowohl seinen Vertex kennt als auch weiss,
    5187              :                         // ob es boundary oder nicht ist, kann danach darüber geloopt werden, ohne nochmal
    5188              :                         // aussen den Vertex mit geben zu müssen, oder die Info, ob bndry oder nicht.....
    5189              :                         // danach gibts dann Funktionen, die alleine ein Objekt von der Sorte SegmentSides schlucken brauchen
    5190              :                         // und hier nur ein Loop über den ganzen Vektor davon, wo für jedes Element dann die Fkt aufgerufen wird....
    5191              : 
    5192              :                         SegmentLimitingSides segLimSids( oldVrt, vrtxIsBndVrt );
    5193              : 
    5194              :         //              std::vector<Volume*> vecVolsOfSegment;
    5195              : 
    5196              :                         IndexType boundarySites = 0;
    5197              : 
    5198            0 :                         for( AttachedVolumeElemInfo const & volElmInf : segVolsElInf )
    5199              :                         {
    5200            0 :                                 if( ! segLimSids.schluckVecAttFractElm( volElmInf.getVecFractManifElem() ) )
    5201              :                                 {
    5202              :                                         UG_LOG("schlucken schief gegangen " << std::endl);
    5203            0 :                                         UG_THROW("schlucken schief gegangen " << std::endl);
    5204              :                                         return false;
    5205              :                                 }
    5206              : 
    5207              : 
    5208            0 :                                 if( volElmInf.hasUnclosedFracture() )
    5209              :                                 {
    5210            0 :                                         if( ! segLimSids.schluckVecAttUnclosedFractElm( volElmInf.getVecUnclosedFractManifElem() ) )
    5211              :                                         {
    5212              :                                                 UG_LOG("Schlucken von unclosed schief gegangen " << std::endl);
    5213              : //                                              UG_THROW("Schlucken von unclosed schief gegangen " << std::endl);
    5214              : //                                              return false;
    5215              :                                         }
    5216              :                                         else
    5217              :                                         {
    5218              :                                                 UG_LOG("ungeschlossene fracture geschluckt " << std::endl);
    5219              :                                         }
    5220              : 
    5221            0 :                                         if( ! segLimSids.hasUnclosedFaces() )
    5222              :                                         {
    5223              :                                                 UG_LOG("keine ungeschlossenen Gesichter " << std::endl);
    5224            0 :                                                 UG_THROW("keine ungeschlossenen Gesichter " << std::endl);
    5225              :                                         }
    5226              :                                 }
    5227              : 
    5228            0 :                                 if( vrtxIsBndVrt )
    5229              :                                 {
    5230              :                                         auto vecBndryManifelm = volElmInf.getVecBndryManifElem();
    5231              : 
    5232            0 :                                         IndexType sizeVecBndryManifElm = volElmInf.getVecBndryManifElem().size();
    5233              : 
    5234            0 :                                         boundarySites += sizeVecBndryManifElm;
    5235              : 
    5236              :         //                              if( ! segLimSids.schluckVecAttBndryElm( volElmInf.getVecBndryManifElem() ) )
    5237            0 :                                         if( ! segLimSids.schluckVecAttBndryElm( vecBndryManifelm ) )
    5238              :                                         {
    5239              :                                                 UG_LOG("schlucken B schief gegangen " << std::endl);
    5240            0 :                                                 UG_THROW("schlucken B schief gegangen " << std::endl);
    5241              :                                                 return false;
    5242              :                                         }
    5243              : 
    5244              :                                         // TODO FIXME es muss abgefangen werden, wenn bei einem boundary vertex gar keine boundary Seiten da sind
    5245              :         //                              if( (volElmInf.getVecBndryManifElem()).size() == 0  )
    5246            0 :                                         if( sizeVecBndryManifElm == 0  )
    5247            0 :                                                 UG_LOG("Grenze verloren gegangen " << m_aaPos[oldVrt] << std::endl);
    5248            0 :                                 }
    5249              : 
    5250              :                                 Volume * vol2Add = volElmInf.getFulldimElem();
    5251              :                                 segLimSids.schluckFulldimElem(vol2Add);
    5252              :                         }
    5253              : 
    5254            0 :                         if( vrtxIsBndVrt && boundarySites == 0 )
    5255              :                         {
    5256            0 :                                 UG_LOG("No boundary sites at " << m_aaPos[oldVrt] << std::endl);
    5257            0 :                                 UG_THROW("No boundary sites at " << m_aaPos[oldVrt] << std::endl);
    5258              :                         }
    5259              : 
    5260            0 :                         if( ! segLimSids.averageAll() )
    5261              :                         {
    5262              :                                 UG_LOG("keine Mittelung " << std::endl);
    5263            0 :                                 UG_THROW("keine Mittelung " << std::endl);
    5264              :                                 return false;
    5265              :                         }
    5266              : 
    5267            0 :                         vecSegmLimSid.push_back(segLimSids);
    5268            0 :                 }
    5269              : 
    5270              : 
    5271              :         }
    5272              : 
    5273              :         UG_LOG("END ESTABLISH SGEMENT LIM SIDE INFO" << std::endl );
    5274              : 
    5275              : 
    5276              :         return true;
    5277              : }
    5278              : 
    5279              : ///////////////////////////////////////////////////////////////////////
    5280              : 
    5281            0 : bool ArteExpandFracs3D::establishNewVertizesStasiBased( Vertex * const & oldVrt)
    5282              : {
    5283              : 
    5284            0 :         auto & vrtxFracPrps = m_aaMarkVrtVFP[ oldVrt ];
    5285              : 
    5286              :         bool vrtxIsBndVrt = vrtxFracPrps.getIsBndFracVertex();
    5287              : 
    5288              :         UG_LOG("is bndry " << vrtxIsBndVrt << std::endl);
    5289              : 
    5290              : 
    5291              : //      VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[oldVrt];
    5292              : //
    5293              : //      if( vecSegVolElmInf.size() < 2 )
    5294              : //      {
    5295              : //              UG_LOG("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5296              : ////            UG_THROW("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5297              : ////            return false;
    5298              : //              return true;
    5299              : //      }
    5300              : 
    5301            0 :         VecSegmentLimitingSides & vecSegmLimSid = m_vrtxAttAccsVecSegmLimSid[oldVrt];
    5302              : 
    5303            0 :         if(  vecSegmLimSid.size() == 0 )
    5304              :         {
    5305              :                 UG_LOG("keine verschiedenen Segmente" << std::endl);
    5306            0 :                 return true;
    5307              :         }
    5308              : 
    5309            0 :         if( vecSegmLimSid.size() == 1 )
    5310              :         {
    5311              :                 UG_LOG("sonderbarer Fall von nur einem Segment " << std::endl );
    5312            0 :                 UG_THROW("sonderbarer Fall von nur einem Segment " << std::endl );
    5313              :                 return false;
    5314              :         }
    5315              : 
    5316            0 :         for( SegmentLimitingSides & segLimSids : vecSegmLimSid )
    5317              :         {
    5318              : 
    5319            0 :                 if( segLimSids.hasUnclosedFaces() )
    5320              :                 {
    5321              :                         UG_LOG("beim ausdehnen ungeschlossene Gesichter " << std::endl);
    5322              :                 }
    5323              : 
    5324            0 :                 if( ! expandWithinTheSegment( segLimSids ) )
    5325              :                 {
    5326              :                         UG_LOG("schief gegangen Vertex Erzeugung " << std::endl);
    5327              :                         //UG_THROW("schief gegangen Vertex Erzeugung " << std::endl);
    5328              :                         return false;
    5329              :                 }
    5330              :         }
    5331              : 
    5332              :         // collect information for diamonds already now, get the crossing points
    5333              : 
    5334              :         bool isCrossingPt = ( vecSegmLimSid.size() > 2 );
    5335              : 
    5336            0 :         if( isCrossingPt )
    5337            0 :                 m_vrtcsCrossingPts.push_back(oldVrt);
    5338              : 
    5339              :         UG_LOG("Vertex creation hat funktioniert " << std::endl);
    5340              :         //      UG_THROW("Vertex creation failed " << std::endl);
    5341              : 
    5342            0 :         return true;
    5343              : 
    5344              : }
    5345              : 
    5346              : /////////////////////////////////////////////////////////////////
    5347              : 
    5348              : #if 0
    5349              : 
    5350              : bool ArteExpandFracs3D::establishNewVertizesStasiBased( Vertex * const & oldVrt)
    5351              : {
    5352              :         // anfangs nur für innere Vertizes mit einer fracture
    5353              : 
    5354              :         // testweise, später verallgemeinert mit den Boundary faces
    5355              : 
    5356              :         auto & vrtxFracPrps = m_aaMarkVrtVFP[ oldVrt ];
    5357              : 
    5358              :         bool vrtxIsBndVrt = vrtxFracPrps.getIsBndFracVertex();
    5359              : 
    5360              :         UG_LOG("is bndry " << vrtxIsBndVrt << std::endl);
    5361              : 
    5362              : //      if( vrtxIsBndVrt )
    5363              : //      {
    5364              : //              UG_LOG("boundary noch zu lösen, bisher nix machen" << std::endl);
    5365              : //              return true;
    5366              : //      }
    5367              : 
    5368              :         VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[oldVrt];
    5369              : 
    5370              :         if( vecSegVolElmInf.size() < 2 )
    5371              :         {
    5372              :                 UG_LOG("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5373              : //              UG_THROW("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5374              : //              return false;
    5375              :                 return true;
    5376              :         }
    5377              : 
    5378              : 
    5379              :         for( SegmentVolElmInfo const & segVolsElInf : vecSegVolElmInf )
    5380              :         {
    5381              :                 // count the number of the fracture subdomains surrounding the segment
    5382              :                 // in case of boundary vertex, also count the number of boundary subdomains
    5383              : 
    5384              : //              std::vector<IndexType> sudosInSegment;
    5385              : 
    5386              :                 // hier die neue Klasse und ihr averaing einführen, oder im Hauptloop der neuen Elemente.....
    5387              :                 // SegmentSides<....> in .h file für die richtigen template parameter Kurznamen geben und hier
    5388              :                 // Objekt erstellen und je nach ob mit oder ohne Bndry entsprechend aufladen und averagen.....
    5389              :                 // und zwar für jedes Segment einzeln, und abhängig von boundary oder nicht die boundary Geschichten
    5390              :                 // dazu oder auch nicht...... also einen VecSegmentSides erstellen auch, das einzelne Objekt
    5391              :                 // weiss dann, ob es eine Boundary ist..... vielleicht noch den Vektor dazu als übergebener Parameter
    5392              :                 // damit man den da drin weiter reichen kann?
    5393              :                 // wenn jedes Objekt des Vektors von SegmentSIdes sowohl seinen Vertex kennt als auch weiss,
    5394              :                 // ob es boundary oder nicht ist, kann danach darüber geloopt werden, ohne nochmal
    5395              :                 // aussen den Vertex mit geben zu müssen, oder die Info, ob bndry oder nicht.....
    5396              :                 // danach gibts dann Funktionen, die alleine ein Objekt von der Sorte SegmentSides schlucken brauchen
    5397              :                 // und hier nur ein Loop über den ganzen Vektor davon, wo für jedes Element dann die Fkt aufgerufen wird....
    5398              : 
    5399              :                 SegmentLimitingSides segLimSids( oldVrt, vrtxIsBndVrt );
    5400              : 
    5401              : //              std::vector<Volume*> vecVolsOfSegment;
    5402              : 
    5403              :                 IndexType boundarySites = 0;
    5404              : 
    5405              :                 for( AttachedVolumeElemInfo const & volElmInf : segVolsElInf )
    5406              :                 {
    5407              :                         if( ! segLimSids.schluckVecAttFractElm( volElmInf.getVecFractManifElem() ) )
    5408              :                         {
    5409              :                                 UG_LOG("schlucken schief gegangen " << std::endl);
    5410              :                                 UG_THROW("schlucken schief gegangen " << std::endl);
    5411              :                                 return false;
    5412              :                         }
    5413              : 
    5414              :                         if( vrtxIsBndVrt )
    5415              :                         {
    5416              :                                 auto vecBndryManifelm = volElmInf.getVecBndryManifElem();
    5417              : 
    5418              :                                 IndexType sizeVecBndryManifElm = volElmInf.getVecBndryManifElem().size();
    5419              : 
    5420              :                                 boundarySites += sizeVecBndryManifElm;
    5421              : 
    5422              : //                              if( ! segLimSids.schluckVecAttBndryElm( volElmInf.getVecBndryManifElem() ) )
    5423              :                                 if( ! segLimSids.schluckVecAttBndryElm( vecBndryManifelm ) )
    5424              :                                 {
    5425              :                                         UG_LOG("schlucken B schief gegangen " << std::endl);
    5426              :                                         UG_THROW("schlucken B schief gegangen " << std::endl);
    5427              :                                         return false;
    5428              :                                 }
    5429              : 
    5430              :                                 // TODO FIXME es muss abgefangen werden, wenn bei einem boundary vertex gar keine boundary Seiten da sind
    5431              : //                              if( (volElmInf.getVecBndryManifElem()).size() == 0  )
    5432              :                                 if( sizeVecBndryManifElm == 0  )
    5433              :                                         UG_LOG("Grenze verloren gegangen " << m_aaPos[oldVrt] << std::endl);
    5434              :                         }
    5435              : 
    5436              :                         Volume * vol2Add = volElmInf.getFulldimElem();
    5437              :                         segLimSids.schluckFulldimElem(vol2Add);
    5438              :                 }
    5439              : 
    5440              :                 if( vrtxIsBndVrt && boundarySites == 0 )
    5441              :                 {
    5442              :                         UG_LOG("No boundary sites at " << m_aaPos[oldVrt] << std::endl);
    5443              :                         UG_THROW("No boundary sites at " << m_aaPos[oldVrt] << std::endl);
    5444              :                 }
    5445              : 
    5446              :                 if( ! segLimSids.averageAll() )
    5447              :                 {
    5448              :                         UG_LOG("keine Mittelung " << std::endl);
    5449              :                         UG_THROW("keine Mittelung " << std::endl);
    5450              :                         return false;
    5451              :                 }
    5452              : 
    5453              : //              if( vrtxIsBndVrt )
    5454              : //              {
    5455              : //                      if( segLimSids. )
    5456              : //              }
    5457              : 
    5458              : //              for( SegmentLimitSidesPairSudoNorml segLimSiPSN : vecSegmLimSidPrSudoNorml )
    5459              : //              {
    5460              : //
    5461              : //              }
    5462              : 
    5463              : //              expandWithinTheSegment<SegmentVrtxFracStatus::oneFracSuDoAtt>(segLimSids
    5464              : 
    5465              :                 if( ! expandWithinTheSegment(segLimSids) )
    5466              :                 {
    5467              :                         UG_LOG("schief gegangen Vertex Erzeugung " << std::endl);
    5468              :                         UG_THROW("schief gegangen Vertex Erzeugung " << std::endl);
    5469              :                         return false;
    5470              :                 }
    5471              : 
    5472              : //              SegmentVrtxFracStatus segStatFract = segLimSids.spuckCrossingTyp();
    5473              : //
    5474              : //              switch( segStatFract )
    5475              : //              {
    5476              : //                      case SegmentVrtxFracStatus::noFracSuDoAtt :
    5477              : //                      {
    5478              : //                              UG_LOG("is not a fracture, but a segment?" << std::endl);
    5479              : //                              UG_THROW("is not a fracture, but a segment?" << std::endl);
    5480              : //                              return false;
    5481              : //                      }
    5482              : //                      case SegmentVrtxFracStatus::oneFracSuDoAtt :
    5483              : //                      {
    5484              : //                              if( ! expandWithinTheSegment<SegmentVrtxFracStatus::oneFracSuDoAtt,false,false>(segLimSids, vecVolsOfSegment) )
    5485              : //                              {
    5486              : //                                      UG_LOG("Expandierung 1 schief gegangen " << std::endl);
    5487              : //                                      UG_THROW("Expandierung 1 schief gegangen " << std::endl);
    5488              : //                                      return false;
    5489              : //                              }
    5490              : //                              break;
    5491              : //                      }
    5492              : //                      case SegmentVrtxFracStatus::twoFracSuDoAtt :
    5493              : //                      {
    5494              : //                              break; // TODO FIXME implementieren
    5495              : //                      }
    5496              : //                      case SegmentVrtxFracStatus::threeFracSuDoAtt :
    5497              : //                      {
    5498              : //                              if( ! expandWithinTheSegment<SegmentVrtxFracStatus::threeFracSuDoAtt,false,false>(segLimSids, vecVolsOfSegment) )
    5499              : //                              {
    5500              : //                                      UG_LOG("Expandierung 3 schief gegangen " << std::endl);
    5501              : //                                      UG_THROW("Expandierung 3 schief gegangen " << std::endl);
    5502              : //                                      return false;
    5503              : //                              }
    5504              : //                              break;
    5505              : //                      }
    5506              : //                      default :
    5507              : //                      {
    5508              : //                              UG_LOG("strange fracture crossing" << std::endl);
    5509              : //                              UG_THROW("strange fracture crossing?" << std::endl);
    5510              : //                              return false;
    5511              : //                      }
    5512              : //              }
    5513              :         }
    5514              : 
    5515              :         UG_LOG("Vertex creation hat funktioniert " << std::endl);
    5516              :         //      UG_THROW("Vertex creation failed " << std::endl);
    5517              : 
    5518              :         return true;
    5519              : }
    5520              : 
    5521              : #endif
    5522              : 
    5523              : //              if( ! extracFractSudosOfSegment( svei, sudosInSegment ) )
    5524              : //              {
    5525              : //                      UG_LOG("kann sudos nicht extrahieren " << std::endl);
    5526              : //                      UG_THROW("kann sudos nicht extrahieren " << std::endl);
    5527              : //                      return false;
    5528              : //              }
    5529              : //
    5530              : //              IndexType sudoNumInSeg = sudosInSegment.size();
    5531              : //
    5532              : //              // check if is boundary vertex
    5533              : //
    5534              : //              auto & vrtxFracPrps = m_aaMarkVrtVFP[ oldVrt ];
    5535              : //
    5536              : //
    5537              : //              if( ! vrtxIsBndVrt )
    5538              : //              {
    5539              : //                      // count number of fracture subdomains in the Segment, should have been done before......
    5540              : //
    5541              : //                      // TODO FIXME ersetze das altmodische VrtxFracProptsStatus durch ein Zählen
    5542              : //                      // der subdomains, die pro Segment wirklich vorkommen, nachdem die
    5543              : //                      // auslaufenden fracture faces den generellen Faces zugeschlagen worden sind
    5544              : //                      // diese Zählweise ist die erste Folgeaufgabe, damit der komische vrtxFractureProperties Status
    5545              : //                      // weg geworfen werden kann, der ist nämlich nutzlos inzwischen, da er auch auslaufende
    5546              : //                      // fracture faces zählt, was Unsinn ist.......
    5547              : //                      // später folgt auch die Verallgemeinerung auf boundary vertizes, dann muss deren Wahl
    5548              : //                      // vielleicht wieder dazu genommen werden.....
    5549              : //
    5550              : //                      //Vorbereitung Ersetzung VertexFractureProperties Status
    5551              : //                      // durch Zählen der Fracture Subdomains von jedem Segment
    5552              : //                      // die Zählerei kann dann gemacht werden, wenn die doppelten offenen fracture faces
    5553              : //                      // in die allgemeinen faces verschoben werden, dann geht das in einem Abwasch,
    5554              : //                      // gehe dazu in die entsprechende Funktion
    5555              : //
    5556              : ////                    if( vrtxFracPrps.getVrtxFracStatus() == VrtxFracProptsStatus::oneFracSuDoAtt )
    5557              : //                      if( sudoNumInSeg == 1 )
    5558              : //                      {
    5559              : //                              // standard case, one fracture
    5560              : //                              if( ! expandWithinTheSegment<1,false>( oldVrt, svei ) )
    5561              : //                              {
    5562              : //                                      UG_LOG("Expandierung einfachster Fall schief gegangen " << std::endl);
    5563              : //                                      return false;
    5564              : //                              }
    5565              : //                      }
    5566              : //                      else // unterscheiden zwei und drei vermutlich..... aber wichtiger Segmentzahl..... und dann kommt es darauf an, wieviele subdoms im einzelnen Segment sind
    5567              : //                      {
    5568              : //
    5569              : //                      }
    5570              : //
    5571              : //              }
    5572              : //              else
    5573              : //              {
    5574              : //                      // boundary faces counted as fracture faces, but no expansion
    5575              : //                      // zuerst aber die inneren Schnittvertizes, weil bei denen die Nicht-Null Expansion
    5576              : //                      // gelernt werden kann, dann anzuwenden auf Null-Expansion senkrecht zu den boundaries......
    5577              : //              }
    5578              : //
    5579              : //      }
    5580              : 
    5581              : //      UG_LOG("Vertex creation failed " << std::endl);
    5582              : //      UG_THROW("Vertex creation failed " << std::endl);
    5583              : //
    5584              : //
    5585              : //      return false;
    5586              : //
    5587              : 
    5588              : 
    5589              : ////////////////////////////////////////////////////////////////////
    5590              : 
    5591              : #if 0
    5592              : bool ArteExpandFracs3D::extracFractSudosOfSegment( SegmentVolElmInfo const & segmVolElmInfo, std::vector<ArteExpandFracs3D::IndexType> & sudosInSegment )
    5593              : {
    5594              : 
    5595              : 
    5596              :         VecAttachedFractFaceEdgeSudo vecAttFractFaces;
    5597              : 
    5598              :         for( AttachedVolumeElemInfo const & avei : segmVolElmInfo )
    5599              :         {
    5600              :                 VecAttachedFractFaceEdgeSudo const & vecAttFractVol = avei.getVecFractManifElem();
    5601              : 
    5602              :                 for( AttachedFractFaceEdgeSudo const & affe : vecAttFractVol )
    5603              :                 {
    5604              :                         vecAttFractFaces.push_back(affe);
    5605              :                 }
    5606              :         }
    5607              : 
    5608              :         IndexType numbContrFracFaces = vecAttFractFaces.size();
    5609              : 
    5610              :         if( numbContrFracFaces < 1 )
    5611              :         {
    5612              :                 UG_LOG("Kein Affe da " << std::endl);
    5613              :                 UG_THROW("Kein Affe da " << std::endl);
    5614              :                 return false;
    5615              :         }
    5616              : 
    5617              :         IndexType sudoBase = vecAttFractFaces[0].getSudo();
    5618              : 
    5619              :         sudosInSegment.push_back(sudoBase);
    5620              : 
    5621              :         // add sudos different from the base one
    5622              :         for( AttachedFractFaceEdgeSudo const & affe : vecAttFractFaces )
    5623              :         {
    5624              :                 IndexType sudoNeeded = affe.getSudo();
    5625              : 
    5626              :                 bool sudoIsKnown = false;
    5627              : 
    5628              :                 for( IndexType sudoInList : sudosInSegment )
    5629              :                 {
    5630              :                         if( sudoNeeded == sudoInList )
    5631              :                         {
    5632              :                                 sudoIsKnown = true;
    5633              :                         }
    5634              :                 }
    5635              : 
    5636              :                 if( ! sudoIsKnown )
    5637              :                 {
    5638              :                         sudosInSegment.push_back(sudoNeeded);
    5639              :                 }
    5640              : 
    5641              :         }
    5642              : 
    5643              :         return true;
    5644              : }
    5645              : #endif
    5646              : 
    5647              : 
    5648              : ////////////////////////////////////////////////////////////////////
    5649              : // for only one surrounding subdom around the segment, for example only one fracture, or T End like ending side
    5650              : // TODO FIXME alles in eine einzige Funktion, die verschiedene Unterfunktionen aufruft für verschiedene Zahlen
    5651              : // von Seiten innen und aussen!!!!
    5652              : //template<>
    5653              : //bool ArteExpandFracs3D::expandWithinTheSegment<ArteExpandFracs3D::SegmentVrtxFracStatus::oneFracSuDoAtt>( SegmentLimitingSides const & segmLimSides )
    5654            0 : bool ArteExpandFracs3D::expandWithinTheSegment( ArteExpandFracs3D::SegmentLimitingSides & segmLimSides )
    5655              : {
    5656              :         // should not be called for boundary vertices
    5657              : 
    5658              :         bool isBndry = segmLimSides.isBoundary();
    5659              : 
    5660              : 
    5661              : //      if( isBndry )
    5662              : //              return true;
    5663              : 
    5664              : //      if( isBndry )
    5665              : //      {
    5666              : //              UG_LOG("boundary noch zu behandeln " << std::endl);
    5667              : //              UG_THROW("boundary noch zu behandeln " << std::endl);
    5668              : //              return false;
    5669              : //      }
    5670              : 
    5671              : //      VecSegmentLimitSidesPairSudoNorml vecSegmLimSidPrSudoNrml;
    5672              :         VecPlaneDescriptor vecPlaneFracDescr;
    5673              : 
    5674              :         //      if( ! segmLimSides.spuckFractSudoNormls( vecSegmLimSidPrSudoNrml ) )
    5675            0 :         if( ! segmLimSides.spuckFractManifDescr( vecPlaneFracDescr, m_aaPos ) )
    5676              :         {
    5677            0 :                 UG_LOG("Spucken schief gegangen  " << segmLimSides.spuckCrossingTyp() << std::endl);
    5678            0 :                 UG_THROW("Spucken schief gegangen  " << segmLimSides.spuckCrossingTyp() << std::endl);
    5679              :                 return false;
    5680              :         }
    5681              : 
    5682              :         // falls Boundary, hier noch spuckBndryManifDescr aufrufen
    5683              : 
    5684            0 :         Vertex * oldVrt = segmLimSides.spuckVertex();
    5685              :         vector3 posOldVrt = m_aaPos[oldVrt];
    5686              : 
    5687              :         VecPlaneDescriptor vecShiftedPlaneDescript;
    5688              : 
    5689              : //      for( SegmentLimitSidesPairSudoNorml const & segLimSidPrSN : vecSegmLimSidPrSudoNrml )
    5690            0 :         for( PlaneDescriptor & planeDescr : vecPlaneFracDescr )
    5691              :         {
    5692            0 :                 UG_LOG("GOT MANIF TYP " << planeDescr.spuckManifTyp() << std::endl );
    5693              : //              IndexType const & sudoSide = segLimSidPrSN.first;
    5694              : //              vector3 const & normlAvrg = segLimSidPrSN.second;
    5695              : //
    5696              : //              // normal computed standard mässig directs of of the volume, we need that one into the volume
    5697              : //              vector3 normalOutsideVol;
    5698              : 
    5699              :                 // hier testen, ob die Subdomain von der Liste der fracture subdomains ist,
    5700              :                 // damit für den Fall von sich zwei schneidenden Ebenen für die dritte,
    5701              :                 // die als senkrecht zu den beiden anderen gesetzt werden soll, mit Verschiebung null,
    5702              :                 // analog Boundary sides, die künstliche Weite null erhalten kann hier
    5703              : 
    5704            0 :                 if( planeDescr.spuckManifTyp() != PlaneDescriptorType::isFracture )
    5705            0 :                         UG_THROW("muss fracture sein " << std::endl);
    5706              : //
    5707              :                 int sudoSide = planeDescr.spuckSudo();
    5708            0 :                 number width = m_fracInfosBySubset[sudoSide].width;;
    5709              : 
    5710              :                 // ensure that the width is nonzero only for real fractures, not for pseudo vectors or such stuff
    5711              : //              if( ! isBndry )
    5712              : //              {
    5713              : //                      if( planeDescr.spuckManifTyp() == PlaneDescriptorType::isFracture )
    5714              : //                      {
    5715              : //                              width = m_fracInfosBySubset[sudoSide].width;
    5716              : //                      }
    5717              : //                      else
    5718              : //                      {
    5719              : //                              UG_LOG("Manif Typ is " << planeDescr.spuckManifTyp() << std::endl );
    5720              : //                              UG_LOG("Fract wäre " << PlaneDescriptorType::isFracture << std::endl );
    5721              : //                              UG_LOG("Bndry wäre " << PlaneDescriptorType:: << std::endl );
    5722              : //                              UG_LOG("Artif wäre " << PlaneDescriptorType::isArtificial << std::endl );
    5723              : //
    5724              : //                              UG_THROW("keine Boundary, aber will Boundary Manif" << std::endl);
    5725              : //                      }
    5726              : //              }
    5727              : //              else
    5728              : //              {
    5729              : //                      UG_THROW("hier nur keine boundary" << std::endl);
    5730              : //              }
    5731              : 
    5732              : 
    5733              : //              else
    5734              : //              {
    5735              : //      TODO FIXME              bei boundary auch noch für die entsprechenden boundaries
    5736              : //              }
    5737              : 
    5738            0 :                 number shiftScal = width / 2.;
    5739            0 :                 planeDescr.schluckScaleShiftNormal( - shiftScal );
    5740              : 
    5741              : //              vector3 shiftVec4Plane;
    5742              : //
    5743              : //              // as normal outside vol, but we need to go inside the volumes / segment side
    5744              : //              VecScale( shiftVec4Plane, normalOutsideVol, - shiftScal );
    5745              : 
    5746              : //              vecShiftVec4Plane.push_back( shiftVec4Plane );
    5747              : //              vecSudosSides.push_back( sudoSide );
    5748              : //              vecNormalsAveraged.push_back( normalIntoVol );
    5749              : 
    5750              : //              PlaneDescriptor planeDescr( normalOutsideVol, posOldVrt, shiftScal );
    5751              : 
    5752              :                 PlaneDescriptor shiftedPlaneDescr;
    5753            0 :                 planeDescr.spuckPlaneShifted( shiftedPlaneDescr );
    5754              : 
    5755              :                 //              planeDescr.spuckPlaneShiftedAlong( shiftVec4Plane, shiftedPlaneDescr );
    5756              : 
    5757            0 :                 vecShiftedPlaneDescript.push_back( shiftedPlaneDescr );
    5758              :         }
    5759              : 
    5760              :         // TODO FIXME test if the new points might squeeze the volumes
    5761              : 
    5762              : //      std::vector<Volume*> volsOfSegm;
    5763              : //
    5764              : //      if( ! segmLimSides.spuckListLowdimElmsOfVols( volsOfSegm, m_grid ) )
    5765              : //      {
    5766              : //              UG_LOG("which attached edges? " << std::endl);
    5767              : //              UG_LOG("which attached edges? " << std::endl);
    5768              : //      }
    5769              : 
    5770            0 :         bool testNewPoints = testIfNewPointsSqueezeVolumes( segmLimSides, vecShiftedPlaneDescript );
    5771              : 
    5772              :         UG_LOG("TESTING NEW POINTS IS " << testNewPoints << " of " << true << " or " << false << std::endl);
    5773              : 
    5774              : //      if( ! testIfNewPointsSqueezeVolumes( segmLimSides, vecShiftedPlaneDescript ) )
    5775            0 :         if( ! testNewPoints )
    5776              :         {
    5777              :                 UG_LOG("CAUTION: expansion probably violates the surrounding volumes!" << std::endl);
    5778              : //              return false;
    5779              :         }
    5780              : 
    5781              :         // will get the sudo of the shifted vertex
    5782              :         IndexType sudoExample = (vecPlaneFracDescr[0]).spuckSudo();
    5783              :         vector3 posNewVrt; // to be determined depending on the segment properties
    5784              : 
    5785              :         bool hasUnclosedFaces = segmLimSides.hasUnclosedFaces();
    5786              : 
    5787            0 :         if( hasUnclosedFaces )
    5788              :         {
    5789              :                 UG_LOG("hat ungeschlossene Seiten " << std::endl);
    5790              :         }
    5791              : 
    5792            0 :         if( ! isBndry && vecShiftedPlaneDescript.size() == 1 )
    5793              :         {
    5794              :                 // die unclosed crossing faces behandeln!!!
    5795              : 
    5796              :                 // muss wieder eingeschaltet werden hier
    5797              :                 // use the hasUnclosedFaces property, but for visual debugging, better set as false
    5798              :                 bool distinguishUnclosedFaces = segmLimSides.hasUnclosedFaces();
    5799              : //              constexpr bool distinguishUnclosedFaces = false; // segmLimSides.hasUnclosedFaces();
    5800              :                 UG_LOG("Please use switch unclosed faces in final version, please remove debugging set false" << std::endl);
    5801              : 
    5802            0 :                 if( ! distinguishUnclosedFaces ) // standard case, just shift perpendicular to the plane, no SLE to solve
    5803              :                 {
    5804              :                         //              // one single inner fracture, Testfall Anfang
    5805              :                         //              computeShiftVector( vecShiftedPlaneDescript[0] );
    5806            0 :                         posNewVrt = (vecPlaneFracDescr[0]).spuckShiftedBaseVect();
    5807              : 
    5808              :                 }
    5809              :                 else
    5810              :                 {
    5811              :                         // NOTE: TODO FIXME funktioniert vermutlich auch, wenn der Vertex ein Boundary Vertex ist
    5812              :                         // ob der Spezialfall aber auch praktisch vorkommt, fragwürdig
    5813              :                         // Test der Methode erstmal innen drin, später ggf. Ausweitung auf Grenzvertizes
    5814              :                         // dann würde das hier raus wandern aus dem Frage ob Boundary oder nicht, isBndry wäre egal
    5815              :                         // relevant wäre dass size des vecShiftPlaneDescr 1 ist und withUnclosedFaces true
    5816              : 
    5817              : 
    5818            0 :                         Edge * shiftDirectionEdg = nullptr;
    5819              : 
    5820              :                         if( ! segmLimSides.spuckLowdimElmShiftDirectionIfUnclosedFractPresent(shiftDirectionEdg) )
    5821              :                         {
    5822              :                                 UG_LOG("no shift direction " << std::endl);
    5823            0 :                                 UG_THROW("no shift direction " << std::endl);
    5824              : 
    5825              :                         }
    5826              : 
    5827              :                         if( shiftDirectionEdg == nullptr )
    5828              :                         {
    5829              :                                 UG_LOG("Null Shift cross end?" << std::endl);
    5830              :                                 UG_THROW("Null Shift cross end?" << std::endl);
    5831              :                         }
    5832              : 
    5833              :                         // jetzt sollte also die shift direction bekannt sein, muss normalisiert werden,
    5834              :                         // vielleicht kann man das im PlaneDescriptor drin auch machen
    5835              : 
    5836              :                         PlaneDescriptor const & shiftedPlane = vecShiftedPlaneDescript[0];
    5837              : 
    5838              : 
    5839            0 :                         if( ! computeCrossPointOfPlaneWithLine( shiftedPlane, shiftDirectionEdg, oldVrt, posNewVrt ) )
    5840              :                         {
    5841              :                                 UG_LOG("CAUTION: shifting cross point along ending crossing cleft edge might break volumes " << std::endl);
    5842              : 
    5843              : //                              UG_LOG("Not possible to compute crossing point plane with line" << std::endl);
    5844              : //                              UG_THROW("Not possible to compute crossing point plane with line" << std::endl);
    5845              :                         }
    5846              :                 }
    5847              :         }
    5848              :         else
    5849              :         {
    5850            0 :                 if( ! isBndry && vecShiftedPlaneDescript.size() > 1 )
    5851              :                 {
    5852              : 
    5853            0 :                         if( vecShiftedPlaneDescript.size() == 2 )
    5854              :                         {
    5855              :                                 // we need to add an artificial plane which gets extended with scale 0
    5856              : 
    5857              :                                 vector3 artificialNormal;
    5858            0 :                                 VecCross( artificialNormal, vecShiftedPlaneDescript[0].spuckNormalVector(), vecShiftedPlaneDescript[1].spuckNormalVector() );
    5859              : 
    5860            0 :                                 PlaneDescriptor artificialPlane( artificialNormal, posOldVrt );
    5861              : 
    5862            0 :                                 vecShiftedPlaneDescript.push_back(artificialPlane);
    5863              :                         }
    5864              : 
    5865            0 :                         if( vecShiftedPlaneDescript.size() > 3  )
    5866            0 :                                 UG_THROW("too much fractures" << std::endl);
    5867              : 
    5868              :                         // now we should have three planes to cross
    5869              : 
    5870              :                 }
    5871            0 :                 else if( isBndry )
    5872              :                 {
    5873              :                         VecPlaneDescriptor vecPlaneBndryDescr;
    5874              : 
    5875              :                         //      if( ! segmLimSides.spuckFractSudoNormls( vecSegmLimSidPrSudoNrml ) )
    5876            0 :                         if( ! segmLimSides.spuckBndryManifDescr( vecPlaneBndryDescr, m_aaPos ) )
    5877              :                         {
    5878            0 :                                 UG_LOG("Spucken schief gegangen bndry " << segmLimSides.spuckCrossingTyp() << std::endl);
    5879            0 :                                 UG_THROW("Spucken schief gegangen bndry " << segmLimSides.spuckCrossingTyp() << std::endl);
    5880              :                                 return false;
    5881              :                         }
    5882              : 
    5883            0 :                         if( vecPlaneBndryDescr.size() < 1 )
    5884              :                         {
    5885            0 :                                 UG_LOG("at point " << m_aaPos[oldVrt] << std::endl);
    5886              : 
    5887            0 :                                 UG_LOG("BOUNRARY PPPPP vertex BOUNDARY size problem " << m_aaPos[oldVrt] << std::endl);
    5888              : 
    5889              :                                 UG_LOG("Boundaries" << std::endl);
    5890            0 :                                 for( PlaneDescriptor pd : vecPlaneBndryDescr  )
    5891              :                                 {
    5892            0 :                                         UG_LOG("Subdom " << pd.spuckSudo() << std::endl);
    5893            0 :                                         UG_LOG("Base " << pd.spuckBaseVector() << std::endl);
    5894            0 :                                         UG_LOG("Normal " << pd.spuckNormalVector() <<std::endl);
    5895              :                                 }
    5896              : 
    5897              :                                 UG_LOG("Shifted" << std::endl);
    5898            0 :                                 for( PlaneDescriptor pd : vecShiftedPlaneDescript  )
    5899              :                                 {
    5900            0 :                                         UG_LOG("Subdom S " << pd.spuckSudo() << std::endl);
    5901            0 :                                         UG_LOG("Base S " << pd.spuckBaseVector() << std::endl);
    5902            0 :                                         UG_LOG("Normal S " << pd.spuckNormalVector() <<std::endl);
    5903              :                                 }
    5904              : 
    5905              :                                 UG_LOG("Fracs " << std::endl);
    5906            0 :                                 for( PlaneDescriptor pd : vecPlaneFracDescr  )
    5907              :                                 {
    5908            0 :                                         UG_LOG("Subdom F " << pd.spuckSudo() << std::endl);
    5909            0 :                                         UG_LOG("Base F " << pd.spuckBaseVector() << std::endl);
    5910            0 :                                         UG_LOG("Normal F " << pd.spuckNormalVector() <<std::endl);
    5911              :                                 }
    5912              : 
    5913              : 
    5914              :                                 // PROBLEM PPPPPPPPPPPPPPPPP
    5915            0 :                                 UG_THROW("NO boundary sudos " << std::endl);
    5916              :                         }
    5917              : 
    5918              :                         bool needToAverage = false;
    5919              : 
    5920            0 :                         if( vecPlaneBndryDescr.size() > 2 )
    5921              :                         {
    5922              : 
    5923              :                                 UG_LOG("dudos" << std::endl);
    5924            0 :                                 for( PlaneDescriptor pd : vecPlaneBndryDescr )
    5925              :                                 {
    5926              :                                         int sudo = pd.spuckSudo();
    5927            0 :                                         UG_LOG("sudos " << sudo << std::endl);
    5928              : 
    5929              :                                 }
    5930            0 :                                 UG_LOG("at point " << m_aaPos[oldVrt] << std::endl);
    5931              :                                 UG_LOG("too much boundary sudos - NEED TO AVERAGE OVER ALL - introduce pseudo boundary descriptor, size 1" << vecPlaneBndryDescr.size() << std::endl);
    5932              : 
    5933              :                                 needToAverage = true;
    5934              :                         }
    5935            0 :                         else if( vecPlaneBndryDescr.size() == 2 )
    5936              :                         {
    5937            0 :                                 if( vecPlaneFracDescr.size() == 2  )
    5938              :                                 {
    5939              :                                         UG_LOG("zwei Boundary subdoms plus zwei Kreuzungen " << std::endl);
    5940              :                                         needToAverage = true;
    5941              :                                 }
    5942              :                                 else
    5943              :                                 {
    5944              :                                         // depending on angle between the two boundary normals, an averaging also useful, if too similar
    5945              : 
    5946              :                                         vector3 const & normalOne = vecPlaneBndryDescr[0].spuckNormalVector();
    5947              :                                         vector3 const & normalTwo = vecPlaneBndryDescr[1].spuckNormalVector();
    5948              : 
    5949              :                                         number lengthOne = VecLength(normalOne);
    5950              :                                         number lengthTwo = VecLength(normalTwo);
    5951              : 
    5952              :                                         vector3 crossVec;
    5953              : 
    5954            0 :                                         VecCross(crossVec, normalOne, normalTwo);
    5955              : 
    5956              :                                         number crossProdBetween = VecLength(crossVec);
    5957              : 
    5958              :                                         number tol = 1e-1;
    5959              : 
    5960            0 :                                         number deviationOne = std::fabs( (lengthOne - 1.) / (lengthOne + 1 ) );
    5961            0 :                                         number deviationTwo = std::fabs( (lengthTwo - 1.) / (lengthTwo + 1 ) );
    5962              : 
    5963            0 :                                         if( deviationOne > tol || deviationTwo > tol )
    5964              :                                         {
    5965            0 :                                                 UG_LOG("Normals no length one " << normalOne << " " << normalTwo << std::endl);
    5966            0 :                                                 UG_THROW("Normals no length one " << normalOne << " " << normalTwo << std::endl);
    5967              :                                         }
    5968              : 
    5969            0 :                                         number sinBetween = std::fabs( crossProdBetween / lengthOne / lengthTwo );
    5970              : 
    5971              :                                         number decisionSin = 0.05;
    5972              : 
    5973            0 :                                         if( decisionSin > sinBetween )
    5974              :                                         {
    5975              :                                                 needToAverage = true;
    5976              : //                                              m_sh.assign_subset(oldVrt, m_sh.num_subsets());
    5977              : //                                              return false;
    5978              : 
    5979              :                                         }
    5980              : 
    5981              :                                         // very close, so better average, as they might be even parallel
    5982              :                                 }
    5983              :                         }
    5984              : 
    5985              : 
    5986              : 
    5987              :                         if( ! needToAverage  )
    5988              :                         {
    5989              : 
    5990            0 :                                 if( vecShiftedPlaneDescript.size() + vecPlaneBndryDescr.size() > 3 )
    5991            0 :                                         UG_THROW("too much crossing stuff at boundary"<<std::endl);
    5992              : 
    5993            0 :                                 for( PlaneDescriptor const & pbd : vecPlaneBndryDescr )
    5994              :                                 {
    5995            0 :                                         vecShiftedPlaneDescript.push_back( pbd );
    5996              :                                 }
    5997              : 
    5998            0 :                                 if( vecPlaneBndryDescr.size() == 2 )
    5999              :                                 {
    6000              :                                         // PROBLEM PPPPPPPPPPPPPPPP
    6001            0 :                                         if( vecShiftedPlaneDescript.size() != 3 ||  vecPlaneFracDescr.size() != 1 )
    6002              :                                         {
    6003            0 :                                                 UG_LOG("BOUNRARY PPPPP vertex TWO problem " << m_aaPos[oldVrt] << std::endl);
    6004              : 
    6005              :                                                 UG_LOG("Boundaries" << std::endl);
    6006            0 :                                                 for( PlaneDescriptor pd : vecPlaneBndryDescr  )
    6007              :                                                 {
    6008            0 :                                                         UG_LOG("Subdom " << pd.spuckSudo() << std::endl);
    6009            0 :                                                         UG_LOG("Base " << pd.spuckBaseVector() << std::endl);
    6010            0 :                                                         UG_LOG("Normal " << pd.spuckNormalVector() <<std::endl);
    6011              :                                                 }
    6012              : 
    6013              :                                                 UG_LOG("Shifted" << std::endl);
    6014            0 :                                                 for( PlaneDescriptor pd : vecShiftedPlaneDescript  )
    6015              :                                                 {
    6016            0 :                                                         UG_LOG("Subdom S " << pd.spuckSudo() << std::endl);
    6017            0 :                                                         UG_LOG("Base S " << pd.spuckBaseVector() << std::endl);
    6018            0 :                                                         UG_LOG("Normal S " << pd.spuckNormalVector() <<std::endl);
    6019              :                                                 }
    6020              : 
    6021              :                                                 UG_LOG("Fracs " << std::endl);
    6022            0 :                                                 for( PlaneDescriptor pd : vecPlaneFracDescr  )
    6023              :                                                 {
    6024            0 :                                                         UG_LOG("Subdom F " << pd.spuckSudo() << std::endl);
    6025            0 :                                                         UG_LOG("Base F " << pd.spuckBaseVector() << std::endl);
    6026            0 :                                                         UG_LOG("Normal F " << pd.spuckNormalVector() <<std::endl);
    6027              :                                                 }
    6028              : 
    6029            0 :                                                 UG_THROW("noch nicht genug Grenzen " << std::endl);
    6030              : 
    6031              :                                         }
    6032              :                                 }
    6033            0 :                                 else if( vecPlaneBndryDescr.size() == 1 )
    6034              :                                 {
    6035            0 :                                         if( vecShiftedPlaneDescript.size() < 3 )
    6036              :                                                 UG_LOG("noch nicht genug Grenzen " << std::endl);
    6037              : 
    6038            0 :                                         if( vecShiftedPlaneDescript.size() > 3 )
    6039              :                                                 UG_LOG("too much Grenzen " << std::endl);
    6040              : 
    6041            0 :                                         if( vecPlaneFracDescr.size() != 1 && vecPlaneFracDescr.size() != 2 )
    6042            0 :                                                 UG_THROW("Nicht passend Fract plus Bndry" << std::endl);
    6043              : 
    6044              :         //                              if( vecPlaneFracDescr.size() == 1 && vecPlaneFracDescr.size() == 2 )
    6045              :         //                                      if( vecShiftedPlaneDescript.size() != 3 )
    6046              :         //                                              UG_THROW"SO viele unsinnige Kombinationen " << std::endl );
    6047              : 
    6048            0 :                                         if( vecPlaneFracDescr.size() == 2 )
    6049              :                                         {
    6050            0 :                                                 if( vecShiftedPlaneDescript.size() != 3 )
    6051            0 :                                                         UG_THROW("da passt nicht zusammen was 3 sein sollte" << std::endl);
    6052              : 
    6053              :                                                 // sonst nix zu tun
    6054              :                                         }
    6055              :                                         else if( vecPlaneFracDescr.size() == 1 )
    6056              :                                         {
    6057            0 :                                                 if( vecShiftedPlaneDescript.size() != 2 )
    6058              :                                                         UG_LOG("1+2 nicht 3" << std::endl);
    6059              : 
    6060              :                                                 // add an artificial perpendicular plane with move vector zero
    6061              : 
    6062              :                                                 vector3 artificialNormal;
    6063            0 :                                                 VecCross( artificialNormal, vecShiftedPlaneDescript[0].spuckNormalVector(), vecShiftedPlaneDescript[1].spuckNormalVector() );
    6064              : 
    6065            0 :                                                 PlaneDescriptor artificialPlane( artificialNormal, posOldVrt );
    6066              : 
    6067            0 :                                                 vecShiftedPlaneDescript.push_back(artificialPlane);
    6068              : 
    6069              :                                         }
    6070              : 
    6071              : 
    6072              : 
    6073              :                                 }
    6074              : 
    6075              :                         }
    6076              :                         else
    6077              :                         {
    6078              :                                 // need to average boundaries
    6079              : 
    6080              :                                 // AVERAGE in this case and introduce an averaged pseudo boundary descriptor
    6081              :                                 // AAAAAAAAAAAAAAAA
    6082              : 
    6083              :                                 vector3 averagedNormal;
    6084              : 
    6085              : //                              if( ! averageBndryNormals( VecPlaneDescriptor const & vecPlaneBndryDescr, vector3 & averagedNormal ) )
    6086            0 :                                 if( ! averageBndryNormals( vecPlaneBndryDescr, averagedNormal ) )
    6087              :                                 {
    6088              :                                         UG_LOG("NORMAL NOT AVERAGABLE" << std::endl);
    6089            0 :                                         UG_THROW("NORMAL NOT AVERAGABLE" << std::endl);
    6090              :                                         return false;
    6091              :                                 }
    6092              : 
    6093            0 :                                 PlaneDescriptor averagedBoundaryPlane( averagedNormal, posOldVrt );
    6094            0 :                                 vecShiftedPlaneDescript.push_back(averagedBoundaryPlane);
    6095              : 
    6096            0 :                                 if( vecPlaneFracDescr.size() == 1 )
    6097              :                                 {
    6098              :                                         // behave as if we would have one boundary and thus need one additional artificial normal
    6099              : 
    6100              :                                         vector3 artificialNormal;
    6101            0 :                                         VecCross( artificialNormal, vecShiftedPlaneDescript[0].spuckNormalVector(), averagedNormal );
    6102              : 
    6103            0 :                                         PlaneDescriptor artificialPlane( artificialNormal, posOldVrt );
    6104              : 
    6105            0 :                                         vecShiftedPlaneDescript.push_back(artificialPlane);
    6106              :                                 }
    6107              : 
    6108              :                         }
    6109              : 
    6110              : 
    6111            0 :                 }
    6112              : 
    6113              :                 // vector shifted plane descriptor kriegt was dazu, wenn es keine drei sind ohne boundary
    6114              : 
    6115            0 :                 if( vecShiftedPlaneDescript.size() != 3 )
    6116            0 :                         UG_THROW("wie gross soll es denn sein" << std::endl);
    6117              : 
    6118            0 :                 computeCrossingPointOf3Planes( vecShiftedPlaneDescript, posNewVrt );
    6119              : 
    6120              :         }
    6121              : 
    6122              : 
    6123              : 
    6124              : //      if( vecSegmLimSidPrSudoNrml.size() != 1 )
    6125              : //      {
    6126              : //              UG_LOG("only one fracture, but not one normal and sudo?"  <<  std::endl);
    6127              : //              UG_THROW("only one fracture, but not one normal and sudo?" << std::endl);
    6128              : //              return false;
    6129              : //      }
    6130              : 
    6131              :         // FALL eins extra Funktion, unterscheiden nach Länge
    6132              : 
    6133              : //      if(  )
    6134              : 
    6135              : 
    6136              : //      SegmentLimitSidesPairSudoNorml & sudoAndNormal = vecSegmLimSidPrSudoNrml[0];
    6137              : //
    6138              : //      IndexType sudoBase = sudoAndNormal.first;
    6139              : //      vector3 normalsAveraged = sudoAndNormal.second;
    6140              : //
    6141              : //      Vertex * oldVrt = segmLimSides.spuckVertex();
    6142              : //
    6143              : //      number width = m_fracInfosBySubset[sudoBase].width;
    6144              : //
    6145              : //      number scal = width / 2.;
    6146              : //
    6147              : //      NormalVectorFacIntoVol scaledNormal;
    6148              : //
    6149              : //      VecScale( scaledNormal, normalsAveraged, - scal );
    6150              : //
    6151              : //      vector3 posOldVrt = m_aaPos[oldVrt];
    6152              : //
    6153              : //      UG_LOG("NORMAL OLD VRTX " << posOldVrt << " -> " << normalsAveraged << std::endl );
    6154              : 
    6155              : 
    6156              : //      VecAdd( posNewVrt, posOldVrt, scaledNormal );
    6157              : 
    6158            0 :         Vertex * newShiftVrtx = *m_grid.create<RegularVertex>();
    6159              : 
    6160            0 :         if( newShiftVrtx == nullptr )
    6161              :         {
    6162              :                 UG_LOG("Nullen erzeugt" << std::endl);
    6163            0 :                 UG_THROW("Nullen erzeugt" << std::endl);
    6164              :                 return false;
    6165              :         }
    6166              : 
    6167              :         m_aaPos[newShiftVrtx] = posNewVrt;
    6168              : 
    6169            0 :         UG_LOG("Created new vertex at " << m_aaPos[newShiftVrtx] << std::endl );
    6170              : 
    6171            0 :         m_sh.assign_subset(newShiftVrtx, sudoExample);
    6172              : //      m_sh.assign_subset(newShiftVrtx, m_sh.num_subsets());
    6173              : 
    6174              :         // wenn der neue Vertex mit einer ungeschlossenen endenden Kluft zu tun hat
    6175              :         // muss am Ende vom Kernvertex, old vertex, die edge, die nicht mit der
    6176              :         // kreuzenden nicht endenden KLuft geht, gelöscht werden
    6177              :         m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft[newShiftVrtx] = hasUnclosedFaces;
    6178              : 
    6179              :         // TODO FIXME das auch verwenden
    6180              : 
    6181            0 :         if( hasUnclosedFaces )
    6182              :         {
    6183              :                 // TEST AUF ANZAHL der kreuzenden Klüfte, zusätzlich, ob es eine ist nur
    6184              :                 // zur Sicherheit
    6185            0 :                 if( isBndry || vecShiftedPlaneDescript.size() != 1 )
    6186              :                 {
    6187              :                         UG_LOG("Shift vertex but boundary or more than one shift direction " << std::endl);
    6188            0 :                         UG_THROW("Shift vertex but boundary or more than one shift direction " << std::endl);
    6189              :                 }
    6190              : 
    6191            0 :                 if( ! addElem( m_vrtxArisesFromExpandedEndingCrossingCleft, newShiftVrtx ) )
    6192              :                 {
    6193              :                         UG_LOG("Shifted ecf vertex schon bekannt " << std::endl);
    6194            0 :                         UG_THROW("Shifted ecf vertex schon bekannt " << std::endl);
    6195              :                 }
    6196              : 
    6197              :                 // TODO FIXME figure out segment limiting side of the member vector and add the shift vertex
    6198              : 
    6199              :                 Edge * shiftDirection = nullptr;
    6200              : 
    6201            0 :                 if( ! segmLimSides.spuckLowdimElmShiftDirectionIfUnclosedFractPresent( shiftDirection ) )
    6202              :                 {
    6203              :                         UG_LOG("No shift direction in ending crossing cleft segment " << std::endl);
    6204            0 :                         UG_THROW("No shift direction in ending crossing cleft segment " << std::endl);
    6205              :                 }
    6206              : 
    6207              :                 IndexType numFoundECFSI = 0;
    6208              : 
    6209              :                 // figure out the Ending crossing cleft segment info corresponding to this shift edge
    6210            0 :                 for( EndingCrossingFractureSegmentInfo const & ecfs : m_vecEndCrossFractSegmInfo )
    6211              :                 {
    6212            0 :                         if( ecfs.spuckLowdimElmShiftDirection() == shiftDirection )
    6213            0 :                                 numFoundECFSI++;
    6214              :                 }
    6215              : 
    6216            0 :                 if( numFoundECFSI != 1 )
    6217              :                 {
    6218              :                         UG_LOG("not one cefsi found " << numFoundECFSI << std::endl);
    6219            0 :                         UG_THROW("not one cefsi found " << numFoundECFSI << std::endl);
    6220              :                 }
    6221              : 
    6222            0 :                 for( EndingCrossingFractureSegmentInfo & ecfs : m_vecEndCrossFractSegmInfo )
    6223              :                 {
    6224            0 :                         if( ecfs.spuckLowdimElmShiftDirection() == shiftDirection )
    6225              :                         {
    6226            0 :                                 if( ! ecfs.schluckShiftVrtx( newShiftVrtx ) )
    6227              :                                 {
    6228            0 :                                         UG_LOG("Shift vertex wird nicht geschluckt" << m_aaPos[newShiftVrtx] << std::endl );
    6229            0 :                                         UG_THROW("Shift vertex wird nicht geschluckt" << m_aaPos[newShiftVrtx] << std::endl );
    6230              :                                         return false;
    6231              :                                 }
    6232              : 
    6233              :                                 break;
    6234              :                         }
    6235              :                 }
    6236              : 
    6237              :                 IndexType numFoundAssigned = 0;
    6238              : 
    6239            0 :                 for( EndingCrossingFractureSegmentInfo const & ecfs : m_vecEndCrossFractSegmInfo )
    6240              :                 {
    6241            0 :                         if( ecfs.spuckShiftVrtx() != nullptr && ecfs.spuckLowdimElmShiftDirection() == shiftDirection )
    6242            0 :                                 numFoundAssigned++;
    6243              :                 }
    6244              : 
    6245            0 :                 if( numFoundAssigned != 1 )
    6246              :                 {
    6247            0 :                         m_sh.assign_subset( oldVrt, m_sh.num_subsets());
    6248            0 :                         m_sh.assign_subset( shiftDirection, m_sh.num_subsets());
    6249              : 
    6250              : 
    6251              :                         UG_LOG( "num found assigend wrong " << numFoundAssigned );
    6252            0 :                         UG_THROW( "num found assigend wrong " << numFoundAssigned );
    6253              :                 }
    6254              : 
    6255              :                 UG_LOG("ending crossing cleft shift vertex generated " << std::endl);
    6256              : 
    6257              :         }
    6258              : 
    6259              :         std::vector<Volume*> volsInSegm;
    6260              : 
    6261              :         segmLimSides.spuckVecFulldimElem( volsInSegm );
    6262              : 
    6263            0 :         for( Volume * const & vol : volsInSegm )
    6264              :         {
    6265            0 :                 std::vector<Vertex*> & newVrts4Fac = m_aaVrtVecVol[ vol ];
    6266              : 
    6267            0 :                 for(size_t indVrt = 0; indVrt < (vol)->num_vertices();  indVrt++ )
    6268              :                 {
    6269            0 :                         Vertex* volVrt = (vol)->vertex(indVrt);
    6270              : 
    6271            0 :                         if(  volVrt == oldVrt )
    6272              :                         {
    6273            0 :                                 newVrts4Fac[ indVrt ] = newShiftVrtx;
    6274              :                         }
    6275              :                 }
    6276              :         }
    6277              : 
    6278              : //      if( isCrossingPt )
    6279              : //      {
    6280              : //              VrtxPair oldNewV( oldVrt, newShiftVrtx );
    6281              : //              m_oldNewVrtcs4Diams.push_back(oldNewV);
    6282              : //      }
    6283              : 
    6284              : 
    6285              : 
    6286              :         return true;
    6287              : 
    6288              : 
    6289            0 : }
    6290              : 
    6291              : //////////////////////////////////////////////////////////////////////////
    6292              : 
    6293              : 
    6294            0 : bool ArteExpandFracs3D::averageBndryNormals( VecPlaneDescriptor const & vecPlaneBndryDescr, vector3 & averagedNormal  )
    6295              : {
    6296            0 :         if( vecPlaneBndryDescr.size() == 0 )
    6297              :         {
    6298              :                 UG_LOG("no boundary" << std::endl);
    6299            0 :                 return false;
    6300              :         }
    6301              : 
    6302              :         vector3 normalsSum;
    6303              : 
    6304            0 :         for( PlaneDescriptor const & pd : vecPlaneBndryDescr )
    6305              :         {
    6306              :                 vector3 const & norml = pd.spuckNormalVector();
    6307              : 
    6308              :                 vector3 normalsSumBefore = normalsSum;
    6309              : 
    6310              :                 VecAdd(normalsSum, norml, normalsSumBefore );
    6311              :         }
    6312              : 
    6313            0 :         VecScale( averagedNormal, normalsSum, static_cast<number>(vecPlaneBndryDescr.size()) );
    6314              : 
    6315              :         return true;
    6316              : 
    6317              : }
    6318              : 
    6319              : 
    6320              : ///////////////////////////////////////////////////////////////////////////
    6321              : 
    6322            0 : bool ArteExpandFracs3D::testIfNewPointsSqueezeVolumes( ArteExpandFracs3D::SegmentLimitingSides & segmLimSides,
    6323              :                 ArteExpandFracs3D::VecPlaneDescriptor const & vecShiftedPlaneDescript )
    6324              : {
    6325              :         // TODO FIXME test if the new points might squeeze the volumes
    6326              : 
    6327              :         UG_LOG("TEST POINTS BEGIN " << std::endl);
    6328              : 
    6329              :         bool notViolated = true;
    6330              : 
    6331            0 :         IndexType debugSubs = m_sh.num_subsets();
    6332              : 
    6333            0 :         Vertex * oldVrt = segmLimSides.spuckVertex();
    6334              :         vector3 posOldVrt = m_aaPos[oldVrt];
    6335              : 
    6336              :         vector3 posTestVertex;
    6337              : 
    6338              :         std::vector<Edge*> vecEdgesOfSegVols;
    6339              : 
    6340            0 :         if( ! segmLimSides.spuckListLowdimElmsOfVols( vecEdgesOfSegVols, m_grid ) )
    6341              :         {
    6342              :                 UG_LOG("which attached edges? " << std::endl);
    6343              :                 UG_LOG("which attached edges? " << std::endl);
    6344              :         }
    6345              : 
    6346            0 :         if( vecEdgesOfSegVols.size() == 0 )
    6347              :         {
    6348              :                 UG_LOG("NO EDGES" << std::endl);
    6349              :         }
    6350              : 
    6351              :         std::vector<Volume*> attVols;
    6352              : 
    6353              :         segmLimSides.spuckVecFulldimElem(attVols);
    6354              : 
    6355            0 :         if( attVols.size() == 0 )
    6356              :         {
    6357              :                 UG_LOG("NO VOLS " << std::endl);
    6358              :         }
    6359              : 
    6360              :         UG_LOG("TEST POINTS MIDDLE " << notViolated << std::endl);
    6361              : 
    6362              : 
    6363            0 :         for( PlaneDescriptor const & shiftedPlane : vecShiftedPlaneDescript )
    6364              :         {
    6365              :                 std::vector<Edge *> manifoldEdges;
    6366              : 
    6367            0 :                 if( ! shiftedPlane.spuckLowDimElms(manifoldEdges) )
    6368              :                 {
    6369              :                         UG_LOG("NO MANIFOLD EDGED OF PLANE " << std::endl);
    6370            0 :                         UG_THROW("NO MANIFOLD EDGED OF PLANE " << std::endl);
    6371              :                 }
    6372              : 
    6373              :                 // TODO FIXME nur die Edges, die NICHT zur Basis-Ebene gehören, die, die zur Mannigfaltigkeit
    6374              :                 // gehören, die expandiert wird, müssen raus gefiltert werden!!!!!
    6375            0 :                 for( Edge * testEdge : vecEdgesOfSegVols )
    6376              :                 {
    6377              : //                      if( ! testEdge )
    6378              : //                              continue;
    6379              : 
    6380              :                         // test if testEdge belongs to the allowed Edges
    6381              : 
    6382              :                         bool isManifEdg = false;
    6383              : 
    6384            0 :                         for( Edge * me : manifoldEdges )
    6385              :                         {
    6386            0 :                                 if( me == testEdge )
    6387              :                                 {
    6388              :                                         isManifEdg = true;
    6389              :                                         UG_LOG("Test edge is manifold edge" << std::endl);
    6390            0 :                                         continue;
    6391              :                                 }
    6392              : 
    6393              :                                 // if edge belongs to manifold, it must not be considered!!!
    6394              :                         }
    6395              : 
    6396            0 :                         if( isManifEdg )
    6397            0 :                                 continue;
    6398              : 
    6399              :                         UG_LOG("TESTING CROSS POINT " << notViolated << std::endl);
    6400              : 
    6401              :                         // abuse of the compute cross point function originally developped for ending crossing cleft purposes
    6402            0 :                         if( ! computeCrossPointOfPlaneWithLine( shiftedPlane, testEdge, oldVrt, posTestVertex ) )
    6403              :                         {
    6404              :                                 UG_LOG("CAUTION: shifting cross point along test procedure cleft edge might break volumes " << std::endl);
    6405              : 
    6406              :                                 notViolated = false;
    6407              : 
    6408              :                                 UG_LOG("DEBUGGING WITH SUDO " << debugSubs << std::endl );
    6409              : 
    6410              : //                              return false;
    6411              : 
    6412            0 :                                 for( IndexType i = 0; i < 2; i++ )
    6413              :                                 {
    6414            0 :                                         Vertex * testVertex = testEdge->vertex(i);
    6415              : 
    6416            0 :                                         if( testVertex != oldVrt )
    6417              :                                         {
    6418            0 :                                                 addElem( m_vrtcsViolatingExpansion, testVertex );
    6419              :                                                 break;
    6420              :                                         }
    6421              :                                 }
    6422              : 
    6423            0 :                                 for( Volume * vol : attVols )
    6424              :                                 {
    6425            0 :                                         if( VolumeContains( vol, testEdge ))
    6426              :                                         {
    6427            0 :                                                 addElem(m_volsViolatingExpansion, vol);
    6428            0 :                                                 m_sh.assign_subset( vol, debugSubs );
    6429            0 :                                                 UG_LOG("CAUTION quenched volume, assigning debug subset " << debugSubs
    6430              :                                                                 << " for vol with center " << CalculateCenter( vol, m_aaPos )
    6431              :                                                                 << " for fracture subdomain " << shiftedPlane.spuckSudo() << std::endl);
    6432              :                                         }
    6433              :                                 }
    6434              : 
    6435              :                         }
    6436              : 
    6437              :                 }
    6438              : 
    6439            0 :         }
    6440              : 
    6441              :         UG_LOG("TEST POINTS END " << notViolated << " of " << true << " " << false << std::endl);
    6442              : 
    6443              : 
    6444            0 :         return true;
    6445              : 
    6446            0 : }
    6447              : 
    6448              : //////////////////////////////////////////////////////////////////////////
    6449              : 
    6450              : 
    6451            0 : bool ArteExpandFracs3D::computeCrossPointOfPlaneWithLine( PlaneDescriptor const & shiftedPlane, Edge * const & shiftDirectionEdg, Vertex * const & oldVrt, vector3 & posCrossingPt )
    6452              : {
    6453              :         UG_LOG("computing cross point start " << std::endl);
    6454              : 
    6455              :         vector3 const & normalShiftedPlane = shiftedPlane.spuckNormalVector();
    6456              :         vector3 const & baseShiftedPlane = shiftedPlane.spuckBaseVector();
    6457              :         number const & rhs = shiftedPlane.spuckRHS();
    6458              : 
    6459              :         // vector3 posOldVrt Aufpunkt der Edge, entland der verschoben werden soll
    6460              :         // establish
    6461              : 
    6462            0 :         if( ! ( EdgeContains(shiftDirectionEdg, oldVrt ) ) )
    6463              :         {
    6464              :                 UG_LOG("Shift edge ohne alten Vertex?" << std::endl);
    6465            0 :                 UG_THROW("Shift edge ohne alten Vertex?" << std::endl);
    6466              :         }
    6467              : 
    6468            0 :         vector3 posOldVrt = m_aaPos[oldVrt];
    6469              : 
    6470            0 :         UG_LOG("Pos old vertex CCP " << posOldVrt << std::endl);
    6471              : 
    6472              :         vector3 const & shiftVecBase = posOldVrt;
    6473              : 
    6474            0 :         Vertex * const & shiftEdgeVrtOne = shiftDirectionEdg->vertex(0);
    6475            0 :         Vertex * const & shiftEdgeVrtTwo = shiftDirectionEdg->vertex(1);
    6476              : 
    6477              :         vector3 shiftVecEnd = shiftVecBase; // needs to be changed still
    6478              : 
    6479            0 :         if( shiftEdgeVrtOne == oldVrt )
    6480              :         {
    6481              :                 shiftVecEnd = m_aaPos[shiftEdgeVrtTwo];
    6482              :         }
    6483            0 :         else if( shiftEdgeVrtTwo == oldVrt )
    6484              :         {
    6485              :                 shiftVecEnd = m_aaPos[shiftEdgeVrtOne];
    6486              :         }
    6487              :         else
    6488              :         {
    6489              :                 UG_LOG("no end vertex" << std::endl);
    6490            0 :                 UG_THROW("no end vertex" << std::endl);
    6491              :         }
    6492              : 
    6493              :         vector3 directionVec;
    6494              : 
    6495              :         VecSubtract(directionVec, shiftVecEnd, posOldVrt );
    6496              : 
    6497            0 :         UG_LOG("SHIVEEND " << shiftVecEnd << std::endl);
    6498            0 :         UG_LOG("POS OLD " << posOldVrt << std::endl);
    6499              : 
    6500              : 
    6501              :         // x = aufpunkt + s . r
    6502              :         // richtung einsetzen in ( x - x_0 ) * n = 0, auflösen nach s
    6503              :         // . gilt als Skalarprodukt, * als Kreuzprodukt hier in Notation
    6504              :         // x*n = rhs = x_0*n
    6505              :         // ( a + s . r -x0 ) * n = 0
    6506              :         // a * n + s . n * r - x0*n = 0
    6507              :         // s . ( n * r ) = x0 * n - a * n
    6508              :         // "Normallfall": n*r != 0
    6509              :         // dann gilt
    6510              :         // s = ( x0*n - a*n ) / ( n*r )
    6511              :         // Spezialfall: n*r = 0 dann, wenn Richtungsvektor Gerade und Normalenvektor Ebene übereinstimmen
    6512              :         // also wenn Verschiebung entlang der Normalen
    6513              :         // dann ist (x0-a) parallel zu n bzw r, dann ist die Frage, was für ein Vielfaches von r ist (x0-a)
    6514              :         // also a + s . r - x0 = 0 auflösen nach s
    6515              :         // s . r = x0 - a , muss auch für den Betrag gelten
    6516              :         // also s | r | = | x_0 - a |
    6517              :         // also s = | x_0 - a | / | r |
    6518              : 
    6519              :         number planeBaseMultNormal = VecDot(baseShiftedPlane,normalShiftedPlane);
    6520              :         number lineBaseMultNormal = VecDot(posOldVrt,normalShiftedPlane);
    6521              :         number lineDirMultNormal = VecDot( directionVec, normalShiftedPlane );
    6522              : 
    6523            0 :         UG_LOG("base shift plane " << baseShiftedPlane << std::endl);
    6524            0 :         UG_LOG("normal shift plane " << normalShiftedPlane << std::endl);
    6525            0 :         UG_LOG("pos Old " << posOldVrt << std::endl);
    6526            0 :         UG_LOG("direction " << directionVec << std::endl);
    6527              : 
    6528              : 
    6529            0 :         UG_LOG("COMPARE RHS AND LBMN " << rhs << " - " << planeBaseMultNormal << std::endl);
    6530              : 
    6531            0 :         number fbs = std::fabs( ( rhs - planeBaseMultNormal ) / ( rhs + planeBaseMultNormal) );
    6532              : 
    6533              :         UG_LOG("RELATIVE DIFF " << fbs << std::endl);
    6534              : 
    6535              :         number const d_toler = 1e-4;
    6536              : 
    6537            0 :         if( fbs > d_toler )
    6538              :         {
    6539              :                 UG_LOG("RELATIVE DIFF TOO BIG " << std::endl);
    6540            0 :                 UG_THROW("RELATIVE DIFF TOO BIG " << std::endl);
    6541              :         }
    6542              : 
    6543              :         number moveAlongLine = 0;
    6544              : 
    6545            0 :         if( lineDirMultNormal == 0. )
    6546              :         {
    6547              :                 UG_LOG("SHIFT denominator zero division " << std::endl);
    6548              : //              UG_THROW("denominator zero division " << std::endl);
    6549              : 
    6550              :                 vector3 connectNewAndOldBase;
    6551              :                 VecSubtract(connectNewAndOldBase, baseShiftedPlane, posOldVrt );
    6552              : 
    6553              :                 // Test also if the connection vector parallel to normalShiftedPlane and directionVec
    6554              : 
    6555              :                 number testParallShiftPlan = std::fabs( VecDot( connectNewAndOldBase, normalShiftedPlane ) );
    6556            0 :                 number testParallDirVec = std::fabs( VecDot( connectNewAndOldBase, directionVec ) );
    6557              : 
    6558            0 :                 if( testParallDirVec > d_toler || testParallDirVec > d_toler )
    6559              :                 {
    6560              :                         UG_LOG("VECTORS PARALLEL AND NOT " << std::endl);
    6561            0 :                         UG_THROW("VECTORS PARALLEL AND NOT " << std::endl);
    6562              :                 }
    6563              : 
    6564              :                 number lengthDirVec = VecLength(directionVec);
    6565              :                 number lengthConnVec = VecLength(connectNewAndOldBase);
    6566              : 
    6567            0 :                 moveAlongLine = lengthConnVec / lengthDirVec;
    6568              : 
    6569              :                 UG_LOG("MONULL " << lengthConnVec << " " << lengthDirVec << std::endl );
    6570              :         }
    6571              :         else
    6572              :         {
    6573            0 :                 moveAlongLine = ( planeBaseMultNormal - lineBaseMultNormal ) / lineDirMultNormal;
    6574              : 
    6575              :                 UG_LOG("MOAL  " << planeBaseMultNormal << " " <<  lineBaseMultNormal << " " <<  lineDirMultNormal << std::endl );
    6576              :         }
    6577              : 
    6578            0 :         if( moveAlongLine == 0. )
    6579              :         {
    6580              :                 UG_LOG("No Moving?" << std::endl);
    6581            0 :                 UG_THROW("No Moving?" << std::endl);
    6582              :         }
    6583              : 
    6584              :         vector3 shiftAlongLine;
    6585              : 
    6586              :         VecScale( shiftAlongLine, directionVec, moveAlongLine );
    6587              : 
    6588            0 :         UG_LOG("SHIFT " << shiftAlongLine << " Dir " << directionVec << " MOV " << moveAlongLine << std::endl );
    6589              : 
    6590              :         VecAdd( posCrossingPt, posOldVrt, shiftAlongLine );
    6591              : 
    6592              : //      m_allowedSqueeze = 0.8;
    6593              : 
    6594              : //      UG_LOG("MOVING " << moveAlongLine << std::endl);
    6595              : 
    6596              :         // falsch bei ending crossing cleft Verschiebung u.U. , zweiten Parameter dazu zur Unterscheidung?
    6597              :         // Vertex erzeugen wenn Problem an der Stelle? um zu sehen, wo es hin will?
    6598            0 :         if( moveAlongLine > m_allowedSqueeze )
    6599              :         {
    6600            0 :                 UG_LOG("MOVING ALONG LINE TOO BIG C " << posCrossingPt << " Old " << posOldVrt << " move " << shiftAlongLine << std::endl);
    6601              : 
    6602              :                 // create debug vertex at position of crossing point
    6603              : 
    6604            0 :                 Vertex * dbgVrtx = *m_grid.create<RegularVertex>();
    6605              : 
    6606              :                 m_aaPos[dbgVrtx] = posCrossingPt;
    6607              : 
    6608            0 :                 IndexType strangeSubs = m_sh.num_subsets();
    6609              : 
    6610            0 :                 m_sh.assign_subset(dbgVrtx, strangeSubs);
    6611              : 
    6612            0 :                 m_sh.assign_subset( shiftDirectionEdg, strangeSubs );
    6613              : //              m_sh.assign_subset( shiftDirectionEdg, m_sh.num_subsets() );
    6614              : 
    6615            0 :                 m_sh.assign_subset( shiftDirectionEdg->vertex(0), strangeSubs );
    6616            0 :                 m_sh.assign_subset( shiftDirectionEdg->vertex(1), strangeSubs );
    6617            0 :                 m_sh.assign_subset( oldVrt, strangeSubs );
    6618              : 
    6619              : 
    6620              :                 UG_LOG("computing cross point end false " << std::endl);
    6621              : 
    6622            0 :                 return false;
    6623              :         }
    6624              : 
    6625              :         UG_LOG("computing cross point end true " << std::endl);
    6626              : 
    6627              : 
    6628              :         return true;
    6629              : 
    6630              : }
    6631              : //////////////////////////////////////////////////////////////////////////
    6632              : 
    6633              : 
    6634              : #if 0
    6635              : template<>
    6636              : bool ArteExpandFracs3D::expandWithinTheSegment<1,false>( Vertex * const & oldVrt, SegmentVolElmInfo const & segmVolElmInfo )
    6637              : {
    6638              : 
    6639              :         // get all fracture faces, check if they belong to the same subdomain, must be the case here!
    6640              : 
    6641              :         VecAttachedFractFaceEdgeSudo vecAttFractFaces;
    6642              : 
    6643              :         for( AttachedVolumeElemInfo const & avei : segmVolElmInfo )
    6644              :         {
    6645              :                 VecAttachedFractFaceEdgeSudo const & vecAttFractVol = avei.getVecFractManifElem();
    6646              : 
    6647              :                 for( AttachedFractFaceEdgeSudo const & affe : vecAttFractVol )
    6648              :                 {
    6649              :                         vecAttFractFaces.push_back(affe);
    6650              :                 }
    6651              :         }
    6652              : 
    6653              :         IndexType numbContrFracFaces = vecAttFractFaces.size();
    6654              : 
    6655              :         if( numbContrFracFaces < 1 )
    6656              :         {
    6657              :                 UG_LOG("Kein Affe da " << std::endl);
    6658              :                 UG_THROW("Kein Affe da " << std::endl);
    6659              :                 return false;
    6660              :         }
    6661              : 
    6662              :         IndexType sudoBase = vecAttFractFaces[0].getSudo();
    6663              : 
    6664              :         // check if all sudos equal
    6665              :         for( AttachedFractFaceEdgeSudo const & affe : vecAttFractFaces )
    6666              :         {
    6667              :                 IndexType sudoTest = affe.getSudo();
    6668              : 
    6669              :                 if( sudoTest != sudoBase )
    6670              :                 {
    6671              :                         UG_LOG("unterschiedliche Sudos an einer einzelnen Fracture?" << std::endl);
    6672              :                         UG_THROW("unterschiedliche Sudos an einer einzelnen Fracture?" << std::endl);
    6673              :                         return false;
    6674              :                 }
    6675              :         }
    6676              : 
    6677              :         // now we are sure we have the same sudo, now we average the normals
    6678              : 
    6679              :         NormalVectorFacIntoVol normalsFacInVolSummed(0,0,0);
    6680              : 
    6681              :         for( AttachedFractFaceEdgeSudo const & affe : vecAttFractFaces )
    6682              :         {
    6683              :                 NormalVectorFacIntoVol tmpVec = normalsFacInVolSummed;
    6684              :                 UG_LOG("Normal Vec " << tmpVec << std::endl);
    6685              :                 VecAdd(normalsFacInVolSummed, tmpVec, affe.getNormalVec() );
    6686              :         }
    6687              : 
    6688              :         NormalVectorFacIntoVol normalsAveraged;
    6689              : 
    6690              :         VecScale( normalsAveraged, normalsFacInVolSummed, 1. / ( static_cast<number>(numbContrFracFaces) ) );
    6691              : 
    6692              :         number width = m_fracInfosBySubset[sudoBase].width;
    6693              : 
    6694              :         number scal = width / 2.;
    6695              : 
    6696              :         NormalVectorFacIntoVol scaledNormal;
    6697              : 
    6698              :         VecScale( scaledNormal, normalsAveraged, - scal );
    6699              : 
    6700              :         vector3 posOldVrt = m_aaPos[oldVrt];
    6701              : 
    6702              :         vector3 posNewVrt;
    6703              : 
    6704              :         VecAdd( posNewVrt, posOldVrt, scaledNormal );
    6705              : 
    6706              :         Vertex * newShiftVrtx = *m_grid.create<RegularVertex>();
    6707              : 
    6708              :         if( newShiftVrtx == nullptr )
    6709              :         {
    6710              :                 UG_LOG("Nullen erzeugt" << std::endl);
    6711              :                 UG_THROW("Nullen erzeugt" << std::endl);
    6712              :                 return false;
    6713              :         }
    6714              : 
    6715              :         m_aaPos[newShiftVrtx] = posNewVrt;
    6716              : 
    6717              :         UG_LOG("Created new vertex at " << m_aaPos[newShiftVrtx] << std::endl );
    6718              : 
    6719              :         m_sh.assign_subset(newShiftVrtx, sudoBase);
    6720              : 
    6721              :         for( AttachedVolumeElemInfo const & avei : segmVolElmInfo )
    6722              :         {
    6723              :                 Volume * vol = avei.getFulldimElem();
    6724              : 
    6725              :                 std::vector<Vertex*> & newVrts4Fac = m_aaVrtVecVol[ vol ];
    6726              : 
    6727              :                 for(size_t indVrt = 0; indVrt < (vol)->num_vertices();  indVrt++ )
    6728              :                 {
    6729              :                         Vertex* volVrt = (vol)->vertex(indVrt);
    6730              : 
    6731              :                         if(  volVrt == oldVrt )
    6732              :                         {
    6733              :                                 newVrts4Fac[ indVrt ] = newShiftVrtx;
    6734              :                         }
    6735              :                 }
    6736              :         }
    6737              : 
    6738              :         return true;
    6739              : }
    6740              : #endif
    6741              : 
    6742              : 
    6743              : ////////////////////////////////////////////////////////////////////
    6744              : 
    6745              : //template<ArteExpandFracs3D::SegmentVrtxFracStatus::oneFracSuDoAtt>
    6746              : //bool ArteExpandFracs3D::computeShiftVector( ArteExpandFracs3D::VecSegmentLimitSidesPairSudoNorml const & vecSegmLimSidPrSudoNrml )
    6747              : //{
    6748              : //      return {};
    6749              : //}
    6750              : 
    6751              : 
    6752              : ////////////////////////////////////////////////////////////////////
    6753              : 
    6754              : // TODO FIXME muss verschwinden!
    6755              : //template<>
    6756              : //bool ArteExpandFracs3D::computeShiftVector( VecSegmentLimitSidesPairSudoNorml const & vecSegmLimSidPrSudoNrml )
    6757              : ////bool ArteExpandFracs3D::expandWithinTheSegment<ArteExpandFracs3D::SegmentVrtxFracStatus::threeFracSuDoAtt>( SegmentLimitingSides const & segmLimSides )
    6758              : //{
    6759              : //      // wenn es nur zwei Segmentnormalen und sudos sind, dann wird die dritte auf Normale senkrecht zu
    6760              : //      // den beiden anderen gesetzt, und um Null verschoben, ihr
    6761              : //
    6762              : ////    if( segmLimSides.isBoundary() )
    6763              : ////    {
    6764              : ////            UG_LOG("three fracture at boundary need implementation " << std::endl);
    6765              : ////            UG_THROW("three fracture at boundary need implementation " << std::endl);
    6766              : ////            return false;
    6767              : ////    }
    6768              : //
    6769              : ////    VecSegmentLimitSidesPairSudoNorml vecSegmLimSidPrSudoNrml;
    6770              : //
    6771              : //      Vertex * oldVrt = segmLimSides.spuckVertex();
    6772              : //
    6773              : //      if( ! segmLimSides.spuckFractSudoNormls( vecSegmLimSidPrSudoNrml ) )
    6774              : //      {
    6775              : //              UG_LOG("Spucken schief gegangen three " << std::endl);
    6776              : //              UG_THROW("Spucken schief gegangen three " << std::endl);
    6777              : //              return false;
    6778              : //      }
    6779              : //
    6780              : //      if( vecSegmLimSidPrSudoNrml.size() != 3 )
    6781              : //      {
    6782              : //              UG_LOG("three fractures, but not three normals and sudo?"  <<  std::endl);
    6783              : //              UG_THROW("three fracture, but not three normal and sudo?" << std::endl);
    6784              : //              return false;
    6785              : //      }
    6786              : //
    6787              : //      // select one of the sudos of the sourrounding sudos of the segment, to which we want to assign the new vertex
    6788              : //      IndexType sudoExample = (vecSegmLimSidPrSudoNrml[0]).first;
    6789              : //
    6790              : ////    std::vector<IndexType> vecSudosSides;
    6791              : ////    std::vector<vector3> vecNormalsAveraged;
    6792              : ////    std::vector<vector3> vecShiftVec4Plane;
    6793              : //
    6794              : //      vector3 posOldVrt = m_aaPos[oldVrt];
    6795              : //
    6796              : //      VecPlaneDescriptor vecShiftedPlaneDescript;
    6797              : //
    6798              : ////    IndexType side = 0;
    6799              : //
    6800              : //      for( SegmentLimitSidesPairSudoNorml const & segLimSidPrSN : vecSegmLimSidPrSudoNrml )
    6801              : //      {
    6802              : //              IndexType const & sudoSide = segLimSidPrSN.first;
    6803              : //              vector3 const & normlAvrg = segLimSidPrSN.second;
    6804              : //
    6805              : //              // normal computed standard mässig directs of of the volume, we need that one into the volume
    6806              : //              vector3 normalOutsideVol;
    6807              : //
    6808              : //              // hier testen, ob die Subdomain von der Liste der fracture subdomains ist,
    6809              : //              // damit für den Fall von sich zwei schneidenden Ebenen für die dritte,
    6810              : //              // die als senkrecht zu den beiden anderen gesetzt werden soll, mit Verschiebung null,
    6811              : //              // analog Boundary sides, die künstliche Weite null erhalten kann hier
    6812              : //              number width = 0;
    6813              : //
    6814              : //              // ensure that the width is nonzero only for real fractures, not for pseudo vectors or such stuff
    6815              : //              if( ( side == 1 && ! artificialNormalTwo ) ||  ( side == 2 && ! artificialNormalThree ) )
    6816              : //                      width = m_fracInfosBySubset[sudoSide].width;
    6817              : //
    6818              : //              side++;
    6819              : //
    6820              : //              number shiftScal = width / 2.;
    6821              : //
    6822              : //              vector3 shiftVec4Plane;
    6823              : //
    6824              : //              // as normal outside vol, but we need to go inside the volumes / segment side
    6825              : //              VecScale( shiftVec4Plane, normalOutsideVol, - shiftScal );
    6826              : //
    6827              : ////            vecShiftVec4Plane.push_back( shiftVec4Plane );
    6828              : ////            vecSudosSides.push_back( sudoSide );
    6829              : ////            vecNormalsAveraged.push_back( normalIntoVol );
    6830              : //
    6831              : //              PlaneDescriptor planeDescr( normalOutsideVol, posOldVrt );
    6832              : //
    6833              : //              PlaneDescriptor shiftedPlaneDescr;
    6834              : //
    6835              : //              planeDescr.spuckPlaneShiftedAlong( shiftVec4Plane, shiftedPlaneDescr );
    6836              : //
    6837              : //              vecShiftedPlaneDescript.push_back( shiftedPlaneDescr );
    6838              : //      }
    6839              : //
    6840              : //      // KÄSE alles!!! wenn es eine boundary ist oder eine Kreuzung von zwei Ebenen innendrin,
    6841              : //      // dann muss hier DANACH noch was dazu kommen, das heisst, alles, was hier gemacht wird,
    6842              : //      // soll für den Fall sein, dass es keine einzelne Fracture innen drin ist,
    6843              : //      // und alle bool template Parameter sind MÜLL!!!!
    6844              : //      // das für zwei Fractures muss hier auch dazu
    6845              : //      // vielleicht am einfachsten, wenn man den template parameter auf true oder false stellt
    6846              : //      // für eine fracture innen oder allen anderen Rest......
    6847              : //
    6848              : //      // TODO FIXME compute crossing point of the three new planes!!!! need functions from lib_disc, cf FiniteStrainMechanics, solve LGS exact
    6849              : //
    6850              : //      vector3 shiftedCrossingPoint;
    6851              : //
    6852              : //      computeCrossingPointOf3Planes( vecShiftedPlaneDescript, shiftedCrossingPoint );
    6853              : //
    6854              : //      return true;
    6855              : //}
    6856              : 
    6857              : ////////////////////////////////////////////////////////////////////
    6858              : 
    6859            0 : bool ArteExpandFracs3D::computeCrossingPointOf3Planes(  VecPlaneDescriptor const & vecPlaneDescr, vector3 & crossingPoint )
    6860              : {
    6861              :         // n_i * vecX_i = a_i * n_i , i=1,2,3, ohne Summenkonvention, und n_i, vecX_i, a_i jeweils Vektoren Grösse 3
    6862              :         // es entsteht also ein LGS für drei Unbekannte und drei Gleichungen
    6863              : 
    6864              : //       vector<vector<double>> coefficients = {{2, 1}, {1, -3}};
    6865              : //       vector<double> constants = {5, -1};
    6866              : //       vector<double> solutions = cramer_rule(coefficients, constants);
    6867              : //       cout << "Solution for x: " << solutions[0] << endl;
    6868              : //       cout << "Solution for y: " << solutions[1] << endl;
    6869              : 
    6870              :         PlaneDescriptor const & planeDescrZero = vecPlaneDescr[0];
    6871              :         PlaneDescriptor const & planeDescrOne = vecPlaneDescr[1];
    6872              :         PlaneDescriptor const & planeDescrTwo = vecPlaneDescr[2];
    6873              : 
    6874              :         vector3 const & normalZero = planeDescrZero.spuckNormalVector();
    6875              :         vector3 const & normalOne = planeDescrOne.spuckNormalVector();
    6876              :         vector3 const & normalTwo = planeDescrTwo.spuckNormalVector();
    6877              : 
    6878              :         number const & rhsZero = planeDescrZero.spuckRHS();
    6879              :         number const & rhsOne = planeDescrOne.spuckRHS();
    6880              :         number const & rhsTwo = planeDescrTwo.spuckRHS();
    6881              : 
    6882              : 
    6883              : 
    6884              :         std::vector<std::vector<double>> coefficients = { {normalZero[0], normalZero[1], normalZero[2]},
    6885              :                                                                                                           {normalOne[0], normalOne[1], normalOne[2]},
    6886              :                                                                                                           {normalTwo[0], normalTwo[1], normalTwo[2]},
    6887            0 :                                                                                                         };
    6888              : 
    6889            0 :         std::vector<double> constants = { rhsZero, rhsOne, rhsTwo };
    6890              : 
    6891            0 :         std::vector<double> solutions = ug::simpleMatrOps::cramerRule(coefficients, constants);
    6892              : 
    6893            0 :         crossingPoint = vector3( solutions[0], solutions[1], solutions[2] );
    6894              : 
    6895            0 :         return true;
    6896            0 : }
    6897              : 
    6898              : ////////////////////////////////////////////////////////////////////
    6899              : 
    6900              : 
    6901              : 
    6902              : #if 0
    6903              : //template <>
    6904              : //bool ArteExpandFracs3D::establishNewVertices< Tetrahedron,
    6905              : //                                                                                        ArteExpandFracs3D::VrtxFracProptsStatus::oneFracSuDoAtt
    6906              : //                                                                                      >( Vertex * const & oldVrt )
    6907              : //template< bool APPLY_GENERAL_SEGMENT_ORDERING,
    6908              : //                ArteExpandFracs3D::VrtxFracProptsStatus vfp,
    6909              : //                typename std::enable_if< std::integral_constant<bool,APPLY_GENERAL_SEGMENT_ORDERING>>
    6910              : //              >
    6911              : template <>
    6912              : bool ArteExpandFracs3D::establishNewVertices< true,
    6913              :                                                                                           ArteExpandFracs3D::VrtxFracProptsStatus::oneFracSuDoAtt
    6914              :                                                                                         >( Vertex * const & oldVrt )
    6915              : {
    6916              :         UG_LOG("under construction Tetrahedra limited" << std::endl);
    6917              : 
    6918              :         VecVertFracTrip const & vecVertFracTrip = m_aaVrtInfoFraTri[oldVrt];
    6919              : 
    6920              :         VecAttachedVolumeElemInfo const & vecAttVolElemInfo = m_aaVolElmInfo[oldVrt];
    6921              : 
    6922              :         VecAttachedVolumeElemInfo vecAttVolElemInfoCop = vecAttVolElemInfo; // echte KOPIE
    6923              : 
    6924              :         VecAttachedVolumeElemInfo reconstructedVecAttVolElmInf;
    6925              : 
    6926              :         VecSegmentVolElmInfo vecSegVolElmInfo;
    6927              : 
    6928              :                 /*
    6929              :                  * While Schleifen aufbauen für den
    6930              :                  * Search the adjacent surface interatively - Algorithmus
    6931              :                  * (Stasi Algorithmus)
    6932              :                  *
    6933              :                  */
    6934              : 
    6935              :         IndexType d_segmenteErledigt = 0;
    6936              : 
    6937              :         while( vecAttVolElemInfoCop.size() != 0 )
    6938              :         {
    6939              :                 SegmentVolElmInfo segmentAVEI;
    6940              : 
    6941              :                 AttachedVolumeElemInfo & startVolInfoThisSegment = vecAttVolElemInfoCop[0];
    6942              : 
    6943              :                 startVolInfoThisSegment.markIt();
    6944              : 
    6945              :                 Volume * volSta = startVolInfoThisSegment.getFulldimElem();
    6946              : 
    6947              :                 vector3 center;
    6948              : 
    6949              :                 if( volSta != nullptr )
    6950              :                         center = CalculateCenter(volSta,m_aaPos);
    6951              : 
    6952              : //              UG_LOG("volume center " << center << std::endl );
    6953              : 
    6954              :                 int d_loopsDone = 0;
    6955              : 
    6956              :                 while( vecAttVolElemInfoCop.size() != 0 )
    6957              :                 {
    6958              :                         // count number of marked elements
    6959              :                         IndexType numMarkedElems = 0;
    6960              :                         IndexType markPoint = 0;
    6961              : 
    6962              : //                      IndexType lastMarkPt = 0;
    6963              :                         IndexType startIndexInner = 0;
    6964              : 
    6965              :                         for( AttachedVolumeElemInfo const & volElInfCop : vecAttVolElemInfoCop )
    6966              :                         {
    6967              :                                 if( volElInfCop.isMarked() )
    6968              :                                 {
    6969              :                                         Volume * vol = volElInfCop.getFulldimElem();
    6970              : //                                      m_sh.assign_subset(vol, m_sh.num_subsets());
    6971              : 
    6972              :                                         vector3 center = CalculateCenter(vol,m_aaPos);
    6973              : 
    6974              : //                                      UG_LOG("DAS ZENTRUM " << numMarkedElems << " -> " << center << std::endl);
    6975              : 
    6976              :                                         startIndexInner = markPoint;
    6977              :                                         numMarkedElems++;
    6978              : 
    6979              :                                 }
    6980              : 
    6981              :                                 markPoint++;
    6982              :                         }
    6983              : 
    6984              :                         UG_LOG("LOOPS DONE " << numMarkedElems << std::endl);
    6985              : 
    6986              :                         if( numMarkedElems == 0 )
    6987              :                                 break;
    6988              : 
    6989              : //                      int startIndexInner = -1;
    6990              : //
    6991              : //                      for( int i = 0; i < vecAttVolElemInfoCop.size(); i++ )
    6992              : //                      {
    6993              : //                              AttachedVolumeElemInfo vi = vecAttVolElemInfoCop[i];
    6994              : //
    6995              : //                              Volume * vo = vi.getFulldimElem();
    6996              : //
    6997              : //                              vector3 center = CalculateCenter(vo,m_aaPos);
    6998              : //
    6999              : //                              UG_LOG("DAS ZENTRUM ZAHL VOR " << i << " -> " <<  center << std::endl);
    7000              : //
    7001              : //                              if( vi.isMarked() )
    7002              : //                                      startIndexInner = i;
    7003              : //                      }
    7004              : //
    7005              : //                      if( startIndexInner < 0 )
    7006              : //                      {
    7007              : //                              UG_THROW("kein Anfang gefunden " << std::endl);
    7008              : //                      }
    7009              : //
    7010              : //#if 0
    7011              : //                      IndexType startIndexInner = markPoint - 1;
    7012              : //#endif
    7013              :                         AttachedVolumeElemInfo startVolInfoMarkLoop = vecAttVolElemInfoCop[startIndexInner];
    7014              : 
    7015              :                         Volume * stattVoll = startVolInfoMarkLoop.getFulldimElem();
    7016              : 
    7017              :                         vector3 centerX = CalculateCenter(stattVoll,m_aaPos);
    7018              : 
    7019              :                         UG_LOG("DAS ZENTRUM DANACH " << startIndexInner << " -> " <<  centerX << std::endl);
    7020              : 
    7021              : //                      m_sh.assign_subset(stattVoll, m_sh.num_subsets());
    7022              : #if 0
    7023              :                         for( int i = 0; i < vecAttVolElemInfoCop.size(); i++ )
    7024              :                         {
    7025              :                                 AttachedVolumeElemInfo vi = vecAttVolElemInfoCop[i];
    7026              : 
    7027              :                                 Volume * vo = vi.getFulldimElem();
    7028              : 
    7029              :                                 vector3 center = CalculateCenter(vo,m_aaPos);
    7030              : 
    7031              :                                 UG_LOG("DAS ZENTRUM ZAHL " << i << " -> " <<  center << std::endl);
    7032              : 
    7033              :                         }
    7034              : #endif
    7035              :                         for( AttachedVolumeElemInfo const & possibleOrigVolInfo : vecAttVolElemInfo )
    7036              :                         {
    7037              :                                 if( possibleOrigVolInfo.hasSameFulldimElem( startVolInfoMarkLoop ) )
    7038              :                                 {
    7039              :                                         segmentAVEI.push_back(possibleOrigVolInfo);
    7040              :                                         reconstructedVecAttVolElmInf.push_back(possibleOrigVolInfo);
    7041              :                                         break;
    7042              :                                 }
    7043              :                         }
    7044              : 
    7045              :                         vecAttVolElemInfoCop.erase( vecAttVolElemInfoCop.begin() + startIndexInner );
    7046              : 
    7047              : //                      if( d_loopsDone == 1 )
    7048              : //                              return false;
    7049              : 
    7050              :                         for( VecAttachedVolumeElemInfo::iterator aveiIt = vecAttVolElemInfoCop.begin();
    7051              :                                                                                                          aveiIt < vecAttVolElemInfoCop.end();
    7052              :                                                                                                          aveiIt++
    7053              :                         )
    7054              :                         {
    7055              :                                 AttachedVolumeElemInfo & possibleNeighbour = *aveiIt;
    7056              : 
    7057              :                                 if( possibleNeighbour.hasSameFulldimElem( startVolInfoMarkLoop ) )
    7058              :                                 {
    7059              :                                         continue;
    7060              :                                 }
    7061              :                                 else
    7062              :                                 {
    7063              :                                         bool neighbourFound = possibleNeighbour.testFullDimElmNeighbour( startVolInfoMarkLoop );
    7064              : 
    7065              :                                         if( neighbourFound )
    7066              :                                         {
    7067              :                                                 Volume * vol = possibleNeighbour.getFulldimElem();
    7068              : 
    7069              : //                                              m_sh.assign_subset(vol, m_sh.num_subsets());
    7070              : 
    7071              :                                         }
    7072              :                                 }
    7073              :                         }
    7074              : 
    7075              : 
    7076              :                         d_loopsDone++;
    7077              : 
    7078              : 
    7079              :                 }
    7080              : 
    7081              :                 vecSegVolElmInfo.push_back(segmentAVEI);
    7082              : 
    7083              : //              d_segmenteErledigt++;
    7084              : //
    7085              : //              if( d_segmenteErledigt == 1 )
    7086              : //              return false;
    7087              :         }
    7088              : 
    7089              :         if( reconstructedVecAttVolElmInf.size() != vecAttVolElemInfo.size() )
    7090              :         {
    7091              :                 UG_LOG("Rekonstruktion schief gegangen " << std::endl);
    7092              :                 UG_THROW("Rekonstruktion schief gegangen " << std::endl);
    7093              :                 return false;
    7094              :         }
    7095              : 
    7096              :         for( SegmentVolElmInfo const & svei : vecSegVolElmInfo )
    7097              :         {
    7098              :                 // TODO FIXME das hier wieder entfernen, die Subdomain Zuweisung, nur für debug Zwecke
    7099              :                 IndexType sudoMax = m_sh.num_subsets();
    7100              : 
    7101              :                 for( AttachedVolumeElemInfo const & vei : svei )
    7102              :                 {
    7103              :                         Volume * vol = vei.getFulldimElem();
    7104              : 
    7105              :                         m_sh.assign_subset( vol, sudoMax );
    7106              :                 }
    7107              :         }
    7108              : 
    7109              :         return true;
    7110              : }
    7111              : 
    7112              : 
    7113              : ////////////////////////////////////////////////////////////////////
    7114              : 
    7115              : 
    7116              : 
    7117              : //template <>
    7118              : //bool ArteExpandFracs3D::establishNewVertices< Hexahedron,
    7119              : //                                                                                        ArteExpandFracs3D::VrtxFracProptsStatus::oneFracSuDoAtt
    7120              : //                                                                                      >( Vertex * const & oldVrt )
    7121              : //template< bool APPLY_GENERAL_SEGMENT_ORDERING,
    7122              : //                ArteExpandFracs3D::VrtxFracProptsStatus vfp,
    7123              : //                typename std::enable_if< std::integral_constant<bool,!APPLY_GENERAL_SEGMENT_ORDERING>>
    7124              : //              >
    7125              : template <>
    7126              : bool ArteExpandFracs3D::establishNewVertices< false,
    7127              :                                                                                           ArteExpandFracs3D::VrtxFracProptsStatus::oneFracSuDoAtt
    7128              :                                                                                         >( Vertex * const & oldVrt )
    7129              : {
    7130              :         VecVertFracTrip & vecVertFracTrip = m_aaVrtInfoFraTri[oldVrt];
    7131              : 
    7132              : //      std::vector<Edge*> & allAssoEdges = m_aaVrtInfoAssoEdges[oldVrt];
    7133              : //      std::vector<Face*> & allAssoFaces = m_aaVrtInfoAssoFaces[oldVrt];
    7134              : //      std::vector<Volume*> & allAssoVolumes = m_aaVrtInfoAssoVols[oldVrt];
    7135              : 
    7136              :         // TODO FIXME works if at all only for very simple geometries
    7137              :         // and works only in particular if all asso volumes are part of the triple, i.e. have all a common face with the fracture
    7138              :         // this is not selbstverständlich at all!!!!
    7139              : 
    7140              :         VecVertFracTrip  vecVertFracTripCopy = m_aaVrtInfoFraTri[oldVrt]; // copy, not reference!
    7141              : 
    7142              : 
    7143              :         VecVertFracTrip firstSegment;
    7144              :         VecVertFracTrip secondSegment;
    7145              : 
    7146              :         IndexType beginIndex = 0;
    7147              : 
    7148              :         VertFracTrip startTrip = vecVertFracTripCopy[beginIndex];
    7149              : 
    7150              :         firstSegment.push_back( startTrip );
    7151              : 
    7152              :         vector3 normalOne = startTrip.getNormal();
    7153              :         vector3 normalTwo;
    7154              :         // vermute einfach umgekehrte Normale, ein Trick, der im einfachsten Fall geht......
    7155              :         VecScale(normalTwo,normalOne,-1);
    7156              : 
    7157              :         vecVertFracTripCopy.erase( vecVertFracTripCopy.begin() + beginIndex );
    7158              : 
    7159              : //      for( VecVertFracTrip::iterator itVFT  = vecVertFracTripCopy.begin();
    7160              : //                                                                         itVFT != vecVertFracTripCopy.end();
    7161              : //                                                                         itVFT++
    7162              : //              )
    7163              : //              {
    7164              : //                      VertFracTrip actualVFT = *itVFT;
    7165              : //
    7166              : //                      vector3 volCenter = CalculateCenter(actualVFT.getFullElm(),m_aaPos);
    7167              : //                      UG_LOG("Vol center" << volCenter << std::endl);
    7168              : //                      vecVertFracTripCopy.erase(itVFT);
    7169              : //              }
    7170              : //
    7171              : //      return true;
    7172              : 
    7173              : //      while( vecVertFracTripCopy.size() != 0 )
    7174              : //      {
    7175              : //              for( VecVertFracTrip::iterator itVFT  = vecVertFracTripCopy.begin();
    7176              : //                                                                         itVFT != vecVertFracTripCopy.end();
    7177              : //                                                                         itVFT++
    7178              : //              )
    7179              :         for( auto const & actualVFT : vecVertFracTripCopy )
    7180              :         {
    7181              : //                      VertFracTrip actualVFT = *itVFT;
    7182              : 
    7183              :                 vector3 normalActual = actualVFT.getNormal();
    7184              : 
    7185              :                 vector3 volCenter = CalculateCenter(actualVFT.getFullElm(),m_aaPos);
    7186              :                 UG_LOG("Vol center" << volCenter << std::endl);
    7187              : 
    7188              :                 // test direction
    7189              : 
    7190              :                 number cosinus2One = VecDot(normalOne,normalActual);
    7191              :                 number cosinus2Two = VecDot(normalTwo,normalActual);
    7192              : 
    7193              :                 UG_LOG("normal eins " << normalOne << std::endl);
    7194              :                 UG_LOG("normal zwei " << normalTwo << std::endl);
    7195              :                 UG_LOG("normal actu " << normalActual << std::endl);
    7196              : 
    7197              :                 UG_LOG("cosi one " << cosinus2One << std::endl );
    7198              :                 UG_LOG("cosi two " << cosinus2Two << std::endl );
    7199              : 
    7200              : 
    7201              :                 // if cosinus > 0, assume same side
    7202              : 
    7203              :                 if( ( cosinus2One >= 0 && cosinus2Two >= 0 ) || ( cosinus2One <= 0 && cosinus2Two <= 0 ) )
    7204              :                         UG_THROW("kann nicht auf zwei Seiten hinken" << std::endl);
    7205              : 
    7206              :                 if( cosinus2One >= 0 )
    7207              :                 {
    7208              :                         firstSegment.push_back( actualVFT );
    7209              :                 }
    7210              :                 else if( cosinus2Two >= 0 )
    7211              :                 {
    7212              :                         secondSegment.push_back( actualVFT );
    7213              :                 }
    7214              :                 else
    7215              :                 {
    7216              :                         UG_THROW("muss wo dazu gehoeren wohl" << std::endl);
    7217              :                 }
    7218              :         }
    7219              : //                      vecVertFracTripCopy.erase(itVFT);
    7220              : //              }
    7221              : //      }
    7222              : 
    7223              :         // computer averaged normal
    7224              : 
    7225              :         vector3 normalsOneSummed(0,0,0);
    7226              :         vector3 normalsTwoSummed(0,0,0);
    7227              : 
    7228              : 
    7229              :         for( auto const & seg: firstSegment )
    7230              :         {
    7231              :                 vector3 tmpVec = normalsOneSummed;
    7232              :                 VecAdd(normalsOneSummed,tmpVec,seg.getNormal());
    7233              :         }
    7234              : 
    7235              :         for( auto const & seg: secondSegment )
    7236              :         {
    7237              :                 vector3 tmpVec = normalsTwoSummed;
    7238              :                 VecAdd(normalsTwoSummed,tmpVec,seg.getNormal());
    7239              :         }
    7240              : 
    7241              :         vector3 normalsOneAveraged;
    7242              :         vector3 normalsTwoAveraged;
    7243              : 
    7244              :         if( firstSegment.size() != 0 )
    7245              :         {
    7246              :                 VecScale(normalsOneAveraged, normalsOneSummed, 1./firstSegment.size());
    7247              :         }
    7248              : 
    7249              :         if( secondSegment.size() != 0 )
    7250              :         {
    7251              :                 VecScale(normalsTwoAveraged, normalsTwoSummed, 1./secondSegment.size());
    7252              :         }
    7253              : 
    7254              :         // get to know width of fracture
    7255              : 
    7256              :         IndexType suse = startTrip.getSudoElm();
    7257              : 
    7258              :         number width = m_fracInfosBySubset[suse].width;
    7259              : 
    7260              :         number scal = width / 2.;
    7261              : 
    7262              :         vector3 scaledNormalOne, scaledNormalTwo;
    7263              :         VecScale( scaledNormalOne, normalOne, - scal );
    7264              :         VecScale( scaledNormalTwo, normalTwo, - scal );
    7265              :         // Minuszeichen wichtig, sonst wird in die falsche Richtung gedrückt, und die Volumen gehen über die fracture
    7266              :         // raus und werden grösser, anstatt kleiner zu werden.....
    7267              : 
    7268              :         vector3 posOldVrt = m_aaPos[oldVrt];
    7269              : 
    7270              :         vector3 posNewVrtOne, posNewVrtTwo;
    7271              : 
    7272              :         VecAdd( posNewVrtOne, posOldVrt, scaledNormalOne);
    7273              :         VecAdd( posNewVrtTwo, posOldVrt, scaledNormalTwo);
    7274              : 
    7275              :         Vertex * newShiftVrtxOne = *m_grid.create<RegularVertex>();
    7276              :         Vertex * newShiftVrtxTwo = *m_grid.create<RegularVertex>();
    7277              : 
    7278              :         m_aaPos[newShiftVrtxOne] = posNewVrtOne;
    7279              :         m_aaPos[newShiftVrtxTwo] = posNewVrtTwo;
    7280              : 
    7281              :         UG_LOG("Created new vertex 1 at " <<m_aaPos[newShiftVrtxOne] << std::endl );
    7282              :         UG_LOG("Created new vertex 2 at " <<m_aaPos[newShiftVrtxTwo] << std::endl );
    7283              : 
    7284              :         m_sh.assign_subset(newShiftVrtxOne, suse);
    7285              :         m_sh.assign_subset(newShiftVrtxTwo, suse);
    7286              : 
    7287              : //      m_sh.assign_subset(newShiftVrtxOne, 3);
    7288              : //      m_sh.assign_subset(newShiftVrtxTwo, 3);
    7289              : 
    7290              :         for( auto const & fs : firstSegment )
    7291              :         {
    7292              :                 Volume * vol = fs.getFullElm();
    7293              : 
    7294              :                 std::vector<Vertex*>& newVrts4Fac = m_aaVrtVecVol[ vol ];
    7295              : 
    7296              :                 for(size_t indVrt = 0; indVrt < (vol)->num_vertices();  indVrt++ )
    7297              :                 {
    7298              :                         Vertex* volVrt = (vol)->vertex(indVrt);
    7299              : 
    7300              :                         if(  volVrt == oldVrt )
    7301              :                         {
    7302              :                                 newVrts4Fac[ indVrt ] = newShiftVrtxOne;
    7303              :                         }
    7304              :                 }
    7305              :         }
    7306              : 
    7307              :         for( auto const & ses : secondSegment )
    7308              :         {
    7309              :                 Volume * vol = ses.getFullElm();
    7310              : 
    7311              :                 std::vector<Vertex*>& newVrts4Fac = m_aaVrtVecVol[ vol ];
    7312              : 
    7313              :                 for(size_t indVrt = 0; indVrt < (vol)->num_vertices();  indVrt++ )
    7314              :                 {
    7315              :                         Vertex* volVrt = (vol)->vertex(indVrt);
    7316              : 
    7317              :                         if(  volVrt == oldVrt )
    7318              :                         {
    7319              :                                 newVrts4Fac[ indVrt ] = newShiftVrtxTwo;
    7320              :                         }
    7321              :                 }
    7322              :         }
    7323              : 
    7324              : 
    7325              :         return true;
    7326              : }
    7327              : 
    7328              : #endif
    7329              : 
    7330              : ////////////////////////////////////////////////////////////////////
    7331              : 
    7332              : 
    7333            0 : bool ArteExpandFracs3D::createConditionForNewVrtcs()
    7334              : {
    7335              : 
    7336              :         //      iterate over all surrounding volumes to enable volume changes, this loop taken from SR but shortened
    7337            0 :         for(VolumeIterator iterSurrVol = m_sel.volumes_begin(); iterSurrVol != m_sel.volumes_end(); iterSurrVol++ )
    7338              :         {
    7339              :                 Volume * sv = *iterSurrVol;
    7340              : 
    7341              :                 std::vector<Vertex*>& newVrts = m_aaVrtVecVol[sv];
    7342            0 :                 newVrts.resize(sv->num_vertices());
    7343              : 
    7344            0 :                 for(size_t iVrt = 0; iVrt < sv->num_vertices(); iVrt++ )
    7345              :                 {
    7346            0 :                         newVrts[iVrt] = nullptr;
    7347              :                 }
    7348              :                         // erstmal so tun, als ob keine neuen Vertizes erzeugt werden an den alten Vertizes
    7349              :         }
    7350              : 
    7351              : 
    7352            0 :         return true;
    7353              : }
    7354              : 
    7355              : /////////////////////////////////////////////////////////////
    7356              : 
    7357            0 : bool ArteExpandFracs3D::createNewElements()
    7358              : {
    7359              :         // originally practically copied from Sebastian, as this concept was fine for 2D, but adapted in 3D
    7360              : 
    7361              :         //      create new elements
    7362              : 
    7363              :         UG_LOG("want to create new elems" << std::endl );
    7364              : 
    7365              :         //      holds local side vertex indices
    7366              :         std::vector<size_t>       locVrtInds;
    7367              : 
    7368              :         //      first we create new edges from selected ones which are connected to
    7369              :         //      inner vertices. This allows to preserve old subsets.
    7370              :         //      Since we have to make sure that we use the right vertices,
    7371              :         //      we have to iterate over the selected volumes and perform all actions on the edges
    7372              :         //      of those volumes.
    7373            0 :         for(VolumeIterator iter_sv = m_sel.volumes_begin(); iter_sv != m_sel.volumes_end(); ++iter_sv)
    7374              :         {
    7375              :                 Volume* sv = *iter_sv;
    7376              : 
    7377            0 :                 UG_LOG("entering volume to create new elems " << CalculateCenter(sv, m_aaPos) << std::endl);
    7378              : 
    7379              :                 //      check for each edge whether it has to be copied.
    7380            0 :                 for(size_t i_edge = 0; i_edge < sv->num_edges(); ++i_edge)
    7381              :                 {
    7382            0 :                         Edge* e = m_grid.get_edge(sv, i_edge);
    7383              : 
    7384            0 :                         if(m_sel.is_selected(e))
    7385              :                         {
    7386              :                                 //      check the associated vertices through the volumes aaVrtVecVol attachment.
    7387              :                                 //      If at least one has an associated new vertex and if no edge between the
    7388              :                                 //      new vertices already exists, we'll create the new edge.
    7389              :                                 size_t ind0, ind1;
    7390            0 :                                 sv->get_vertex_indices_of_edge(ind0, ind1, i_edge);
    7391            0 :                                 Vertex* nv0 = (m_aaVrtVecVol[sv])[ind0];
    7392            0 :                                 Vertex* nv1 = (m_aaVrtVecVol[sv])[ind1];
    7393              : 
    7394            0 :                                 if(nv0 || nv1)
    7395              :                                 {
    7396              :                                         //      if one vertex has no associated new one, then we use the vertex itself
    7397            0 :                                         if(!nv0)
    7398            0 :                                                 nv0 = sv->vertex(ind0);
    7399            0 :                                         if(!nv1)
    7400            0 :                                                 nv1 = sv->vertex(ind1);
    7401              : 
    7402              : #if 1
    7403              :                                         //      create the new edge if it not already exists.
    7404            0 :                                         if( ! m_grid.get_edge(nv0, nv1))
    7405            0 :                                                 m_grid.create_by_cloning(e, EdgeDescriptor(nv0, nv1), e);
    7406              : #else // only for debugging purposes
    7407              : 
    7408              :                                         //                                      if( ! ( m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft[nv0] || m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft[nv0] ) )
    7409              :                                         {
    7410              :                                                 //      create the new edge if it not already exists.
    7411              :                                                 if( ! m_grid.get_edge(nv0, nv1))
    7412              :                                                 {
    7413              :                                                         Edge * cloneEdge = * ( m_grid.create_by_cloning(e, EdgeDescriptor(nv0, nv1), e) );
    7414              : 
    7415              :                                                         if( ( m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft[nv0] || m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft[nv1] ) )
    7416              :                                                         {
    7417              :                                                                 m_sh.assign_subset(cloneEdge, m_sh.num_subsets());
    7418              :                                                                 UG_LOG("Edge clone from ending crossing cleft new shift vertex" << std::endl);
    7419              : 
    7420              :                                                         }
    7421              :                                                 }
    7422              :                                         }
    7423              :                                         //                                      else
    7424              :                                         //                                      {
    7425              :                                         //                                              UG_LOG("Edge clone from ending crossing cleft new shift vertex" << std::endl);
    7426              :                                         //                                      }
    7427              : 
    7428              :                                         // Ergebnis dieses debug Teils: alle edges, die geclont werden, sind notwendig
    7429              :                                         // auch bei ending crossing clefts
    7430              : #endif
    7431              :                                 }
    7432              :                         }
    7433              :                 }
    7434              :         }
    7435              : 
    7436              :         UG_LOG("Vol enter clone finished " << std::endl);
    7437              : 
    7438              :         //      now we create new faces from selected ones which are connected to
    7439              :         //      inner vertices. This allows to preserve old subsets.
    7440              :         //      Since we have to make sure that we use the right vertices,
    7441              :         //      we have to iterate over the selected volumes and perform all actions on the side-faces
    7442              :         //      of those volumes.
    7443              : 
    7444            0 :         FaceDescriptor fd;
    7445              : 
    7446              : 
    7447            0 :         for(VolumeIterator iter_sv = m_sel.volumes_begin(); iter_sv != m_sel.volumes_end(); ++iter_sv)
    7448              :         {
    7449              :                 Volume* sv = *iter_sv;
    7450              :                 //      check for each face whether it has to be copied.
    7451              : 
    7452            0 :                 UG_LOG("Face descriptor for vol " << CalculateCenter(sv, m_aaPos) << std::endl);
    7453              : 
    7454            0 :                 for(size_t i_face = 0; i_face < sv->num_faces(); ++i_face)
    7455              :                 {
    7456            0 :                         Face* sf = m_grid.get_face(sv, i_face);
    7457              : 
    7458            0 :                         if( m_sel.is_selected(sf))
    7459              :                         {
    7460              :                                 //      check the associated vertices through the volumes aaVrtVecVol attachment.
    7461              :                                 //      If no face between the new vertices already exists, we'll create the new face.
    7462            0 :                                 sv->get_vertex_indices_of_face(locVrtInds, i_face);
    7463            0 :                                 fd.set_num_vertices(sf->num_vertices());
    7464              : 
    7465              :                                 bool containsEndingCrossingCleftVrtx = false;
    7466              : 
    7467            0 :                                 for(size_t i = 0; i < sf->num_vertices(); ++i)
    7468              :                                 {
    7469            0 :                                         Vertex* nVrt = (m_aaVrtVecVol[sv])[locVrtInds[i]];
    7470              : 
    7471            0 :                                         if(nVrt)
    7472            0 :                                                 fd.set_vertex(i, nVrt);
    7473              :                                         else
    7474            0 :                                                 fd.set_vertex(i, sv->vertex(locVrtInds[i]));
    7475              :                                 }
    7476              : 
    7477              : #if 1
    7478              :                                 //      if the new face does not already exist, we'll create it
    7479            0 :                                 if(!m_grid.get_face(fd))
    7480            0 :                                         m_grid.create_by_cloning(sf, fd, sf);
    7481              : #else
    7482              :                                 //      if the new face does not already exist, we'll create it
    7483              :                                 if( ! m_grid.get_face(fd) )
    7484              :                                 {
    7485              :                                         Face * fac = *( m_grid.create_by_cloning(sf, fd, sf) );
    7486              : 
    7487              :                                         bool faceAtEndingCrossingCleft = m_aaMarkFaceWithEndingCrossingCleft[sf];
    7488              : 
    7489              :                                         bool faceTouchingEndingCrossingCleft = m_facAttAccsIfFaceIsSegmLimFaceEndingCrossingCleft[sf];
    7490              : 
    7491              :                                         if( faceAtEndingCrossingCleft || faceTouchingEndingCrossingCleft )
    7492              :                                         {
    7493              :                                                 m_sh.assign_subset( fac, m_sh.num_subsets() );
    7494              :                                                 UG_LOG("Face at ending crossing cleft" << std::endl);
    7495              :                                         }
    7496              :                                 }
    7497              : 
    7498              :                                 // Ergebnis dieses debug Teils: alle faces, die geclont werden, sind notwendig
    7499              :                                 // auch bei ending crossing clefts
    7500              : #endif
    7501              : 
    7502              :                         }
    7503              :                 }
    7504              :         }
    7505              : 
    7506              :         UG_LOG("Face descriptor left" << std::endl);
    7507              : 
    7508              :         //      Expand all faces.
    7509              :         //      Since volumes are replaced on the fly, we have to take care with the iterator.
    7510              :         //      record all new volumes in a vector. This will help to adjust positions later on.
    7511              : 
    7512              :         std::vector<Volume*> newFractureVolumes;
    7513              :         std::vector<IndexType> subsOfNewVolumes;
    7514              : 
    7515              :         // create alternative volumes where there are ending crossing clefts
    7516              : 
    7517              : //      etablishVolumesAtEndingCrossingClefts( std::vector<Volume*> & newFractureVolumes, std::vector<IndexType> & subsOfNewVolumes );
    7518            0 :         if( ! etablishVolumesAtEndingCrossingClefts( newFractureVolumes, subsOfNewVolumes ) )
    7519              :         {
    7520              :                 UG_LOG("unable to establish volumes at ending crossing clefts" << std::endl);
    7521              :                 return false;
    7522              :         }
    7523              : 
    7524              : //      return false;
    7525              : 
    7526            0 :         VolumeDescriptor vd;
    7527              : 
    7528              :         // beim Volumen fängt das Abfangen an, es muss abgefragt werden, ob das Volumen aus
    7529              :         // einem Segment ist, wo bisher falsch expandiert wird
    7530              :         // erst beim Face ab zu fangen ist viel zu spät TODO FIXME
    7531              :         // nicht zu vergessen, die Edges ordentlich sortiert zu sammeln, die zwei endende Vertizes enthalten,
    7532              :         // und dann zu splitten, wenn alle Attachements entfernt sind, dann Neustart anfordern mit neuer Geometrie
    7533              : 
    7534            0 :         for(VolumeIterator iter_sv = m_sel.volumes_begin(); iter_sv != m_sel.volumes_end();)
    7535              :         {
    7536              :                 Volume* sv = *iter_sv;
    7537              :                 ++iter_sv;
    7538              : 
    7539            0 :                 UG_LOG("Volume new creation try at " << CalculateCenter(sv, m_aaPos) << std::endl);
    7540              : 
    7541              :                 bool volHasEndingCrossingCleftFace = m_volAttAccsVolTouchesEndingCrossingCleft[sv];
    7542              : 
    7543              :                 //      now expand the fracture faces of sv to volumes.
    7544            0 :                 for(size_t i_side = 0; i_side < sv->num_sides(); ++i_side)
    7545              :                 {
    7546              :                         //      get the local vertex indices of the side of the volume
    7547            0 :                         sv->get_vertex_indices_of_face(locVrtInds, i_side);
    7548              : 
    7549            0 :                         Face* tFace = m_grid.get_side(sv, i_side);
    7550              : 
    7551            0 :                         if(tFace)
    7552              :                         {
    7553            0 :                                 if( m_aaMarkFaceIsFracB[tFace] ) // && ! m_aaMarkFaceHasUnclosedFracSideB[tFace] )
    7554              :                                 {
    7555              :                                         bool faceIsSegmLimEndCrossCleft = m_facAttAccsIfFaceIsSegmLimFaceEndingCrossingCleft[tFace];
    7556              :                                         bool faceIsEndingCleftCrossFace = m_aaMarkFaceWithEndingCrossingCleft[tFace];
    7557              : 
    7558            0 :                                         bool avoidFace = ( volHasEndingCrossingCleftFace && ( faceIsSegmLimEndCrossCleft || faceIsEndingCleftCrossFace ) );
    7559              : 
    7560              : //                                      for( Face * testFac :  m_d_endingCrossingCleftFaces )
    7561              : //                                      {
    7562              : //                                              if( testFac == tFace )
    7563              : //                                              {
    7564              : //                                                      avoidFace = true;
    7565              : //                                              }
    7566              : //                                      }
    7567              : //
    7568              : //                                      for( Face * testFac :  m_d_crossingNeighboredNotEndingFaces )
    7569              : //                                      {
    7570              : //                                              if( testFac == tFace )
    7571              : //                                              {
    7572              : //                                                      avoidFace = true;
    7573              : //                                              }
    7574              : //                                      }
    7575              : //
    7576              : //                                      for( Face * testFac :  m_d_crossingNeighboredNotEndingFacesCommEdg )
    7577              : //                                      {
    7578              : //                                              if( testFac == tFace )
    7579              : //                                              {
    7580              : //                                                      avoidFace = true;
    7581              : //                                              }
    7582              : //                                      }
    7583              : //
    7584              : //                                      for( Face * testFac :  m_d_notEndingCrossingFacesNotNeighbour )
    7585              : //                                      {
    7586              : //                                              if( testFac == tFace )
    7587              : //                                              {
    7588              : //                                                      avoidFace = true;
    7589              : //                                              }
    7590              : //                                      }
    7591              : 
    7592              : 
    7593              :                                         constexpr bool debugTest = true;
    7594              : 
    7595            0 :                                         if( avoidFace && debugTest )
    7596            0 :                                                 continue;
    7597              : 
    7598            0 :                                         Volume* expVol = nullptr;
    7599              : 
    7600            0 :                                         if(locVrtInds.size() == 3)
    7601              :                                         {
    7602            0 :                                                 size_t iv0 = locVrtInds[0];
    7603            0 :                                                 size_t iv1 = locVrtInds[1];
    7604            0 :                                                 size_t iv2 = locVrtInds[2];
    7605              : 
    7606              :                                                 if(    ( m_aaVrtVecVol[sv] )[iv0]
    7607            0 :                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    7608            0 :                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    7609              :                                                 )
    7610              :                                                 {
    7611              :                                                         //      create a new prism
    7612            0 :                                                         expVol = *m_grid.create<Prism>(
    7613            0 :                                                                                         PrismDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    7614              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    7615              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    7616              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0]));
    7617              :                                                 }
    7618              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    7619            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv1]
    7620              :                                                 )
    7621              :                                                 {
    7622              :                                                         //      create a new Pyramid
    7623            0 :                                                         expVol = *m_grid.create<Pyramid>(
    7624            0 :                                                                                         PyramidDescriptor(sv->vertex(iv0), sv->vertex(iv1),
    7625              :                                                                                                 (m_aaVrtVecVol[sv])[iv1],
    7626              :                                                                                                 (m_aaVrtVecVol[sv])[iv0],
    7627            0 :                                                                                                 sv->vertex(iv2)));
    7628              :                                                 }
    7629              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv1]
    7630            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv2]
    7631              :                                                 )
    7632              :                                                 {
    7633              :                                                         //      create a new Pyramid
    7634            0 :                                                         expVol = *m_grid.create<Pyramid>(
    7635            0 :                                                                                         PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv2),
    7636              :                                                                                                 (m_aaVrtVecVol[sv])[iv2],
    7637              :                                                                                                 (m_aaVrtVecVol[sv])[iv1],
    7638            0 :                                                                                                 sv->vertex(iv0)));
    7639              :                                                 }
    7640              :                                                 else if(    (m_aaVrtVecVol[sv])[iv0]
    7641            0 :                                                                  && (m_aaVrtVecVol[sv])[iv2]
    7642              :                                                 )
    7643              :                                                 {
    7644              :                                                         //      create a new Pyramid
    7645            0 :                                                         expVol = *m_grid.create<Pyramid>(
    7646            0 :                                                                                         PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv0),
    7647              :                                                                                                 (m_aaVrtVecVol[sv])[iv0],
    7648              :                                                                                                 (m_aaVrtVecVol[sv])[iv2],
    7649            0 :                                                                                                 sv->vertex(iv1)));
    7650              :                                                 }
    7651            0 :                                                 else if( ( m_aaVrtVecVol[sv])[iv0] )
    7652              :                                                 {
    7653              :                                                         //      create a new Tetrahedron
    7654            0 :                                                         expVol = *m_grid.create<Tetrahedron>(
    7655            0 :                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    7656              :                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    7657              :                                                 }
    7658            0 :                                                 else if( ( m_aaVrtVecVol[sv])[iv1] )
    7659              :                                                 {
    7660              :                                                         //      create a new Tetrahedron
    7661            0 :                                                         expVol = *m_grid.create<Tetrahedron>(
    7662            0 :                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    7663              :                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    7664              :                                                 }
    7665            0 :                                                 else if( ( m_aaVrtVecVol[sv])[iv2] )
    7666              :                                                 {
    7667              :                                                         //      create a new Tetrahedron
    7668            0 :                                                         expVol = *m_grid.create<Tetrahedron>(
    7669            0 :                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    7670              :                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    7671              :                                                 }
    7672              :                                                 else
    7673              :                                                 {
    7674              :                                                         //      Text from SR, still similar:
    7675              :                                                         //  this code-block should never be entered. If it is entered then
    7676              :                                                         //      we either selected the wrong faces (this shouldn't happen), or there
    7677              :                                                         //      are selected faces, which have fracture-boundary-vertices only.
    7678              :                                                         //      This is the same is if inner fracture edges exists, which are
    7679              :                                                         //      connected to two boundary vertices.
    7680              :                                                         //      Since we tried to remove those edges above, something went wrong.
    7681              :                                                         //      remove the temporary attachments and throw an error
    7682              : 
    7683              :                                                         UG_LOG("Tetraeder Fehlt eine Loesung " << std::endl);
    7684              : #if 1
    7685            0 :                                                         detachMarkers();
    7686            0 :                                                         throw(UGError("Error in ExpandFractures3d Arte Stasi. Implementation Error."));
    7687              :                                                         return false;
    7688              : #endif
    7689              :                                                 }
    7690              :                                         }
    7691            0 :                                         else if ( locVrtInds.size() == 4 )
    7692              :                                         {
    7693              :                                                 // newly implemented by Markus to test with Hexahedrons, not really working.....
    7694              : 
    7695            0 :                                                 size_t iv0 = locVrtInds[0];
    7696            0 :                                                 size_t iv1 = locVrtInds[1];
    7697            0 :                                                 size_t iv2 = locVrtInds[2];
    7698            0 :                                                 size_t iv3 = locVrtInds[3];
    7699              : 
    7700              :                                                 if(    ( m_aaVrtVecVol[sv] )[iv0]
    7701            0 :                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    7702            0 :                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    7703            0 :                                                         && ( m_aaVrtVecVol[sv] )[iv3]
    7704              :                                                 )
    7705              :                                                 {
    7706              :                                                         //      create a new prism
    7707            0 :                                                         expVol = *m_grid.create<Hexahedron>(
    7708            0 :                                                                                                 HexahedronDescriptor(
    7709            0 :                                                                                                                         sv->vertex(iv3), sv->vertex(iv2),
    7710            0 :                                                                                                                         sv->vertex(iv1), sv->vertex(iv0),
    7711              :                                                                                                                         (m_aaVrtVecVol[sv])[iv3],
    7712              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    7713              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    7714              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0]
    7715              :                                                                                                                         )
    7716              :                                                                                                                 );
    7717              : 
    7718              : //                                                      m_sh.assign_subset(expVol, m_fracInfosBySubset.at(m_sh.get_subset_index(tFace)).newSubsetIndex);
    7719              : //
    7720              : //                                                      return true;
    7721              :                                                 }
    7722              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    7723            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv1]
    7724              : 
    7725              :                                                 )
    7726              :                                                 {
    7727              :                                                         //      create a new prism
    7728              :                                                         //      create a new prism
    7729              : //                                                      expVol = *m_grid.create<Prism>(
    7730              : //                                                                                      PrismDescriptor(sv->vertex(iv3),sv->vertex(iv2), sv->vertex(iv1),
    7731              : //                                                                                                                      sv->vertex(iv0),
    7732              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv1],
    7733              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv0])
    7734              : //                                                                                                                      );
    7735              :                                                         //      create a new Prism
    7736              :                                                         ///     only used to initialize a prism. for all other tasks you should use VolumeDescripor.
    7737              :                                                         /**
    7738              :                                                          * please be sure to pass the vertices in the correct order:
    7739              :                                                          * v1, v2, v3: bottom-vertices in counterclockwise order (if viewed from the top).
    7740              :                                                          * v4, v5, v6: top-vertices in counterclockwise order (if viewed from the top).
    7741              :                                                          *              PrismDescriptor(Vertex* v1, Vertex* v2, Vertex* v3,
    7742              :                                                 Vertex* v4, Vertex* v5, Vertex* v6);
    7743              :                                                          *
    7744              :                                                          */
    7745            0 :                                                         expVol = *m_grid.create<Prism>(
    7746            0 :                                                                                         PrismDescriptor( (m_aaVrtVecVol[sv])[iv0],
    7747            0 :                                                                                                         sv->vertex(iv0), sv->vertex(iv3),
    7748            0 :                                                                                                         (m_aaVrtVecVol[sv])[iv1], sv->vertex(iv1), sv->vertex(iv2)
    7749              :                                                                                                 )
    7750              :                                                                                                 );
    7751              : 
    7752              :                                                         UG_LOG("PRISM 0 1 " << std::endl);
    7753              :                                                 }
    7754              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    7755            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv2]
    7756              :                                                 )
    7757              :                                                 {
    7758              :                                                         UG_LOG("PRISM 0 2 " << std::endl);
    7759            0 :                                                         expVol = *m_grid.create<Prism>(
    7760            0 :                                                                                         PrismDescriptor( (m_aaVrtVecVol[sv])[iv0],
    7761            0 :                                                                                                         sv->vertex(iv0), sv->vertex(iv3),
    7762            0 :                                                                                                         sv->vertex(iv2), (m_aaVrtVecVol[sv])[iv2], sv->vertex(iv1)
    7763              :                                                                                                 )
    7764              :                                                                                                 );
    7765              : 
    7766              : //                                                      m_sh.assign_subset(expVol, m_sh.num_subsets());
    7767              : //                                                      m_sh.assign_subset( sv->vertex(iv0), m_sh.num_subsets());
    7768              : //                                                      m_sh.assign_subset( sv->vertex(iv1), m_sh.num_subsets());
    7769              : //                                                      m_sh.assign_subset( sv->vertex(iv2), m_sh.num_subsets());
    7770              : //                                                      m_sh.assign_subset( sv->vertex(iv3), m_sh.num_subsets());
    7771              : //                                                      m_sh.assign_subset( (m_aaVrtVecVol[sv])[iv0], m_sh.num_subsets());
    7772              : //                                                      m_sh.assign_subset( (m_aaVrtVecVol[sv])[iv2], m_sh.num_subsets());
    7773              : 
    7774              : 
    7775              :                                                 }
    7776              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    7777            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv3]
    7778              :                                                 )
    7779              :                                                 {
    7780              :                                                         UG_LOG("PRISM 0 3 " << std::endl);
    7781              : 
    7782              :                                                 }
    7783              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv1]
    7784            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv2]
    7785              :                                                 )
    7786              :                                                 {
    7787              : 
    7788              :                                                         UG_LOG("PRISM 1 2 " << std::endl);
    7789              : 
    7790              :                                                 }
    7791              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv2]
    7792            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv3]
    7793              :                                                 )
    7794              :                                                 {
    7795              :                                                         UG_LOG("PRISM 2 3 " << std::endl);
    7796              : 
    7797              :                                                 }
    7798              : 
    7799              : 
    7800              : 
    7801              :                                         }
    7802              :                                         else
    7803              :                                         {
    7804              :                                                 //      traditionally only tetrahedrons are supported. This section thus raises an error
    7805              :                                                 // Markus tries to implement also Hexahedra
    7806              : //                                                      grid.detach_from_vertices(aVrtVec);
    7807              : //                                                      grid.detach_from_volumes(aVrtVec);
    7808              : //                                                      grid.detach_from_vertices(aAdjMarker);
    7809              : //                                                      grid.detach_from_edges(aAdjMarker);
    7810            0 :                                                 detachMarkers();
    7811            0 :                                                 throw(UGError("Incomplete implementation error in ExpandFractures3d Arte: Only tetrahedrons are supported in the current implementation, and hexahedra are in development."));
    7812              :                                                 return false;
    7813              :                                         }
    7814              : 
    7815            0 :                                         if(expVol)
    7816              :                                         {
    7817              : 
    7818            0 :                                                 IndexType newSubs = m_fracInfosBySubset.at(m_sh.get_subset_index(tFace)).newSubsetIndex;
    7819              : 
    7820            0 :                                                 subsOfNewVolumes.push_back( newSubs );
    7821              : 
    7822              : //                                              m_sh.assign_subset(expVol, m_fracInfosBySubset.at(m_sh.get_subset_index(tFace)).newSubsetIndex);
    7823            0 :                                                 m_sh.assign_subset(expVol, newSubs);
    7824              : 
    7825            0 :                                                 newFractureVolumes.push_back(expVol);
    7826              : 
    7827              :                                                 // TODO FIXME irgendwie hier muss die Infosammlung für die Diamenten auch stattfinden
    7828              : 
    7829              :                                                 // check if contains a crossing point
    7830              : 
    7831              :                                                 IndexType constexpr maxVolVrtxNum = 3;  // restricts algo to tetrahedral based grids
    7832              : 
    7833              : #if 1
    7834              : //                                              std::vector<VrtxPair> oldShiftVrtcs;
    7835              : 
    7836            0 :                                                 for( auto const & crossVrtx : m_vrtcsCrossingPts )
    7837              :                                                 {
    7838            0 :                                                         for( IndexType i = 0; i < maxVolVrtxNum; i++ )
    7839              :                                                         {
    7840            0 :                                                                 IndexType iv = locVrtInds[i];
    7841            0 :                                                                 Vertex * oldVrt = sv->vertex(iv);
    7842              : 
    7843            0 :                                                                 if( oldVrt == crossVrtx )
    7844              :                                                                 {
    7845            0 :                                                                         Vertex * shiVrt = ( m_aaVrtVecVol[sv] )[iv];
    7846              : 
    7847            0 :                                                                         if( shiVrt )
    7848              :                                                                         {
    7849            0 :                                                                                 Vertex * oldVrt = sv->vertex(iv);
    7850              :                                                                                 VrtxPair osv( oldVrt, shiVrt );
    7851              :                                                                                 VolManifVrtxCombi vmvc( expVol, tFace, osv, newSubs );
    7852              : 
    7853            0 :                                                                                 m_vecVolManifVrtxCombiToShrink4Diams.push_back(vmvc);
    7854              :                                                                         }
    7855              :                                                                 }
    7856              :                                                         }
    7857              :                                                 }
    7858              : 
    7859              : //                                              if( oldShiftVrtcs.size() > 0 )
    7860              : //                                              {
    7861              : //                                              }
    7862              : 
    7863              : #else
    7864              : 
    7865              :                                                 bool containsCrossVrtx = false;
    7866              : 
    7867              :                                                 for( auto const & crossVrtx : m_vrtcsCrossingPts )
    7868              :                                                 {
    7869              :                                                         for( IndexType i = 0; i < maxVolVrtxNum; i++ )
    7870              :                                                         {
    7871              :                                                                 IndexType iv = locVrtInds[i];
    7872              :                                                                 Vertex * oldVrt = sv->vertex(iv);
    7873              : 
    7874              :                                                                 if( oldVrt == crossVrtx )
    7875              :                                                                 {
    7876              :                                                                         containsCrossVrtx = true;
    7877              :                                                                         break;
    7878              :                                                                 }
    7879              :                                                         }
    7880              : 
    7881              :                                                         if( containsCrossVrtx )
    7882              :                                                                 break;
    7883              :                                                 }
    7884              : 
    7885              :                                                 if( containsCrossVrtx )
    7886              :                                                 {
    7887              :                                                         std::vector<VrtxPair> oldShiftVrtcs;
    7888              : 
    7889              :                                                         for( IndexType i = 0; i < maxVolVrtxNum; i++ )
    7890              :                                                         {
    7891              :                                                                 IndexType iv = locVrtInds[i];
    7892              : 
    7893              :                                                                 Vertex * shiVrt = ( m_aaVrtVecVol[sv] )[iv];
    7894              : 
    7895              :                                                                 if( shiVrt )
    7896              :                                                                 {
    7897              :                                                                         Vertex * oldVrt = sv->vertex(iv);
    7898              :                                                                         VrtxPair cv( oldVrt, shiVrt );
    7899              :                                                                         oldShiftVrtcs.push_back(cv);
    7900              :                                                                 }
    7901              :                                                         }
    7902              : 
    7903              :                                                         VolManifVrtxCombi vmvc( expVol, tFace, oldShiftVrtcs, newSubs );
    7904              : 
    7905              :                                                         m_vecVolManifVrtxCombiToShrink4Diams.push_back(vmvc);
    7906              :                                                 }
    7907              : 
    7908              : #endif
    7909              : 
    7910              :                                         }
    7911              :                                 }
    7912              :                         }
    7913              :                 }
    7914              : 
    7915              :                 //      now set up a new volume descriptor and replace the volume.
    7916            0 :                 if(vd.num_vertices() != sv->num_vertices())
    7917            0 :                         vd.set_num_vertices(sv->num_vertices());
    7918              : 
    7919            0 :                 for(size_t i_vrt = 0; i_vrt < sv->num_vertices(); ++i_vrt)
    7920              :                 {
    7921            0 :                         if( (m_aaVrtVecVol[sv])[i_vrt] )
    7922            0 :                                 vd.set_vertex(i_vrt, (m_aaVrtVecVol[sv])[i_vrt]);
    7923              :                         else
    7924            0 :                                 vd.set_vertex(i_vrt, sv->vertex(i_vrt));
    7925              :                 }
    7926              : 
    7927            0 :                 m_grid.create_by_cloning(sv, vd, sv);
    7928            0 :                 m_grid.erase(sv);
    7929              :         }
    7930              : 
    7931              :         UG_LOG("Volumes erzeugt " << std::endl);
    7932              : 
    7933              : //      return false;
    7934              : 
    7935              : 
    7936              : 
    7937              : 
    7938              :         //      we have to clean up unused faces and edges.
    7939              :         //      note that all selected edges with mark 0 may safley be deleted. - warum?
    7940            0 :         for(EdgeIterator iter = m_sel.begin<Edge>(); iter!= m_sel.end<Edge>();)
    7941              :         {
    7942              :                 //      take care of the iterator
    7943              :                 Edge* e = *iter;
    7944              :                 ++iter;
    7945              : 
    7946            0 :                 if( m_aaMarkEdgeVFP[e].getNumberFracEdgesInVertex() == 0 )
    7947            0 :                         m_grid.erase(e);
    7948              :         }
    7949              : 
    7950              :         //      make sure that no unused faces linger around (This should never happen!)
    7951              :         bool foundUnusedFaces = false;
    7952              : 
    7953            0 :         for(FaceIterator iter = m_sel.begin<Face>(); iter != m_sel.end<Face>();)
    7954              :         {
    7955              :                 Face* f = *iter;
    7956              :                 ++iter;
    7957              : 
    7958              : //              if( m_aaMarkFaceHasUnclosedFracSideB[f] )
    7959              : //              {
    7960              : //                      UG_LOG("want to delete unclosed frac face " << std::endl);
    7961              : //                      // todo fixme XXXXXXXXXXXXXXXXXX
    7962              : //                      //return false;
    7963              : //              }
    7964              : 
    7965            0 :                 if( ! m_aaMarkFaceIsFracB[f] )
    7966              :                 {
    7967              :                         foundUnusedFaces = true;
    7968            0 :                         m_grid.erase(f);
    7969              :                 }
    7970              :         }
    7971              : 
    7972            0 :         if(foundUnusedFaces)
    7973              :         {
    7974              :                 UG_LOG("WARNING in ExpandFractures3D Arte: Unused faces encountered during cleanup. Removing them...\n");
    7975              :         }
    7976              : 
    7977            0 :         if( subsOfNewVolumes.size() != newFractureVolumes.size() )
    7978              :         {
    7979            0 :                 UG_THROW("andere zahl neue volumes als subdoms " << std::endl);
    7980              :         }
    7981              : 
    7982              : 
    7983              : //      return true;
    7984              : 
    7985              : 
    7986              :         IndexType nfn = 0;
    7987              : 
    7988            0 :         for( auto const & nf : newFractureVolumes )
    7989              :         {
    7990            0 :                 for(size_t iFace = 0; iFace < nf->num_faces(); ++iFace)
    7991              :                 {
    7992            0 :                         Face * fac = m_grid.get_face(nf, iFace);
    7993              : 
    7994            0 :                         m_sh.assign_subset( fac, subsOfNewVolumes[nfn] );
    7995              : 
    7996              :                 }
    7997              : 
    7998            0 :                 for(size_t iEdge = 0; iEdge < nf->num_edges(); ++iEdge)
    7999              :                 {
    8000            0 :                         Edge* edg = m_grid.get_edge(nf, iEdge);
    8001              : 
    8002            0 :                         m_sh.assign_subset( edg, subsOfNewVolumes[nfn] );
    8003              : 
    8004              :                 }
    8005              : 
    8006            0 :                 for( size_t iVrt = 0; iVrt < nf->num_vertices(); iVrt++ )
    8007              :                 {
    8008            0 :                         Vertex * vrt = nf->vertex(iVrt);
    8009              : 
    8010            0 :                         m_sh.assign_subset( vrt, subsOfNewVolumes[nfn] );
    8011              :                 }
    8012              : 
    8013            0 :                 nfn++;
    8014              :         }
    8015              : 
    8016            0 :         for( EndingCrossingFractureSegmentInfo const & ecfsi : m_vecEndCrossFractSegmInfo )
    8017              :         {
    8018              :                 Face * hiddenCutFracFace = ecfsi.spuckHiddenCutFractManifEl();
    8019              : 
    8020              :                 IndexType subsECC = ecfsi.spuckSudoFractEnding();
    8021              : 
    8022            0 :                 m_sh.assign_subset( hiddenCutFracFace, subsECC );
    8023              : 
    8024            0 :                 for(size_t iEdge = 0; iEdge < hiddenCutFracFace->num_edges(); ++iEdge)
    8025              :                 {
    8026            0 :                         Edge* edg = m_grid.get_edge(hiddenCutFracFace, iEdge);
    8027              : 
    8028            0 :                         m_sh.assign_subset( edg, subsECC );
    8029              : 
    8030              :                 }
    8031              : 
    8032            0 :                 for( size_t iVrt = 0; iVrt < hiddenCutFracFace->num_vertices(); iVrt++ )
    8033              :                 {
    8034            0 :                         Vertex * vrt = hiddenCutFracFace->vertex(iVrt);
    8035              : 
    8036            0 :                         m_sh.assign_subset( vrt, subsECC );
    8037              :                 }
    8038              : 
    8039              :         }
    8040              : 
    8041              : 
    8042              :         return true;
    8043            0 : }
    8044              : 
    8045            0 : ArteExpandFracs3D::IndexType ArteExpandFracs3D::deleteEndingCrossingCleftOrigFacs()
    8046              : {
    8047              : 
    8048              :         IndexType numOfDelSegs = 0;
    8049              : 
    8050            0 :         for( EndingCrossingFractureSegmentInfo const & ecfsi : m_vecEndCrossFractSegmInfo )
    8051              :         {
    8052              :                 Vertex * vrt = ecfsi.spuckUnclosedVrtx();
    8053              : 
    8054              :                 Edge * directionEdge = ecfsi.spuckLowdimElmShiftDirection();
    8055              : 
    8056              :                 Face * oldFractFacCut = ecfsi.spuckEndingFractManifCutting();
    8057              : 
    8058              :                 std::vector<Face*> vecOldFractFacNotCut = ecfsi.spuckVecEndingFractManifNotCutting();
    8059              : 
    8060              : //              Edge * commonEdge = nullptr;
    8061              : 
    8062              :                 std::vector<Edge*> innerEdges;
    8063              : 
    8064            0 :                 for( Face * oldFractFacNotCut : vecOldFractFacNotCut )
    8065              :                 {
    8066              : //                      for(size_t iEdge = 0; iEdge < oldFractFacCut->num_edges(); ++iEdge)
    8067              : //                      {
    8068              : //                              Edge* edgC = m_grid.get_edge(oldFractFacCut, iEdge);
    8069              : 
    8070            0 :                         for(size_t iEdge = 0; iEdge < oldFractFacNotCut->num_edges(); ++iEdge)
    8071              :                         {
    8072            0 :                                 Edge* edgN = m_grid.get_edge(oldFractFacNotCut, iEdge);
    8073              : 
    8074            0 :                                 if( edgN != directionEdge && EdgeContains(edgN, vrt) )
    8075              :                                         addElem(innerEdges, edgN);
    8076              : //                                      if( edgC == edgN )
    8077              : //                                      {
    8078              : //                                              commonEdge = edgC;
    8079              : //                                              break;
    8080              : //                                      }
    8081              : 
    8082              :                         }
    8083              : //                              if( commonEdge )
    8084              : //                                      break;
    8085              : //
    8086              : //                      }
    8087              :                 }
    8088              : 
    8089            0 :                 if( oldFractFacCut )
    8090            0 :                         m_grid.erase(oldFractFacCut);
    8091              : 
    8092            0 :                 for( Face * oldFractFacNotCut : vecOldFractFacNotCut )
    8093              :                 {
    8094            0 :                         if( oldFractFacNotCut )
    8095            0 :                                 m_grid.erase(oldFractFacNotCut);
    8096              :                 }
    8097              : 
    8098            0 :                 if( directionEdge )
    8099            0 :                         m_grid.erase(directionEdge);
    8100              : 
    8101            0 :                 for( Edge * iE : innerEdges )
    8102              :                 {
    8103            0 :                         if( iE )
    8104              :                         {
    8105            0 :                                 m_grid.erase(iE);
    8106              : //                              m_sh.assign_subset( iE, m_sh.num_subsets());
    8107              :                         }
    8108              :                 }
    8109              : 
    8110            0 :                 numOfDelSegs++;
    8111            0 :         }
    8112              : 
    8113            0 :         return numOfDelSegs;
    8114              : }
    8115              : 
    8116              : ////////////////////////////////////////////////////////////
    8117              : 
    8118            0 : bool ArteExpandFracs3D::etablishVolumesAtEndingCrossingClefts( std::vector<Volume*> & newFractureVolumes, std::vector<IndexType> & subsOfNewVolumes )
    8119              : {
    8120              : 
    8121            0 :         for( EndingCrossingFractureSegmentInfo & ecfsi : m_vecEndCrossFractSegmInfo )
    8122              :         {
    8123              :                 Vertex * baseVrtx = ecfsi.spuckUnclosedVrtx();
    8124              : 
    8125              :                 Vertex * shiftVrtx = ecfsi.spuckShiftVrtx();
    8126              : 
    8127              :                 Edge * cutEdge = ecfsi.spuckOldLowDimElCut();
    8128              : 
    8129              :                 Vertex * secondVrtxCutEdge = nullptr;
    8130              : 
    8131            0 :                 if( cutEdge->vertex(0) == baseVrtx )
    8132              :                 {
    8133            0 :                         secondVrtxCutEdge = cutEdge->vertex(1);
    8134              :                 }
    8135            0 :                 else if( cutEdge->vertex(1) == baseVrtx )
    8136              :                 {
    8137            0 :                         secondVrtxCutEdge = cutEdge->vertex(0);
    8138              :                 }
    8139              :                 else
    8140              :                 {
    8141              :                         UG_LOG("no second vertex of cut edge " << std::endl);
    8142            0 :                         UG_THROW("no second vertex of cut edge " << std::endl);
    8143              :                         return false;
    8144              :                 }
    8145              : 
    8146            0 :                 Edge * divisionEdge = *m_grid.create<RegularEdge>( EdgeDescriptor( secondVrtxCutEdge, shiftVrtx ) );
    8147              : 
    8148              :                 IndexType subsetECC = ecfsi.spuckSudoFractEnding();
    8149              : 
    8150              : //              m_sh.assign_subset(divisionEdge, m_sh.num_subsets());
    8151            0 :                 m_sh.assign_subset(divisionEdge, subsetECC);
    8152              : 
    8153            0 :                 Face * hiddenCutFracFace = *m_grid.create<Triangle>(TriangleDescriptor( baseVrtx, shiftVrtx, secondVrtxCutEdge ));
    8154              : 
    8155              : //              m_sh.assign_subset(hiddenCutFracFace, m_sh.num_subsets());
    8156            0 :                 m_sh.assign_subset(hiddenCutFracFace, subsetECC);
    8157              : 
    8158            0 :                 IndexType subsNewFacesEdges = m_sh.get_subset_index(hiddenCutFracFace);
    8159              : 
    8160            0 :                 for(size_t iEdge = 0; iEdge < hiddenCutFracFace->num_edges(); ++iEdge)
    8161              :                 {
    8162            0 :                         Edge* edg = m_grid.get_edge(hiddenCutFracFace, iEdge);
    8163              : 
    8164            0 :                         m_sh.assign_subset( edg, subsNewFacesEdges );
    8165            0 :                         UG_LOG("HEDGE CENTER " << CalculateCenter( edg, m_aaPos ) << std::endl );
    8166              : 
    8167            0 :                         UG_LOG("HEdge subdom " << m_sh.get_subset_index(edg) << std::endl );
    8168              : 
    8169              :                 }
    8170              : 
    8171              :                 if( ! ecfsi.schluckHiddenCutFractManifEl( hiddenCutFracFace ))
    8172              :                 {
    8173              :                         UG_LOG("hidden cut face Problem" << std::endl);
    8174            0 :                         UG_THROW("hidden cut face Problem" << std::endl);
    8175              :                 }
    8176              : 
    8177              :                 Face * endingFractFacCutting = ecfsi.spuckEndingFractManifCutting();
    8178              : 
    8179              :                 IndexType const triangVrtxNum = 3;
    8180              : 
    8181            0 :                 if( endingFractFacCutting->num_vertices() != triangVrtxNum )
    8182              :                 {
    8183              :                         UG_LOG("only triangles allowed " << std::endl);
    8184            0 :                         UG_THROW("only triangles allowed " << std::endl);
    8185              :                 }
    8186              : 
    8187              : 
    8188              :                 IndexType foundNotTouchVrtx = 0;
    8189              : 
    8190              :                 Vertex * notTouchingVrtx = nullptr;
    8191              : 
    8192              : 
    8193              :                 // figure out that vertex of the ending fracture faces that is not touching the crossing not ending cleft
    8194            0 :                 for( IndexType vrtIndx = 0; vrtIndx < triangVrtxNum; vrtIndx++ )
    8195              :                 {
    8196            0 :                         Vertex * testVrt = endingFractFacCutting->vertex(vrtIndx);
    8197              : 
    8198            0 :                         if( ! EdgeContains( cutEdge, testVrt ) )
    8199              :                         {
    8200            0 :                                 foundNotTouchVrtx++;
    8201              :                                 notTouchingVrtx = testVrt;
    8202              :                         }
    8203              :                 }
    8204              : 
    8205            0 :                 if( foundNotTouchVrtx != 1 || ! notTouchingVrtx  )
    8206              :                 {
    8207              :                         UG_LOG("not touching vertex not found " << std::endl);
    8208            0 :                         UG_THROW("not touching vertex not found " << std::endl);
    8209              :                 }
    8210              : 
    8211              :                 // replace the face that touches with an edge
    8212            0 :                 Face * replaceEndingFractCutFac = *m_grid.create<Triangle>(TriangleDescriptor( shiftVrtx, secondVrtxCutEdge, notTouchingVrtx ));
    8213              : 
    8214              : //              m_sh.assign_subset( replaceEndingFractCutFac, m_sh.num_subsets() );
    8215            0 :                 m_sh.assign_subset( replaceEndingFractCutFac, subsetECC );
    8216              : 
    8217            0 :                 IndexType subsNewFacesEdgesC = m_sh.get_subset_index(replaceEndingFractCutFac);
    8218              : 
    8219              :                 UG_LOG("EDGE NUMBER CCS CC " << replaceEndingFractCutFac->num_edges() << std::endl);
    8220              : 
    8221            0 :                 for(size_t iEdge = 0; iEdge < replaceEndingFractCutFac->num_edges(); ++iEdge)
    8222              :                 {
    8223            0 :                         Edge* edg = m_grid.get_edge(replaceEndingFractCutFac, iEdge);
    8224              : 
    8225            0 :                         m_sh.assign_subset( edg, subsNewFacesEdgesC );
    8226            0 :                         UG_LOG("EDGE CENTER " << CalculateCenter( edg, m_aaPos ) << std::endl );
    8227              : 
    8228            0 :                         UG_LOG("Edge subdom " << m_sh.get_subset_index(edg) << std::endl );
    8229              : 
    8230              :                 }
    8231              : 
    8232              : //              // replace the face that has only the base vertex common, if existing
    8233              : //              Face * endingFractFacNotCutting = ecfsi.spuckEndingFractManifNotCutting();
    8234              : //
    8235            0 :                 for( Face * const & endingFractFacNotCutting : ecfsi.spuckVecEndingFractManifNotCutting() )
    8236              :                 {
    8237            0 :                         if( endingFractFacNotCutting )
    8238              :                         {
    8239              : 
    8240            0 :                                 if( endingFractFacNotCutting->num_vertices() != triangVrtxNum )
    8241              :                                 {
    8242              :                                         UG_LOG("only triangles allowed NC" << std::endl);
    8243            0 :                                         UG_THROW("only triangles allowed NC" << std::endl);
    8244              :                                 }
    8245              : 
    8246              :                                 std::vector<Vertex*> vrtcsNotBase;
    8247              : 
    8248              :                                 // figure out those vertices which are not the basis vertex
    8249            0 :                                 for( IndexType vrtIndx = 0; vrtIndx < triangVrtxNum; vrtIndx++ )
    8250              :                                 {
    8251            0 :                                         Vertex * testVrt = endingFractFacNotCutting->vertex(vrtIndx);
    8252              : 
    8253            0 :                                         if( testVrt != baseVrtx )
    8254            0 :                                                 vrtcsNotBase.push_back(testVrt);
    8255              :                                 }
    8256              : 
    8257            0 :                                 if( vrtcsNotBase.size() != 2 )
    8258              :                                 {
    8259              :                                         UG_LOG("strange number vertices " << vrtcsNotBase.size() << std::endl);
    8260            0 :                                         UG_THROW("strange number vertices " << vrtcsNotBase.size() << std::endl);
    8261              :                                 }
    8262              : 
    8263            0 :                                 Face * replaceEndingFractNotCutFac = *m_grid.create<Triangle>(TriangleDescriptor( shiftVrtx, vrtcsNotBase[0], vrtcsNotBase[1] ));
    8264              : 
    8265              :         //                      m_sh.assign_subset( replaceEndingFractNotCutFac, m_sh.num_subsets() );
    8266            0 :                                 m_sh.assign_subset( replaceEndingFractNotCutFac, subsetECC );
    8267              : 
    8268            0 :                                 IndexType subsNewFacesEdges = m_sh.get_subset_index(replaceEndingFractNotCutFac);
    8269              : 
    8270              :                                 UG_LOG("EDGE NUMBER CCS " << replaceEndingFractNotCutFac->num_edges() << std::endl);
    8271              : 
    8272            0 :                                 for(size_t iEdge = 0; iEdge < replaceEndingFractNotCutFac->num_edges(); ++iEdge)
    8273              :                                 {
    8274            0 :                                         Edge* edg = m_grid.get_edge(replaceEndingFractNotCutFac, iEdge);
    8275              : 
    8276            0 :                                         m_sh.assign_subset( edg, subsNewFacesEdges );
    8277              : 
    8278            0 :                                         UG_LOG("EDGE CENTER " << CalculateCenter( edg, m_aaPos ) << std::endl );
    8279              : 
    8280            0 :                                         UG_LOG("Edge subdom " << m_sh.get_subset_index(edg) << std::endl );
    8281              : 
    8282              :                                 }
    8283              : 
    8284            0 :                         }
    8285              : 
    8286            0 :                 }
    8287              : 
    8288              : //              for(VolumeIterator iter_sv = m_sel.volumes_begin(); iter_sv != m_sel.volumes_end();)
    8289            0 :                 for( Volume * const & sv : ecfsi.spuckVecFulldimEl() )
    8290              :                 {
    8291              : 
    8292            0 :                         UG_LOG("CEC Volume new creation try at " << CalculateCenter(sv, m_aaPos) << std::endl);
    8293              : 
    8294            0 :                         bool volHasEndingCrossingCleftFace = m_volAttAccsVolTouchesEndingCrossingCleft[sv];
    8295              : 
    8296              :                         // should be true!
    8297              : 
    8298            0 :                         if( ! volHasEndingCrossingCleftFace )
    8299              :                         {
    8300              :                                 UG_LOG("Was ist da los, ending cleft und doch nicht " << std::endl);
    8301            0 :                                 UG_THROW("Was ist da los, ending cleft und doch nicht " << std::endl);
    8302              :                         }
    8303              : 
    8304              :                         // check if volume contains the base vertex
    8305              : 
    8306            0 :                         if( ! VolumeContains(sv, baseVrtx))
    8307              :                         {
    8308              :                                 UG_LOG("VOlume ausdehenen ECC ohne base vertex " << std::endl);
    8309            0 :                                 UG_THROW("VOlume ausdehenen ECC ohne base vertex " << std::endl);
    8310              :                         }
    8311              : 
    8312              :                         //      now expand the fracture faces of sv to volumes.
    8313            0 :                         for(size_t i_side = 0; i_side < sv->num_sides(); ++i_side)
    8314              :                         {
    8315              :                                 //      holds local side vertex indices
    8316              :                                 std::vector<size_t>       locVrtInds;
    8317              : 
    8318              :                                 //      get the local vertex indices of the side of the volume
    8319            0 :                                 sv->get_vertex_indices_of_face(locVrtInds, i_side);
    8320              : 
    8321            0 :                                 Face* tFace = m_grid.get_side(sv, i_side);
    8322              : 
    8323            0 :                                 if(tFace)
    8324              :                                 {
    8325            0 :                                         if( m_aaMarkFaceIsFracB[tFace] )
    8326              :                                         {
    8327              :                                                 bool faceIsSegmLimEndCrossCleft = m_facAttAccsIfFaceIsSegmLimFaceEndingCrossingCleft[tFace];
    8328              :                                                 bool faceIsEndingCleftCrossFace = m_aaMarkFaceWithEndingCrossingCleft[tFace];
    8329              : 
    8330              :                                                 UG_LOG("Volumenerzeugung Versuch ECC Anfang" << std::endl);
    8331              : 
    8332            0 :                                                 Volume* expVol = nullptr;
    8333              : 
    8334            0 :                                                 Volume* expVolTwo = nullptr;
    8335              : 
    8336              : 
    8337            0 :                                                 if(locVrtInds.size() == 3)
    8338              :                                                 {
    8339            0 :                                                         size_t iv0 = locVrtInds[0];
    8340            0 :                                                         size_t iv1 = locVrtInds[1];
    8341            0 :                                                         size_t iv2 = locVrtInds[2];
    8342              : 
    8343              : //                                                      Vertex * vrtxOne = ( m_aaVrtVecVol[sv] )[iv0];
    8344              : //                                                      Vertex * vrtxTwo = ( m_aaVrtVecVol[sv] )[iv1];
    8345              : //                                                      Vertex * vrtxThree = ( m_aaVrtVecVol[sv] )[iv2];
    8346              : 
    8347              :                                                         // figure out which vertex is the base vertex
    8348              : 
    8349              :                                                         int indBasVrtx = -1;
    8350              : 
    8351              :                                                         // wie kann das nur stimmen, das Volumen hat doch mehr als 3 Vertizes....
    8352              :                                                         // zufällig für das Testbeispiel vielleicht richtig?
    8353              : //                                                      for( IndexType vrtxInd = 0; vrtxInd < triangVrtxNum; vrtxInd++ )
    8354            0 :                                                         for( IndexType vrtxInd = 0; vrtxInd < sv->num_vertices(); vrtxInd++ )
    8355              :                                                         {
    8356            0 :                                                                 if( sv->vertex(vrtxInd) == baseVrtx )
    8357            0 :                                                                         indBasVrtx = vrtxInd;
    8358              :                                                         }
    8359              :                                                         // muss der Loop nicht über die Vertizes des volumens gehen?????
    8360              : 
    8361              :                                                         // der Index des Basisvertex ist tabu für die Ausehnung der endenden fracture
    8362              : 
    8363            0 :                                                         bool belongsToEndingCleftFaces = (endingFractFacCutting == tFace);
    8364              : 
    8365              :                                                         bool belongstToEndingNotCuttingFacs = false;
    8366              : 
    8367            0 :                                                         for( Face * const & endingFractFacNotCutting : ecfsi.spuckVecEndingFractManifNotCutting() )
    8368              :                                                         {
    8369            0 :                                                                 if( tFace == endingFractFacNotCutting )
    8370              :                                                                 {
    8371              :                                                                         belongsToEndingCleftFaces = true;
    8372              :                                                                         belongstToEndingNotCuttingFacs = true;
    8373              :                                                                         UG_LOG("Want to create for not cutting ending fract face vol " << std::endl);
    8374              :                                                                 }
    8375            0 :                                                         }
    8376              : 
    8377            0 :                                                         if( belongsToEndingCleftFaces != faceIsEndingCleftCrossFace )
    8378              :                                                         {
    8379              :                                                                 UG_LOG("Widerspruch ending but not ending ECC" << std::endl);
    8380            0 :                                                                 UG_THROW("Widerspruch ending but not ending ECC" << std::endl);
    8381              : 
    8382              :                                                         }
    8383              : 
    8384            0 :                                                         if( belongsToEndingCleftFaces )
    8385              :                                                         {
    8386            0 :                                                                 if( ! faceIsEndingCleftCrossFace )
    8387              :                                                                 {
    8388              :                                                                         UG_LOG("Widerspruch ending but not ending ECC" << std::endl);
    8389              :                                                                 }
    8390              : 
    8391            0 :                                                                 if( iv0 == indBasVrtx )
    8392              :                                                                 {
    8393            0 :                                                                         if(    ( m_aaVrtVecVol[sv] )[iv0]
    8394            0 :                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    8395            0 :                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    8396              :                                                                         )
    8397              :                                                                         {
    8398              :                                                                                 //      create a new pyramid
    8399              : //                                                                              expVol = *m_grid.create<Pyramid>(
    8400              : //                                                                                                              PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv1),
    8401              : //                                                                                                                                              (m_aaVrtVecVol[sv])[iv2],
    8402              : //                                                                                                                                              (m_aaVrtVecVol[sv])[iv1],
    8403              : //                                                                                                                                              (m_aaVrtVecVol[sv])[iv0]));
    8404              : 
    8405            0 :                                                                                 expVol = *m_grid.create<Pyramid>(
    8406            0 :                                                                                                                 PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv2),
    8407              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8408              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8409              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0]));
    8410              : 
    8411              :                                                                         }
    8412              :                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8413            0 :                                                                                          && ( m_aaVrtVecVol[sv] )[iv1]
    8414              :                                                                         )
    8415              :                                                                         {
    8416              :                                                                                 //      create a new tetrahedron
    8417            0 :                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8418            0 :                                                                                                                 TetrahedronDescriptor(sv->vertex(iv1),
    8419              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8420            0 :                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    8421            0 :                                                                                                                         sv->vertex(iv2)));
    8422              :                                                                         }
    8423              : //                                                                      else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8424              : //                                                                                       && ( m_aaVrtVecVol[sv] )[iv2]
    8425              : //                                                                      )
    8426              : //                                                                      {
    8427              : //                                                                              //      create a new Pyramid
    8428              : //                                                                              expVol = *m_grid.create<Pyramid>(
    8429              : //                                                                                                              PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv2),
    8430              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv2],
    8431              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv1],
    8432              : //                                                                                                                      sv->vertex(iv0)));
    8433              : //                                                                      }
    8434              :                                                                         else if(    (m_aaVrtVecVol[sv])[iv0]
    8435            0 :                                                                                          && (m_aaVrtVecVol[sv])[iv2]
    8436              :                                                                         )
    8437              :                                                                         {
    8438              :                                                                                 //      create a new tetrahedron
    8439            0 :                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8440            0 :                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2),
    8441              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    8442            0 :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8443            0 :                                                                                                                         sv->vertex(iv1)));
    8444              :                                                                         }
    8445              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv0] )
    8446              : //                                                                      {
    8447              : //                                                                              //      create a new Tetrahedron
    8448              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8449              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8450              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv0]));
    8451              : //                                                                      }
    8452              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv1] )
    8453              : //                                                                      {
    8454              : //                                                                              //      create a new Tetrahedron
    8455              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8456              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8457              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv1]));
    8458              : //                                                                      }
    8459              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv2] )
    8460              : //                                                                      {
    8461              : //                                                                              //      create a new Tetrahedron
    8462              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8463              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8464              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv2]));
    8465              : //                                                                      }
    8466              :                                                                         else
    8467              :                                                                         {
    8468              :                                                                                 //      Text from SR, still similar:
    8469              :                                                                                 //  this code-block should never be entered. If it is entered then
    8470              :                                                                                 //      we either selected the wrong faces (this shouldn't happen), or there
    8471              :                                                                                 //      are selected faces, which have fracture-boundary-vertices only.
    8472              :                                                                                 //      This is the same is if inner fracture edges exists, which are
    8473              :                                                                                 //      connected to two boundary vertices.
    8474              :                                                                                 //      Since we tried to remove those edges above, something went wrong.
    8475              :                                                                                 //      remove the temporary attachments and throw an error
    8476              : 
    8477              :                                                                                 UG_LOG("Tetraeder ECC Fehlt eine Loesung " << std::endl);
    8478            0 :                                                                                 detachMarkers();
    8479            0 :                                                                                 throw(UGError("Error in ExpandFractures3d Arte Stasi. Implementation Error."));
    8480              :                                                                                 return false;
    8481              :                                                                         }
    8482              : 
    8483              :                                                                 }
    8484            0 :                                                                 else if( iv1 == indBasVrtx )
    8485              :                                                                 {
    8486            0 :                                                                         if(    ( m_aaVrtVecVol[sv] )[iv0]
    8487            0 :                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    8488            0 :                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    8489              :                                                                         )
    8490              :                                                                         {
    8491              :                                                                                 //      create a new prism
    8492              : //                                                                              expVol = *m_grid.create<Pyramid>(
    8493              : //                                                                                                              PyramidDescriptor( sv->vertex(iv2), sv->vertex(iv0),
    8494              : //                                                                                                                                                              (m_aaVrtVecVol[sv])[iv2],
    8495              : //                                                                                                                                                              (m_aaVrtVecVol[sv])[iv1],
    8496              : //                                                                                                                                                              (m_aaVrtVecVol[sv])[iv0]));
    8497              : 
    8498              : 
    8499            0 :                                                                                 expVol = *m_grid.create<Pyramid>(
    8500            0 :                                                                                                                 PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv0),
    8501              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    8502              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8503              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1]));
    8504              : 
    8505              :                                                                         }
    8506              :                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8507            0 :                                                                                          && ( m_aaVrtVecVol[sv] )[iv1]
    8508              :                                                                         )
    8509              :                                                                         {
    8510              :                                                                                 //      create a new Pyramid
    8511            0 :                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8512            0 :                                                                                                                 TetrahedronDescriptor(sv->vertex(iv0),
    8513              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8514            0 :                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    8515            0 :                                                                                                                         sv->vertex(iv2)));
    8516              :                                                                         }
    8517              :                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8518            0 :                                                                                          && ( m_aaVrtVecVol[sv] )[iv2]
    8519              :                                                                         )
    8520              :                                                                         {
    8521              :                                                                                 //      create a new Pyramid
    8522            0 :                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8523            0 :                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2),
    8524              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8525            0 :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8526            0 :                                                                                                                         sv->vertex(iv0)));
    8527              :                                                                         }
    8528              : //                                                                      else if(    (m_aaVrtVecVol[sv])[iv0]
    8529              : //                                                                                       && (m_aaVrtVecVol[sv])[iv2]
    8530              : //                                                                      )
    8531              : //                                                                      {
    8532              : //                                                                              //      create a new Pyramid
    8533              : //                                                                              expVol = *m_grid.create<Pyramid>(
    8534              : //                                                                                                              PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv0),
    8535              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv0],
    8536              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv2],
    8537              : //                                                                                                                      sv->vertex(iv1)));
    8538              : //                                                                      }
    8539              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv0] )
    8540              : //                                                                      {
    8541              : //                                                                              //      create a new Tetrahedron
    8542              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8543              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8544              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv0]));
    8545              : //                                                                      }
    8546              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv1] )
    8547              : //                                                                      {
    8548              : //                                                                              //      create a new Tetrahedron
    8549              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8550              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8551              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv1]));
    8552              : //                                                                      }
    8553              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv2] )
    8554              : //                                                                      {
    8555              : //                                                                              //      create a new Tetrahedron
    8556              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8557              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8558              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv2]));
    8559              : //                                                                      }
    8560              :                                                                         else
    8561              :                                                                         {
    8562              :                                                                                 //      Text from SR, still similar:
    8563              :                                                                                 //  this code-block should never be entered. If it is entered then
    8564              :                                                                                 //      we either selected the wrong faces (this shouldn't happen), or there
    8565              :                                                                                 //      are selected faces, which have fracture-boundary-vertices only.
    8566              :                                                                                 //      This is the same is if inner fracture edges exists, which are
    8567              :                                                                                 //      connected to two boundary vertices.
    8568              :                                                                                 //      Since we tried to remove those edges above, something went wrong.
    8569              :                                                                                 //      remove the temporary attachments and throw an error
    8570              : 
    8571              :                                                                                 UG_LOG("Tetraeder ECC Fehlt eine Loesung " << std::endl);
    8572            0 :                                                                                 detachMarkers();
    8573            0 :                                                                                 throw(UGError("Error in ExpandFractures3d Arte Stasi. Implementation Error."));
    8574              :                                                                                 return false;
    8575              :                                                                         }
    8576              :                                                                 }
    8577            0 :                                                                 else if( iv2 == indBasVrtx )
    8578              :                                                                 {
    8579            0 :                                                                         if(    ( m_aaVrtVecVol[sv] )[iv0]
    8580            0 :                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    8581            0 :                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    8582              :                                                                         )
    8583              :                                                                         {
    8584              :                                                                                 //      create a new prism
    8585              : //                                                                              expVol = *m_grid.create<Pyramid>(
    8586              : //                                                                                                              PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv0),
    8587              : //                                                                                                                                              (m_aaVrtVecVol[sv])[iv2],
    8588              : //                                                                                                                                              (m_aaVrtVecVol[sv])[iv1],
    8589              : //                                                                                                                                              (m_aaVrtVecVol[sv])[iv0]));
    8590              : 
    8591            0 :                                                                                 expVol = *m_grid.create<Pyramid>(
    8592            0 :                                                                                                                 PyramidDescriptor(sv->vertex(iv0), sv->vertex(iv1),
    8593              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8594              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    8595              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2]));
    8596              : 
    8597              :                                                                         }
    8598              : //                                                                      else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8599              : //                                                                                       && ( m_aaVrtVecVol[sv] )[iv1]
    8600              : //                                                                      )
    8601              : //                                                                      {
    8602              : //                                                                              //      create a new Pyramid
    8603              : //                                                                              expVol = *m_grid.create<Pyramid>(
    8604              : //                                                                                                              PyramidDescriptor(sv->vertex(iv0), sv->vertex(iv1),
    8605              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv1],
    8606              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv0],
    8607              : //                                                                                                                      sv->vertex(iv2)));
    8608              : //                                                                      }
    8609              :                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8610            0 :                                                                                          && ( m_aaVrtVecVol[sv] )[iv2]
    8611              :                                                                         )
    8612              :                                                                         {
    8613              :                                                                                 //      create a new Pyramid
    8614            0 :                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8615            0 :                                                                                                                 TetrahedronDescriptor(sv->vertex(iv1),
    8616              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8617            0 :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8618            0 :                                                                                                                         sv->vertex(iv0)));
    8619              :                                                                         }
    8620              :                                                                         else if(    (m_aaVrtVecVol[sv])[iv0]
    8621            0 :                                                                                          && (m_aaVrtVecVol[sv])[iv2]
    8622              :                                                                         )
    8623              :                                                                         {
    8624              :                                                                                 //      create a new Pyramid
    8625            0 :                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8626            0 :                                                                                                                 TetrahedronDescriptor(sv->vertex(iv0),
    8627              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    8628            0 :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8629            0 :                                                                                                                         sv->vertex(iv1)));
    8630              :                                                                         }
    8631              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv0] )
    8632              : //                                                                      {
    8633              : //                                                                              //      create a new Tetrahedron
    8634              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8635              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8636              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv0]));
    8637              : //                                                                      }
    8638              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv1] )
    8639              : //                                                                      {
    8640              : //                                                                              //      create a new Tetrahedron
    8641              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8642              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8643              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv1]));
    8644              : //                                                                      }
    8645              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv2] )
    8646              : //                                                                      {
    8647              : //                                                                              //      create a new Tetrahedron
    8648              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8649              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8650              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv2]));
    8651              : //                                                                      }
    8652              :                                                                         else
    8653              :                                                                         {
    8654              :                                                                                 //      Text from SR, still similar:
    8655              :                                                                                 //  this code-block should never be entered. If it is entered then
    8656              :                                                                                 //      we either selected the wrong faces (this shouldn't happen), or there
    8657              :                                                                                 //      are selected faces, which have fracture-boundary-vertices only.
    8658              :                                                                                 //      This is the same is if inner fracture edges exists, which are
    8659              :                                                                                 //      connected to two boundary vertices.
    8660              :                                                                                 //      Since we tried to remove those edges above, something went wrong.
    8661              :                                                                                 //      remove the temporary attachments and throw an error
    8662              : 
    8663              :                                                                                 UG_LOG("Tetraeder ECC Fehlt eine Loesung " << std::endl);
    8664            0 :                                                                                 detachMarkers();
    8665            0 :                                                                                 throw(UGError("Error in ExpandFractures3d Arte Stasi. Implementation Error."));
    8666              :                                                                                 return false;
    8667              :                                                                         }
    8668              : 
    8669              :                                                                 }
    8670              : 
    8671            0 :                                                                 if( belongstToEndingNotCuttingFacs )
    8672              :                                                                 {
    8673            0 :                                                                         if( expVol )
    8674              :                                                                         {
    8675            0 :                                                                                 UG_LOG("not cutting vol created at " << CalculateCenter(expVol, m_aaPos ) << std::endl );
    8676              : //                                                                              m_sh.assign_subset(expVol, m_sh.num_subsets());
    8677              :                                                                         }
    8678              :                                                                         else
    8679              :                                                                         {
    8680              :                                                                                 UG_LOG("was not able to create vol for not cutting " << std::endl);
    8681              :                                                                         }
    8682              :                                                                 }
    8683              :                                                         }
    8684              :                                                         else
    8685              :                                                         {
    8686              :                                                                 // test if face belongs to the closed faces
    8687              : 
    8688              :                                                                 std::pair<Face*,Face*> const & closedNeighbrs = ecfsi.spuckPairNeighbouredFractClosedManifEl();
    8689              : 
    8690              : 
    8691            0 :                                                                 if( closedNeighbrs.first == tFace || closedNeighbrs.second == tFace )
    8692              :                                                                 {
    8693              : 
    8694              :                                                                         // figure out the vertex that is not from the cut edge
    8695              : 
    8696              :                                                                         Vertex * freeVrtx = nullptr;
    8697              : 
    8698              :                                                                         // wasn das für ein Käse.....
    8699            0 :                                                                         for( IndexType vrtxInd = 0; vrtxInd < triangVrtxNum; vrtxInd++ )
    8700              : //                                                                      for( IndexType vrtxInd = 0; vrtxInd < sv->num_vertices(); vrtxInd++ )
    8701              :                                                                         {
    8702            0 :                                                                                 if( ! EdgeContains(cutEdge, tFace->vertex(vrtxInd)))
    8703            0 :                                                                                         freeVrtx = tFace->vertex(vrtxInd);
    8704              :                                                                         }
    8705              : 
    8706            0 :                                                                         if( freeVrtx == nullptr )
    8707              :                                                                         {
    8708              :                                                                                 UG_LOG("Immer noch null " << std::endl);
    8709            0 :                                                                                 UG_THROW("Immer noch null " << std::endl);
    8710              :                                                                         }
    8711              : 
    8712              : //                                                                      int freeVrtxInd = -1;
    8713              : //                                                                      int secondCutEdgVrtxInd = -1;
    8714              : //
    8715              : //                                                                      for( IndexType vrtxInd = 0; vrtxInd < sv->num_vertices(); vrtxInd++ )
    8716              : //                                                                      {
    8717              : //                                                                              if( ! EdgeContains(cutEdge, freeVrtx))
    8718              : //                                                                                      freeVrtxInd = vrtxInd;
    8719              : //
    8720              : //                                                                              if( secondVrtxCutEdge == secondVrtxCutEdge)
    8721              : //                                                                                      secondCutEdgVrtxInd = vrtxInd;
    8722              : //                                                                      }
    8723              : 
    8724              : 
    8725              :                                                                         // for the "pyramid", exclude the base Vertex
    8726              :                                                                         // for the other tetrahedron, exclude the shifted of the non-base of the cut edge
    8727              :                                                                         // i.e. of secondVrtxCutEdge
    8728              : 
    8729              : //                                                                      Vertex * vrtxNotFromCutEdge = tFace->vertex(freeVrtxInd);
    8730              : 
    8731              :                                                                         // relate iv0, iv1, iv2 to vrtxNotFromCutEdge, base
    8732              : 
    8733            0 :                                                                         if( iv0 == indBasVrtx )
    8734              :                                                                         {
    8735              : 
    8736            0 :                                                                                 if(    ( m_aaVrtVecVol[sv] )[iv0]
    8737            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    8738            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8739              :                                                                                 )
    8740              :                                                                                 {
    8741            0 :                                                                                         expVol = *m_grid.create<Pyramid>(
    8742            0 :                                                                                                                         PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv2),
    8743              :                                                                                                                                 (m_aaVrtVecVol[sv])[iv2],
    8744              :                                                                                                                                 (m_aaVrtVecVol[sv])[iv1],
    8745              :                                                                                                                                 ( m_aaVrtVecVol[sv] )[iv0]));
    8746              : 
    8747            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8748            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8749            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    8750              : 
    8751              :                                                                                 }
    8752              :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8753            0 :                                                                                                  && ( m_aaVrtVecVol[sv] )[iv1]
    8754              :                                                                                 )
    8755              :                                                                                 {
    8756            0 :                                                                                         expVol = *m_grid.create<Tetrahedron>(
    8757            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), ( m_aaVrtVecVol[sv] )[iv0],
    8758              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    8759              : 
    8760              : 
    8761            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8762            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8763            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    8764              :                                                                                 }
    8765              : //                                                                              else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8766              : //                                                                                      && ( m_aaVrtVecVol[sv] )[iv2]
    8767              : //                                                                              )
    8768              : //                                                                              {
    8769              : //
    8770              : //                                                                              }
    8771              :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8772            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8773              :                                                                                 )
    8774              :                                                                                 {
    8775              : 
    8776            0 :                                                                                         expVol = *m_grid.create<Tetrahedron>(
    8777            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1),  ( m_aaVrtVecVol[sv] )[iv0],
    8778              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8779              : 
    8780            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8781            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8782            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    8783              :                                                                                 } //
    8784            0 :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8785              :                                                                                 )
    8786              :                                                                                 {
    8787              : 
    8788            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8789            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8790              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    8791              :                                                                                 } //
    8792              : 
    8793              : 
    8794              : 
    8795              :                                                                         }
    8796              : 
    8797            0 :                                                                         if( iv1 == indBasVrtx )
    8798              :                                                                         {
    8799              : 
    8800            0 :                                                                                 if(    ( m_aaVrtVecVol[sv] )[iv0]
    8801            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    8802            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8803              :                                                                                 )
    8804              :                                                                                 {
    8805            0 :                                                                                         expVol = *m_grid.create<Pyramid>(
    8806            0 :                                                                                                                         PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv0),
    8807              :                                                                                                                                 (m_aaVrtVecVol[sv])[iv0],
    8808              :                                                                                                                                 (m_aaVrtVecVol[sv])[iv2],
    8809              :                                                                                                                                 ( m_aaVrtVecVol[sv] )[iv1]));
    8810              : 
    8811            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8812            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8813            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    8814              : 
    8815              :                                                                                 }
    8816              :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8817            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    8818              :                                                                                 )
    8819              :                                                                                 {
    8820            0 :                                                                                         expVol = *m_grid.create<Tetrahedron>(
    8821            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), ( m_aaVrtVecVol[sv] )[iv1], sv->vertex(iv0),
    8822              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    8823              : 
    8824              : 
    8825            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8826            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8827            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    8828              : 
    8829              :                                                                                 }
    8830              :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8831            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8832              :                                                                                 )
    8833              :                                                                                 {
    8834            0 :                                                                                         expVol = *m_grid.create<Tetrahedron>(
    8835            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), ( m_aaVrtVecVol[sv] )[iv1], sv->vertex(iv0),
    8836              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8837              : 
    8838            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8839            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8840            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    8841              : 
    8842              :                                                                                 }
    8843              : //                                                                              else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8844              : //                                                                                      && ( m_aaVrtVecVol[sv] )[iv2]
    8845              : //                                                                              )
    8846              : //                                                                              {
    8847              : //
    8848              : //                                                                              }
    8849            0 :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8850              :                                                                                 )
    8851              :                                                                                 {
    8852              : 
    8853            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8854            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8855              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    8856              : 
    8857              :                                                                                 }
    8858              : 
    8859              : 
    8860              :                                                                         }
    8861              : 
    8862            0 :                                                                         if( iv2 == indBasVrtx )
    8863              :                                                                         {
    8864              : 
    8865            0 :                                                                                 if(    ( m_aaVrtVecVol[sv] )[iv0]
    8866            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    8867            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8868              :                                                                                 )
    8869              :                                                                                 {
    8870              : 
    8871            0 :                                                                                         expVol = *m_grid.create<Pyramid>(
    8872            0 :                                                                                                                         PyramidDescriptor(sv->vertex(iv0), sv->vertex(iv1),
    8873              :                                                                                                                                 (m_aaVrtVecVol[sv])[iv1],
    8874              :                                                                                                                                 (m_aaVrtVecVol[sv])[iv0],
    8875              :                                                                                                                                 ( m_aaVrtVecVol[sv] )[iv2]));
    8876              : 
    8877            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8878            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8879            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8880              :                                                                                 }
    8881              : 
    8882              :         //                                                                      else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8883              :         //                                                                              && ( m_aaVrtVecVol[sv] )[iv1]
    8884              :         //                                                                      )
    8885              :         //                                                                      {
    8886              :         //
    8887              :         //                                                                      }
    8888              :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8889            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8890              :                                                                                 )
    8891              :                                                                                 {
    8892              : 
    8893            0 :                                                                                         expVol = *m_grid.create<Tetrahedron>(
    8894            0 :                                                                                                                         TetrahedronDescriptor(( m_aaVrtVecVol[sv] )[iv2], sv->vertex(iv1), sv->vertex(iv0),
    8895              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    8896              : 
    8897            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8898            0 :                                                                                                                         TetrahedronDescriptor( sv->vertex(iv1) , sv->vertex(iv1), sv->vertex(iv0),
    8899            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8900              : 
    8901              :                                                                                 }
    8902              :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8903            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8904              :                                                                                 )
    8905              :                                                                                 {
    8906            0 :                                                                                         expVol = *m_grid.create<Tetrahedron>(
    8907            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), ( m_aaVrtVecVol[sv] )[iv0],
    8908              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8909              : 
    8910            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8911            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8912            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8913              :                                                                                 } //
    8914            0 :                                                                                 else if( ( m_aaVrtVecVol[sv] )[iv2]
    8915            0 :                                                                                 )
    8916              :                                                                                 {
    8917            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8918            0 :                                                                                                                         TetrahedronDescriptor( sv->vertex(iv1) , sv->vertex(iv1), sv->vertex(iv0),
    8919              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8920              :                                                                                 }
    8921              : 
    8922              : 
    8923              : 
    8924              :                                                                         }
    8925              : 
    8926              :                                                                 }
    8927              : 
    8928              : 
    8929              :                                                                 std::vector<Face*> const & closedNotNeighbr = ecfsi.spuckVecClosedFracManifElNoNeighbr();
    8930              : 
    8931            0 :                                                                 for( Face * fac : closedNotNeighbr )
    8932              :                                                                 {
    8933            0 :                                                                         if( fac == tFace )
    8934              :                                                                         {
    8935            0 :                                                                                 if( iv0 == indBasVrtx )
    8936              :                                                                                 {
    8937              : 
    8938            0 :                                                                                         if(    ( m_aaVrtVecVol[sv] )[iv0]
    8939            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    8940            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    8941              :                                                                                         )
    8942              :                                                                                         {
    8943              : 
    8944            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8945            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8946              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv0]));
    8947              : 
    8948            0 :                                                                                                 expVolTwo = *m_grid.create<Pyramid>(
    8949            0 :                                                                                                                                 PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv2),
    8950              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8951              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8952            0 :                                                                                                                                         ( m_aaVrtVecVol[sv] )[iv0]));
    8953              : 
    8954              :                                                                                         }
    8955              :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8956            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    8957              :                                                                                         )
    8958              :                                                                                         {
    8959            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8960            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8961              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv0]));
    8962              : 
    8963            0 :                                                                                                 expVolTwo = *m_grid.create<Tetrahedron>(
    8964            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), ( m_aaVrtVecVol[sv] )[iv0],
    8965            0 :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv1]));
    8966              : 
    8967              :                                                                                         }
    8968              : //                                                                                      else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8969              : //                                                                                              && ( m_aaVrtVecVol[sv] )[iv2]
    8970              : //                                                                                      )
    8971              : //                                                                                      {
    8972              : //
    8973              : //                                                                                      }
    8974              : //                                                                                              && ( m_aaVrtVecVol[sv] )[iv2]
    8975              : //                                                                                      )
    8976              : //                                                                                      {
    8977              : //
    8978              : //                                                                                      }
    8979            0 :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8980              :                                                                                         )
    8981              :                                                                                         {
    8982            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8983            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8984              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv0]));
    8985              : 
    8986              : 
    8987              :                                                                                         }
    8988              : 
    8989              : 
    8990              : 
    8991              : 
    8992              :                                                                                 }
    8993              : 
    8994            0 :                                                                                 if( iv1 == indBasVrtx )
    8995              :                                                                                 {
    8996              : 
    8997            0 :                                                                                         if(    ( m_aaVrtVecVol[sv] )[iv0]
    8998            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    8999            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    9000              :                                                                                         )
    9001              :                                                                                         {
    9002            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9003            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9004              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv1]));
    9005              : 
    9006            0 :                                                                                                 expVolTwo = *m_grid.create<Pyramid>(
    9007            0 :                                                                                                                                 PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv0),
    9008              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    9009              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    9010            0 :                                                                                                                                         ( m_aaVrtVecVol[sv] )[iv1]));
    9011              : 
    9012              :                                                                                         }
    9013              :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv0]
    9014            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    9015              :                                                                                         )
    9016              :                                                                                         {
    9017            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9018            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9019              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv1]));
    9020              : 
    9021            0 :                                                                                                 expVolTwo = *m_grid.create<Tetrahedron>(
    9022            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), ( m_aaVrtVecVol[sv] )[iv1], sv->vertex(iv0),
    9023            0 :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv0]));
    9024              : 
    9025              :                                                                                         }
    9026              :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv1]
    9027            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    9028              :                                                                                         )
    9029              :                                                                                         {
    9030            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9031            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9032              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv1]));
    9033              : 
    9034            0 :                                                                                                 expVolTwo = *m_grid.create<Tetrahedron>(
    9035            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), ( m_aaVrtVecVol[sv] )[iv1], sv->vertex(iv0),
    9036            0 :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv2]));
    9037              : 
    9038              :                                                                                         }
    9039              : //                                                                                      else if(    ( m_aaVrtVecVol[sv] )[iv0]
    9040              : //                                                                                              && ( m_aaVrtVecVol[sv] )[iv2]
    9041              : //                                                                                      )
    9042              : //                                                                                      {
    9043              : //
    9044              : //                                                                                      }
    9045            0 :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv1]
    9046              :                                                                                         )
    9047              :                                                                                         {
    9048            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9049            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9050              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv1]));
    9051              : 
    9052              :                                                                                         }
    9053              : 
    9054              : 
    9055              :                                                                                 }
    9056              : 
    9057            0 :                                                                                 if( iv2 == indBasVrtx )
    9058              :                                                                                 {
    9059            0 :                                                                                         if(    ( m_aaVrtVecVol[sv] )[iv0]
    9060            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    9061            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    9062              :                                                                                         )
    9063              :                                                                                         {
    9064              : 
    9065            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9066            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9067              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv2]));
    9068              : 
    9069            0 :                                                                                                 expVolTwo = *m_grid.create<Pyramid>(
    9070            0 :                                                                                                                                 PyramidDescriptor(sv->vertex(iv0), sv->vertex(iv1),
    9071              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    9072              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    9073            0 :                                                                                                                                         ( m_aaVrtVecVol[sv] )[iv2]));
    9074              : 
    9075              :                                                                                         }
    9076              :         //                                                                              else if(    ( m_aaVrtVecVol[sv] )[iv0]
    9077              :         //                                                                                      && ( m_aaVrtVecVol[sv] )[iv1]
    9078              :         //                                                                              )
    9079              :         //                                                                              {
    9080              :         //
    9081              :         //                                                                              }
    9082              :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv1]
    9083            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    9084              :                                                                                         )
    9085              :                                                                                         {
    9086            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9087            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9088              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv2]));
    9089              : 
    9090            0 :                                                                                                 expVolTwo = *m_grid.create<Tetrahedron>(
    9091            0 :                                                                                                                                 TetrahedronDescriptor( ( m_aaVrtVecVol[sv] )[iv2], sv->vertex(iv1), sv->vertex(iv0),
    9092            0 :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv1]));
    9093              : 
    9094              :                                                                                         }
    9095              :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv0]
    9096            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    9097              :                                                                                         )
    9098              :                                                                                         {
    9099            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9100            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9101              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv2]));
    9102              : 
    9103            0 :                                                                                                 expVolTwo = *m_grid.create<Tetrahedron>(
    9104            0 :                                                                                                                                 TetrahedronDescriptor( ( m_aaVrtVecVol[sv] )[iv2], sv->vertex(iv1), sv->vertex(iv0),
    9105            0 :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv0]));
    9106              : 
    9107              :                                                                                         }       //
    9108            0 :                                                                                         else if(   ( m_aaVrtVecVol[sv] )[iv2]
    9109            0 :                                                                                         )
    9110              :                                                                                         {
    9111            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9112            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9113              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv2]));
    9114              : 
    9115              : 
    9116              :                                                                                         }
    9117              : 
    9118              :                                                                                 }
    9119              : 
    9120              :                                                                         }
    9121              :                                                                 }
    9122              : 
    9123              : #if 0
    9124              : 
    9125              :                                                                 if(    ( m_aaVrtVecVol[sv] )[iv0]
    9126              :                                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    9127              :                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    9128              :                                                                 )
    9129              :                                                                 {
    9130              :                                                                         //      create a new prism
    9131              :                                                                         expVol = *m_grid.create<Prism>(
    9132              :                                                                                                         PrismDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9133              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    9134              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    9135              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv0]));
    9136              :                                                                 }
    9137              :                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    9138              :                                                                                  && ( m_aaVrtVecVol[sv] )[iv1]
    9139              :                                                                 )
    9140              :                                                                 {
    9141              :                                                                         //      create a new Pyramid
    9142              :                                                                         expVol = *m_grid.create<Pyramid>(
    9143              :                                                                                                         PyramidDescriptor(sv->vertex(iv0), sv->vertex(iv1),
    9144              :                                                                                                                 (m_aaVrtVecVol[sv])[iv1],
    9145              :                                                                                                                 (m_aaVrtVecVol[sv])[iv0],
    9146              :                                                                                                                 sv->vertex(iv2)));
    9147              :                                                                 }
    9148              :                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv1]
    9149              :                                                                                  && ( m_aaVrtVecVol[sv] )[iv2]
    9150              :                                                                 )
    9151              :                                                                 {
    9152              :                                                                         //      create a new Pyramid
    9153              :                                                                         expVol = *m_grid.create<Pyramid>(
    9154              :                                                                                                         PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv2),
    9155              :                                                                                                                 (m_aaVrtVecVol[sv])[iv2],
    9156              :                                                                                                                 (m_aaVrtVecVol[sv])[iv1],
    9157              :                                                                                                                 sv->vertex(iv0)));
    9158              :                                                                 }
    9159              :                                                                 else if(    (m_aaVrtVecVol[sv])[iv0]
    9160              :                                                                                  && (m_aaVrtVecVol[sv])[iv2]
    9161              :                                                                 )
    9162              :                                                                 {
    9163              :                                                                         //      create a new Pyramid
    9164              :                                                                         expVol = *m_grid.create<Pyramid>(
    9165              :                                                                                                         PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv0),
    9166              :                                                                                                                 (m_aaVrtVecVol[sv])[iv0],
    9167              :                                                                                                                 (m_aaVrtVecVol[sv])[iv2],
    9168              :                                                                                                                 sv->vertex(iv1)));
    9169              :                                                                 }
    9170              :                                                                 else if( ( m_aaVrtVecVol[sv])[iv0] )
    9171              :                                                                 {
    9172              :                                                                         //      create a new Tetrahedron
    9173              :                                                                         expVol = *m_grid.create<Tetrahedron>(
    9174              :                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9175              :                                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    9176              :                                                                 }
    9177              :                                                                 else if( ( m_aaVrtVecVol[sv])[iv1] )
    9178              :                                                                 {
    9179              :                                                                         //      create a new Tetrahedron
    9180              :                                                                         expVol = *m_grid.create<Tetrahedron>(
    9181              :                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9182              :                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    9183              :                                                                 }
    9184              :                                                                 else if( ( m_aaVrtVecVol[sv])[iv2] )
    9185              :                                                                 {
    9186              :                                                                         //      create a new Tetrahedron
    9187              :                                                                         expVol = *m_grid.create<Tetrahedron>(
    9188              :                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9189              :                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    9190              :                                                                 }
    9191              :                                                                 else
    9192              :                                                                 {
    9193              :                                                                         //      Text from SR, still similar:
    9194              :                                                                         //  this code-block should never be entered. If it is entered then
    9195              :                                                                         //      we either selected the wrong faces (this shouldn't happen), or there
    9196              :                                                                         //      are selected faces, which have fracture-boundary-vertices only.
    9197              :                                                                         //      This is the same is if inner fracture edges exists, which are
    9198              :                                                                         //      connected to two boundary vertices.
    9199              :                                                                         //      Since we tried to remove those edges above, something went wrong.
    9200              :                                                                         //      remove the temporary attachments and throw an error
    9201              : 
    9202              :                                                                         UG_LOG("Tetraeder Fehlt eine Loesung " << std::endl);
    9203              :                                                                         detachMarkers();
    9204              :                                                                         throw(UGError("Error in ExpandFractures3d Arte Stasi. Implementation Error."));
    9205              :                                                                         return false;
    9206              :                                                                 }
    9207              : 
    9208              : 
    9209              : #endif
    9210              : 
    9211            0 :                                                         }
    9212              : 
    9213              : 
    9214              :                                                 }
    9215              :                                                 else
    9216              :                                                 {
    9217              :                                                         //      traditionally only tetrahedrons are supported. This section thus raises an error
    9218              :                                                         // Markus tries to implement also Hexahedra
    9219              :                 //                                                                      grid.detach_from_vertices(aVrtVec);
    9220              :                 //                                                              grid.detach_from_volumes(aVrtVec);
    9221              :                 //                                                      grid.detach_from_vertices(aAdjMarker);
    9222              :                 //                                                      grid.detach_from_edges(aAdjMarker);
    9223            0 :                                                         detachMarkers();
    9224            0 :                                                         throw(UGError("Incomplete implementation error in ExpandFractures3d Arte ending crossing clefts."));
    9225              :                                                         return false;
    9226              :                                                 }
    9227              : 
    9228            0 :                                                 if(expVol)
    9229              :                                                 {
    9230              : 
    9231            0 :                                                         IndexType newSubs = m_fracInfosBySubset.at(m_sh.get_subset_index(tFace)).newSubsetIndex;
    9232              : 
    9233            0 :                                                         subsOfNewVolumes.push_back( newSubs );
    9234              : 
    9235            0 :                                                         m_sh.assign_subset(expVol, newSubs);
    9236              : 
    9237            0 :                                                         newFractureVolumes.push_back(expVol);
    9238              :                                                 }
    9239              : 
    9240            0 :                                                 if(expVolTwo)
    9241              :                                                 {
    9242              : 
    9243            0 :                                                         IndexType newSubs = m_fracInfosBySubset.at(m_sh.get_subset_index(tFace)).newSubsetIndex;
    9244              : 
    9245            0 :                                                         subsOfNewVolumes.push_back( newSubs );
    9246              : 
    9247            0 :                                                         m_sh.assign_subset(expVolTwo, newSubs);
    9248              : 
    9249            0 :                                                         newFractureVolumes.push_back(expVolTwo);
    9250              :                                                 }
    9251              : 
    9252              :                                         }
    9253              :                                 }
    9254            0 :                         }
    9255            0 :                 }
    9256              :         }
    9257              : 
    9258              : 
    9259              :         return true;
    9260              : }
    9261              : 
    9262            0 : bool ArteExpandFracs3D::createTheDiamonds()
    9263              : {
    9264            0 :         diamonds::DiamondsEstablish3D establishDiams( m_grid, m_sh, m_vecVolManifVrtxCombiToShrink4Diams );
    9265              : 
    9266              :         UG_LOG("Establishing diamonds" << std::endl);
    9267              : 
    9268            0 :         return establishDiams.createTheDiamonds();
    9269              : 
    9270              : //      IndexType sudos = m_sh.num_subsets();
    9271              : //
    9272              : //      for( auto & vmvcd : m_vecVolManifVrtxCombiToShrink4Diams )
    9273              : //      {
    9274              : //              Volume* vol;
    9275              : //              vmvcd.spuckVol(vol);
    9276              : //
    9277              : //              m_sh.assign_subset(vol, sudos);
    9278              : //      }
    9279              : //
    9280              : //      UG_LOG("Established diamonds" << std::endl);
    9281              : //
    9282              : //
    9283              : //      return true;
    9284            0 : }
    9285              : 
    9286              : } /* namespace arte */
    9287              : 
    9288              : } /* namespace ug */
        

Generated by: LCOV version 2.0-1