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