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

Generated by: LCOV version 2.0-1