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