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